LLVM: lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
25#include
26#include
27#include
28#include
29#include
30
31#define DEBUG_TYPE "mips-elf-object-writer"
32
33using namespace llvm;
34
35namespace {
36
37
38struct MipsRelocationEntry {
40 bool Matched = false;
41
43};
44
46public:
47 MipsELFObjectWriter(uint8_t OSABI, bool HasRelocationAddend, bool Is64);
48
49 ~MipsELFObjectWriter() override = default;
50
51 unsigned getRelocType(const MCFixup &, const MCValue &,
52 bool IsPCRel) const override;
53 bool needsRelocateWithSymbol(const MCValue &, unsigned Type) const override;
54 void sortRelocs(std::vector &Relocs) override;
55};
56
57
58enum FindBestPredicateResult {
59 FindBest_NoMatch = 0,
60 FindBest_Match,
61
62 FindBest_PerfectMatch,
63};
64
65}
66
67
68
69
70template <class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate>
72 OutputIt1 d1, OutputIt2 d2,
76 *d1 = *I;
77 d1++;
78 } else {
79 *d2 = *I;
80 d2++;
81 }
82 }
83
84 return std::make_pair(d1, d2);
85}
86
87
88
89
90
91
92
93
94
95
96template <class InputIt, class UnaryPredicate, class Comparator>
98 Comparator BetterThan) {
99 InputIt Best = Last;
100
103 if (Matched != FindBest_NoMatch) {
104 if (Best == Last || BetterThan(*I, *Best))
105 Best = I;
106 }
107 if (Matched == FindBest_PerfectMatch)
108 break;
109 }
110
111 return Best;
112}
113
114
115
116
117
118
119
120
123 if (Type == ELF::R_MIPS_HI16)
124 return ELF::R_MIPS_LO16;
125 if (Type == ELF::R_MICROMIPS_HI16)
126 return ELF::R_MICROMIPS_LO16;
127 if (Type == ELF::R_MIPS16_HI16)
128 return ELF::R_MIPS16_LO16;
129
131 return ELF::R_MIPS_NONE;
132
133 if (Type == ELF::R_MIPS_GOT16)
134 return ELF::R_MIPS_LO16;
135 if (Type == ELF::R_MICROMIPS_GOT16)
136 return ELF::R_MICROMIPS_LO16;
137 if (Type == ELF::R_MIPS16_GOT16)
138 return ELF::R_MIPS16_LO16;
139
140 return ELF::R_MIPS_NONE;
141}
142
143
144
147 return X.Type == MatchingType && X.Symbol == R.Symbol && X.Addend == R.Addend;
148}
149
150MipsELFObjectWriter::MipsELFObjectWriter(uint8_t OSABI,
151 bool HasRelocationAddend, bool Is64)
153
154unsigned MipsELFObjectWriter::getRelocType(const MCFixup &Fixup,
156 bool IsPCRel) const {
157
159 switch (Target.getSpecifier()) {
168 if (auto *SA = const_cast<MCSymbol *>(Target.getAddSym()))
169 static_cast<MCSymbolELF *>(SA)->setType(ELF::STT_TLS);
170 break;
171 default:
172 break;
173 }
174
175 switch (Kind) {
177 return ELF::R_MIPS_NONE;
179 reportError(Fixup.getLoc(), "MIPS does not support one byte relocations");
180 return ELF::R_MIPS_NONE;
183 return IsPCRel ? ELF::R_MIPS_PC16 : ELF::R_MIPS_16;
186 return IsPCRel ? ELF::R_MIPS_PC32 : ELF::R_MIPS_32;
189 return IsPCRel
190 ? setRTypes(ELF::R_MIPS_PC32, ELF::R_MIPS_64, ELF::R_MIPS_NONE)
191 : (unsigned)ELF::R_MIPS_64;
192 }
193
194 if (IsPCRel) {
195 switch (Kind) {
198 return ELF::R_MIPS_PC16;
200 return ELF::R_MICROMIPS_PC7_S1;
202 return ELF::R_MICROMIPS_PC10_S1;
204 return ELF::R_MICROMIPS_PC16_S1;
206 return ELF::R_MICROMIPS_PC26_S1;
208 return ELF::R_MICROMIPS_PC19_S2;
210 return ELF::R_MICROMIPS_PC18_S3;
212 return ELF::R_MICROMIPS_PC21_S1;
214 return ELF::R_MIPS_PC19_S2;
216 return ELF::R_MIPS_PC18_S3;
218 return ELF::R_MIPS_PC21_S2;
220 return ELF::R_MIPS_PC26_S2;
222 return ELF::R_MIPS_PCHI16;
224 return ELF::R_MIPS_PCLO16;
225 }
226
228 }
229
230 switch (Kind) {
232 return ELF::R_MIPS_TLS_DTPREL32;
234 return ELF::R_MIPS_TLS_DTPREL64;
236 return ELF::R_MIPS_TLS_TPREL32;
238 return ELF::R_MIPS_TLS_TPREL64;
240 return setRTypes(ELF::R_MIPS_GPREL32,
241 is64Bit() ? ELF::R_MIPS_64 : ELF::R_MIPS_NONE,
242 ELF::R_MIPS_NONE);
244 return ELF::R_MIPS_GPREL16;
246 return ELF::R_MIPS_26;
248 return ELF::R_MIPS_CALL16;
250 return ELF::R_MIPS_GOT16;
252 return ELF::R_MIPS_HI16;
254 return ELF::R_MIPS_LO16;
256 return ELF::R_MIPS_TLS_GD;
258 return ELF::R_MIPS_TLS_GOTTPREL;
260 return ELF::R_MIPS_TLS_TPREL_HI16;
262 return ELF::R_MIPS_TLS_TPREL_LO16;
264 return ELF::R_MIPS_TLS_LDM;
266 return ELF::R_MIPS_TLS_DTPREL_HI16;
268 return ELF::R_MIPS_TLS_DTPREL_LO16;
270 return ELF::R_MIPS_GOT_PAGE;
272 return ELF::R_MIPS_GOT_OFST;
274 return ELF::R_MIPS_GOT_DISP;
276 return setRTypes(ELF::R_MIPS_GPREL16, ELF::R_MIPS_SUB, ELF::R_MIPS_HI16);
278 return setRTypes(ELF::R_MICROMIPS_GPREL16, ELF::R_MICROMIPS_SUB,
279 ELF::R_MICROMIPS_HI16);
281 return setRTypes(ELF::R_MIPS_GPREL16, ELF::R_MIPS_SUB, ELF::R_MIPS_LO16);
283 return setRTypes(ELF::R_MICROMIPS_GPREL16, ELF::R_MICROMIPS_SUB,
284 ELF::R_MICROMIPS_LO16);
286 return ELF::R_MIPS_HIGHER;
288 return ELF::R_MIPS_HIGHEST;
290 return ELF::R_MIPS_SUB;
292 return ELF::R_MIPS_GOT_HI16;
294 return ELF::R_MIPS_GOT_LO16;
296 return ELF::R_MIPS_CALL_HI16;
298 return ELF::R_MIPS_CALL_LO16;
300 return ELF::R_MICROMIPS_26_S1;
302 return ELF::R_MICROMIPS_HI16;
304 return ELF::R_MICROMIPS_LO16;
306 return ELF::R_MICROMIPS_GOT16;
308 return ELF::R_MICROMIPS_CALL16;
310 return ELF::R_MICROMIPS_GOT_DISP;
312 return ELF::R_MICROMIPS_GOT_PAGE;
314 return ELF::R_MICROMIPS_GOT_OFST;
316 return ELF::R_MICROMIPS_TLS_GD;
318 return ELF::R_MICROMIPS_TLS_LDM;
320 return ELF::R_MICROMIPS_TLS_DTPREL_HI16;
322 return ELF::R_MICROMIPS_TLS_DTPREL_LO16;
324 return ELF::R_MICROMIPS_TLS_GOTTPREL;
326 return ELF::R_MICROMIPS_TLS_TPREL_HI16;
328 return ELF::R_MICROMIPS_TLS_TPREL_LO16;
330 return ELF::R_MICROMIPS_SUB;
332 return ELF::R_MICROMIPS_HIGHER;
334 return ELF::R_MICROMIPS_HIGHEST;
336 return ELF::R_MIPS_JALR;
338 return ELF::R_MICROMIPS_JALR;
339 }
340
342 return ELF::R_MIPS_NONE;
343}
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380void MipsELFObjectWriter::sortRelocs(std::vector &Relocs) {
381
382
383
384 if (hasRelocationAddend())
385 return;
386
387
388
390 Relocs, [](const ELFRelocationEntry &A, const ELFRelocationEntry &B) {
391 return A.Offset < B.Offset;
392 });
393
394
395
396 std::list Sorted;
397 SmallVector<std::list::iterator, 0> Hi16;
398 for (auto &R : Relocs) {
399 Sorted.push_back(R);
401 Hi16.push_back(std::prev(Sorted.end()));
402 }
403
404 for (auto I : Hi16) {
407
408 if (std::next(I) != Sorted.end() &&
410 continue;
411
412
413
414
415
416
417
418 auto Best = Sorted.end();
419 for (auto J = Sorted.begin(); J != Sorted.end(); ++J) {
420 auto &R1 = J->R;
421 if (R1.Type == MatchingType && R.Symbol == R1.Symbol &&
422 R.Addend <= R1.Addend &&
423 (Best == Sorted.end() || R1.Addend < Best->R.Addend ||
424 (!Best->Matched && R1.Addend == Best->R.Addend)))
425 Best = J;
426 }
427 if (Best != Sorted.end() && R.Addend == Best->R.Addend)
428 Best->Matched = true;
429
430
431
432 Sorted.splice(Best, Sorted, I);
433 }
434
435 assert(Relocs.size() == Sorted.size() && "Some relocs were not consumed");
436
437
438 unsigned CopyTo = 0;
439 for (const auto &R : Sorted)
440 Relocs[CopyTo++] = R.R;
441}
442
443bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCValue &V,
444 unsigned Type) const {
445
446
448 return needsRelocateWithSymbol(V, Type & 0xff) ||
449 needsRelocateWithSymbol(V, (Type >> 8) & 0xff) ||
450 needsRelocateWithSymbol(V, (Type >> 16) & 0xff);
451
452 auto *Sym = static_cast<const MCSymbolELF *>(V.getAddSym());
453 switch (Type) {
454 default:
457 return true;
458
459
460 case ELF::R_MIPS_NONE:
461 return false;
462
463
464
465
466
467
468
469
470 case ELF::R_MIPS_GOT16:
471 case ELF::R_MIPS16_GOT16:
472 case ELF::R_MICROMIPS_GOT16:
473 case ELF::R_MIPS_HIGHER:
474 case ELF::R_MIPS_HIGHEST:
475 case ELF::R_MIPS_HI16:
476 case ELF::R_MIPS16_HI16:
477 case ELF::R_MICROMIPS_HI16:
478 case ELF::R_MIPS_LO16:
479 case ELF::R_MIPS16_LO16:
480 case ELF::R_MICROMIPS_LO16:
481
482
483
485 return true;
486 return false;
487
488 case ELF::R_MIPS_GOT_PAGE:
489 case ELF::R_MICROMIPS_GOT_PAGE:
490 case ELF::R_MIPS_GOT_OFST:
491 case ELF::R_MICROMIPS_GOT_OFST:
492 case ELF::R_MIPS_16:
493 case ELF::R_MIPS_32:
494 case ELF::R_MIPS_GPREL32:
496 return true;
497 [[fallthrough]];
498 case ELF::R_MIPS_26:
499 case ELF::R_MIPS_64:
500 case ELF::R_MIPS_GPREL16:
501 case ELF::R_MIPS_PC16:
502 case ELF::R_MIPS_SUB:
503 return false;
504
505
506
507 case ELF::R_MIPS_REL32:
508 case ELF::R_MIPS_LITERAL:
509 case ELF::R_MIPS_CALL16:
510 case ELF::R_MIPS_SHIFT5:
511 case ELF::R_MIPS_SHIFT6:
512 case ELF::R_MIPS_GOT_DISP:
513 case ELF::R_MIPS_GOT_HI16:
514 case ELF::R_MIPS_GOT_LO16:
515 case ELF::R_MIPS_INSERT_A:
516 case ELF::R_MIPS_INSERT_B:
517 case ELF::R_MIPS_DELETE:
518 case ELF::R_MIPS_CALL_HI16:
519 case ELF::R_MIPS_CALL_LO16:
520 case ELF::R_MIPS_SCN_DISP:
521 case ELF::R_MIPS_REL16:
522 case ELF::R_MIPS_ADD_IMMEDIATE:
523 case ELF::R_MIPS_PJUMP:
524 case ELF::R_MIPS_RELGOT:
525 case ELF::R_MIPS_JALR:
526 case ELF::R_MIPS_TLS_DTPMOD32:
527 case ELF::R_MIPS_TLS_DTPREL32:
528 case ELF::R_MIPS_TLS_DTPMOD64:
529 case ELF::R_MIPS_TLS_DTPREL64:
530 case ELF::R_MIPS_TLS_GD:
531 case ELF::R_MIPS_TLS_LDM:
532 case ELF::R_MIPS_TLS_DTPREL_HI16:
533 case ELF::R_MIPS_TLS_DTPREL_LO16:
534 case ELF::R_MIPS_TLS_GOTTPREL:
535 case ELF::R_MIPS_TLS_TPREL32:
536 case ELF::R_MIPS_TLS_TPREL64:
537 case ELF::R_MIPS_TLS_TPREL_HI16:
538 case ELF::R_MIPS_TLS_TPREL_LO16:
539 case ELF::R_MIPS_GLOB_DAT:
540 case ELF::R_MIPS_PC21_S2:
541 case ELF::R_MIPS_PC26_S2:
542 case ELF::R_MIPS_PC18_S3:
543 case ELF::R_MIPS_PC19_S2:
544 case ELF::R_MIPS_PCHI16:
545 case ELF::R_MIPS_PCLO16:
546 case ELF::R_MIPS_COPY:
547 case ELF::R_MIPS_JUMP_SLOT:
548 case ELF::R_MIPS_NUM:
549 case ELF::R_MIPS_PC32:
550 case ELF::R_MIPS_EH:
551 case ELF::R_MICROMIPS_26_S1:
552 case ELF::R_MICROMIPS_GPREL16:
553 case ELF::R_MICROMIPS_LITERAL:
554 case ELF::R_MICROMIPS_PC7_S1:
555 case ELF::R_MICROMIPS_PC10_S1:
556 case ELF::R_MICROMIPS_PC16_S1:
557 case ELF::R_MICROMIPS_CALL16:
558 case ELF::R_MICROMIPS_GOT_DISP:
559 case ELF::R_MICROMIPS_GOT_HI16:
560 case ELF::R_MICROMIPS_GOT_LO16:
561 case ELF::R_MICROMIPS_SUB:
562 case ELF::R_MICROMIPS_HIGHER:
563 case ELF::R_MICROMIPS_HIGHEST:
564 case ELF::R_MICROMIPS_CALL_HI16:
565 case ELF::R_MICROMIPS_CALL_LO16:
566 case ELF::R_MICROMIPS_SCN_DISP:
567 case ELF::R_MICROMIPS_JALR:
568 case ELF::R_MICROMIPS_HI0_LO16:
569 case ELF::R_MICROMIPS_TLS_GD:
570 case ELF::R_MICROMIPS_TLS_LDM:
571 case ELF::R_MICROMIPS_TLS_DTPREL_HI16:
572 case ELF::R_MICROMIPS_TLS_DTPREL_LO16:
573 case ELF::R_MICROMIPS_TLS_GOTTPREL:
574 case ELF::R_MICROMIPS_TLS_TPREL_HI16:
575 case ELF::R_MICROMIPS_TLS_TPREL_LO16:
576 case ELF::R_MICROMIPS_GPREL7_S2:
577 case ELF::R_MICROMIPS_PC23_S2:
578 case ELF::R_MICROMIPS_PC21_S1:
579 case ELF::R_MICROMIPS_PC26_S1:
580 case ELF::R_MICROMIPS_PC18_S3:
581 case ELF::R_MICROMIPS_PC19_S2:
582 return true;
583
584
585
586 case ELF::R_MIPS16_26:
587 case ELF::R_MIPS16_GPREL:
588 case ELF::R_MIPS16_CALL16:
589 case ELF::R_MIPS16_TLS_GD:
590 case ELF::R_MIPS16_TLS_LDM:
591 case ELF::R_MIPS16_TLS_DTPREL_HI16:
592 case ELF::R_MIPS16_TLS_DTPREL_LO16:
593 case ELF::R_MIPS16_TLS_GOTTPREL:
594 case ELF::R_MIPS16_TLS_TPREL_HI16:
595 case ELF::R_MIPS16_TLS_TPREL_LO16:
597 return true;
598 }
599}
600
601std::unique_ptr
604 bool IsN64 = TT.isArch64Bit() && !IsN32;
605 bool HasRelocationAddend = TT.isArch64Bit();
606 return std::make_unique(OSABI, HasRelocationAddend,
607 IsN64);
608}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static Error reportError(StringRef Message)
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isMatchingReloc(unsigned MatchingType, const ELFRelocationEntry &R, const ELFRelocationEntry &X)
Definition MipsELFObjectWriter.cpp:145
static InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate, Comparator BetterThan)
Find the best match in the range [First, Last).
Definition MipsELFObjectWriter.cpp:97
static std::pair< OutputIt1, OutputIt2 > copy_if_else(InputIt First, InputIt Last, OutputIt1 d1, OutputIt2 d2, UnaryPredicate Predicate)
Copy elements in the range [First, Last) to d1 when the predicate is true or d2 when the predicate is...
Definition MipsELFObjectWriter.cpp:71
static unsigned getMatchingLoType(const ELFRelocationEntry &Reloc)
Determine the low relocation that matches the given relocation.
Definition MipsELFObjectWriter.cpp:121
PowerPC TLS Dynamic Call Fixup
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static bool is64Bit(const char *name)
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
void push_back(const T &Elt)
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
The instances of the Type class are immutable: once they are created, they are never changed.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ fixup_MICROMIPS_TLS_TPREL_LO16
@ fixup_MICROMIPS_GOT_PAGE
@ fixup_MICROMIPS_PC16_S1
@ fixup_MICROMIPS_TLS_TPREL_HI16
@ fixup_MICROMIPS_PC21_S1
@ fixup_MICROMIPS_GPOFF_LO
@ fixup_MICROMIPS_PC19_S2
@ fixup_MICROMIPS_TLS_LDM
@ fixup_MICROMIPS_GOT_OFST
@ fixup_MICROMIPS_TLS_DTPREL_HI16
@ fixup_MICROMIPS_PC10_S1
@ fixup_MICROMIPS_HIGHEST
@ fixup_MICROMIPS_GOT_DISP
@ fixup_MICROMIPS_PC18_S3
@ fixup_MICROMIPS_PC26_S1
@ fixup_MICROMIPS_GOTTPREL
@ fixup_MICROMIPS_TLS_DTPREL_LO16
@ fixup_Mips_Branch_PCRel
@ fixup_MICROMIPS_GPOFF_HI
This is an optimization pass for GlobalISel generic memory operations.
void stable_sort(R &&Range)
std::unique_ptr< MCObjectTargetWriter > createMipsELFObjectWriter(const Triple &TT, bool IsN32)
Construct a Mips ELF object writer.
Definition MipsELFObjectWriter.cpp:602
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ FK_Data_8
A eight-byte fixup.
@ FK_Data_1
A one-byte fixup.
@ FK_Data_4
A four-byte fixup.
@ FK_Data_2
A two-byte fixup.