xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===-- MipsELFObjectWriter.cpp - Mips ELF Writer -------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MCTargetDesc/MipsFixupKinds.h"
100b57cec5SDimitry Andric #include "MCTargetDesc/MipsMCTargetDesc.h"
110b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
120b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCFixup.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCSymbolELF.h"
180b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
190b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
200b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
210b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
220b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
230b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
240b57cec5SDimitry Andric #include <algorithm>
250b57cec5SDimitry Andric #include <cassert>
260b57cec5SDimitry Andric #include <cstdint>
270b57cec5SDimitry Andric #include <iterator>
280b57cec5SDimitry Andric #include <list>
290b57cec5SDimitry Andric #include <utility>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric #define DEBUG_TYPE "mips-elf-object-writer"
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric using namespace llvm;
340b57cec5SDimitry Andric 
350b57cec5SDimitry Andric namespace {
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric /// Holds additional information needed by the relocation ordering algorithm.
380b57cec5SDimitry Andric struct MipsRelocationEntry {
390b57cec5SDimitry Andric   const ELFRelocationEntry R; ///< The relocation.
400b57cec5SDimitry Andric   bool Matched = false;       ///< Is this relocation part of a match.
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric   MipsRelocationEntry(const ELFRelocationEntry &R) : R(R) {}
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric   void print(raw_ostream &Out) const {
450b57cec5SDimitry Andric     R.print(Out);
460b57cec5SDimitry Andric     Out << ", Matched=" << Matched;
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric };
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric #ifndef NDEBUG
510b57cec5SDimitry Andric raw_ostream &operator<<(raw_ostream &OS, const MipsRelocationEntry &RHS) {
520b57cec5SDimitry Andric   RHS.print(OS);
530b57cec5SDimitry Andric   return OS;
540b57cec5SDimitry Andric }
550b57cec5SDimitry Andric #endif
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric class MipsELFObjectWriter : public MCELFObjectTargetWriter {
580b57cec5SDimitry Andric public:
590b57cec5SDimitry Andric   MipsELFObjectWriter(uint8_t OSABI, bool HasRelocationAddend, bool Is64);
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   ~MipsELFObjectWriter() override = default;
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
640b57cec5SDimitry Andric                         const MCFixup &Fixup, bool IsPCRel) const override;
655f757f3fSDimitry Andric   bool needsRelocateWithSymbol(const MCValue &Val, const MCSymbol &Sym,
660b57cec5SDimitry Andric                                unsigned Type) const override;
670b57cec5SDimitry Andric   void sortRelocs(const MCAssembler &Asm,
680b57cec5SDimitry Andric                   std::vector<ELFRelocationEntry> &Relocs) override;
690b57cec5SDimitry Andric };
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric /// The possible results of the Predicate function used by find_best.
720b57cec5SDimitry Andric enum FindBestPredicateResult {
730b57cec5SDimitry Andric   FindBest_NoMatch = 0,  ///< The current element is not a match.
740b57cec5SDimitry Andric   FindBest_Match,        ///< The current element is a match but better ones are
750b57cec5SDimitry Andric                          ///  possible.
760b57cec5SDimitry Andric   FindBest_PerfectMatch, ///< The current element is an unbeatable match.
770b57cec5SDimitry Andric };
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric } // end anonymous namespace
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric /// Copy elements in the range [First, Last) to d1 when the predicate is true or
820b57cec5SDimitry Andric /// d2 when the predicate is false. This is essentially both std::copy_if and
830b57cec5SDimitry Andric /// std::remove_copy_if combined into a single pass.
840b57cec5SDimitry Andric template <class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate>
850b57cec5SDimitry Andric static std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last,
860b57cec5SDimitry Andric                                                     OutputIt1 d1, OutputIt2 d2,
870b57cec5SDimitry Andric                                                     UnaryPredicate Predicate) {
880b57cec5SDimitry Andric   for (InputIt I = First; I != Last; ++I) {
890b57cec5SDimitry Andric     if (Predicate(*I)) {
900b57cec5SDimitry Andric       *d1 = *I;
910b57cec5SDimitry Andric       d1++;
920b57cec5SDimitry Andric     } else {
930b57cec5SDimitry Andric       *d2 = *I;
940b57cec5SDimitry Andric       d2++;
950b57cec5SDimitry Andric     }
960b57cec5SDimitry Andric   }
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   return std::make_pair(d1, d2);
990b57cec5SDimitry Andric }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric /// Find the best match in the range [First, Last).
1020b57cec5SDimitry Andric ///
1030b57cec5SDimitry Andric /// An element matches when Predicate(X) returns FindBest_Match or
1040b57cec5SDimitry Andric /// FindBest_PerfectMatch. A value of FindBest_PerfectMatch also terminates
1050b57cec5SDimitry Andric /// the search. BetterThan(A, B) is a comparator that returns true when A is a
1060b57cec5SDimitry Andric /// better match than B. The return value is the position of the best match.
1070b57cec5SDimitry Andric ///
1080b57cec5SDimitry Andric /// This is similar to std::find_if but finds the best of multiple possible
1090b57cec5SDimitry Andric /// matches.
1100b57cec5SDimitry Andric template <class InputIt, class UnaryPredicate, class Comparator>
1110b57cec5SDimitry Andric static InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate,
1120b57cec5SDimitry Andric                          Comparator BetterThan) {
1130b57cec5SDimitry Andric   InputIt Best = Last;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   for (InputIt I = First; I != Last; ++I) {
1160b57cec5SDimitry Andric     unsigned Matched = Predicate(*I);
1170b57cec5SDimitry Andric     if (Matched != FindBest_NoMatch) {
1180b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << std::distance(First, I) << " is a match (";
1190b57cec5SDimitry Andric                  I->print(dbgs()); dbgs() << ")\n");
1200b57cec5SDimitry Andric       if (Best == Last || BetterThan(*I, *Best)) {
1210b57cec5SDimitry Andric         LLVM_DEBUG(dbgs() << ".. and it beats the last one\n");
1220b57cec5SDimitry Andric         Best = I;
1230b57cec5SDimitry Andric       }
1240b57cec5SDimitry Andric     }
1250b57cec5SDimitry Andric     if (Matched == FindBest_PerfectMatch) {
1260b57cec5SDimitry Andric       LLVM_DEBUG(dbgs() << ".. and it is unbeatable\n");
1270b57cec5SDimitry Andric       break;
1280b57cec5SDimitry Andric     }
1290b57cec5SDimitry Andric   }
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   return Best;
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric /// Determine the low relocation that matches the given relocation.
1350b57cec5SDimitry Andric /// If the relocation does not need a low relocation then the return value
1360b57cec5SDimitry Andric /// is ELF::R_MIPS_NONE.
1370b57cec5SDimitry Andric ///
1380b57cec5SDimitry Andric /// The relocations that need a matching low part are
1390b57cec5SDimitry Andric /// R_(MIPS|MICROMIPS|MIPS16)_HI16 for all symbols and
1400b57cec5SDimitry Andric /// R_(MIPS|MICROMIPS|MIPS16)_GOT16 for local symbols only.
1410b57cec5SDimitry Andric static unsigned getMatchingLoType(const ELFRelocationEntry &Reloc) {
1420b57cec5SDimitry Andric   unsigned Type = Reloc.Type;
1430b57cec5SDimitry Andric   if (Type == ELF::R_MIPS_HI16)
1440b57cec5SDimitry Andric     return ELF::R_MIPS_LO16;
1450b57cec5SDimitry Andric   if (Type == ELF::R_MICROMIPS_HI16)
1460b57cec5SDimitry Andric     return ELF::R_MICROMIPS_LO16;
1470b57cec5SDimitry Andric   if (Type == ELF::R_MIPS16_HI16)
1480b57cec5SDimitry Andric     return ELF::R_MIPS16_LO16;
1490b57cec5SDimitry Andric 
1500b57cec5SDimitry Andric   if (Reloc.OriginalSymbol &&
1510b57cec5SDimitry Andric       Reloc.OriginalSymbol->getBinding() != ELF::STB_LOCAL)
1520b57cec5SDimitry Andric     return ELF::R_MIPS_NONE;
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   if (Type == ELF::R_MIPS_GOT16)
1550b57cec5SDimitry Andric     return ELF::R_MIPS_LO16;
1560b57cec5SDimitry Andric   if (Type == ELF::R_MICROMIPS_GOT16)
1570b57cec5SDimitry Andric     return ELF::R_MICROMIPS_LO16;
1580b57cec5SDimitry Andric   if (Type == ELF::R_MIPS16_GOT16)
1590b57cec5SDimitry Andric     return ELF::R_MIPS16_LO16;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   return ELF::R_MIPS_NONE;
1620b57cec5SDimitry Andric }
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric /// Determine whether a relocation (X) matches the one given in R.
1650b57cec5SDimitry Andric ///
1660b57cec5SDimitry Andric /// A relocation matches if:
1670b57cec5SDimitry Andric /// - It's type matches that of a corresponding low part. This is provided in
1680b57cec5SDimitry Andric ///   MatchingType for efficiency.
1690b57cec5SDimitry Andric /// - It's based on the same symbol.
1700b57cec5SDimitry Andric /// - It's offset of greater or equal to that of the one given in R.
1710b57cec5SDimitry Andric ///   It should be noted that this rule assumes the programmer does not use
1720b57cec5SDimitry Andric ///   offsets that exceed the alignment of the symbol. The carry-bit will be
1730b57cec5SDimitry Andric ///   incorrect if this is not true.
1740b57cec5SDimitry Andric ///
1750b57cec5SDimitry Andric /// A matching relocation is unbeatable if:
1760b57cec5SDimitry Andric /// - It is not already involved in a match.
1770b57cec5SDimitry Andric /// - It's offset is exactly that of the one given in R.
1780b57cec5SDimitry Andric static FindBestPredicateResult isMatchingReloc(const MipsRelocationEntry &X,
1790b57cec5SDimitry Andric                                                const ELFRelocationEntry &R,
1800b57cec5SDimitry Andric                                                unsigned MatchingType) {
1810b57cec5SDimitry Andric   if (X.R.Type == MatchingType && X.R.OriginalSymbol == R.OriginalSymbol) {
1820b57cec5SDimitry Andric     if (!X.Matched &&
1830b57cec5SDimitry Andric         X.R.OriginalAddend == R.OriginalAddend)
1840b57cec5SDimitry Andric       return FindBest_PerfectMatch;
1850b57cec5SDimitry Andric     else if (X.R.OriginalAddend >= R.OriginalAddend)
1860b57cec5SDimitry Andric       return FindBest_Match;
1870b57cec5SDimitry Andric   }
1880b57cec5SDimitry Andric   return FindBest_NoMatch;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric /// Determine whether Candidate or PreviousBest is the better match.
1920b57cec5SDimitry Andric /// The return value is true if Candidate is the better match.
1930b57cec5SDimitry Andric ///
1940b57cec5SDimitry Andric /// A matching relocation is a better match if:
1950b57cec5SDimitry Andric /// - It has a smaller addend.
1960b57cec5SDimitry Andric /// - It is not already involved in a match.
1970b57cec5SDimitry Andric static bool compareMatchingRelocs(const MipsRelocationEntry &Candidate,
1980b57cec5SDimitry Andric                                   const MipsRelocationEntry &PreviousBest) {
1990b57cec5SDimitry Andric   if (Candidate.R.OriginalAddend != PreviousBest.R.OriginalAddend)
2000b57cec5SDimitry Andric     return Candidate.R.OriginalAddend < PreviousBest.R.OriginalAddend;
2010b57cec5SDimitry Andric   return PreviousBest.Matched && !Candidate.Matched;
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric #ifndef NDEBUG
2050b57cec5SDimitry Andric /// Print all the relocations.
2060b57cec5SDimitry Andric template <class Container>
2070b57cec5SDimitry Andric static void dumpRelocs(const char *Prefix, const Container &Relocs) {
2080b57cec5SDimitry Andric   for (const auto &R : Relocs)
2090b57cec5SDimitry Andric     dbgs() << Prefix << R << "\n";
2100b57cec5SDimitry Andric }
2110b57cec5SDimitry Andric #endif
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric MipsELFObjectWriter::MipsELFObjectWriter(uint8_t OSABI,
2140b57cec5SDimitry Andric                                          bool HasRelocationAddend, bool Is64)
2150b57cec5SDimitry Andric     : MCELFObjectTargetWriter(Is64, OSABI, ELF::EM_MIPS, HasRelocationAddend) {}
2160b57cec5SDimitry Andric 
2170b57cec5SDimitry Andric unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx,
2180b57cec5SDimitry Andric                                            const MCValue &Target,
2190b57cec5SDimitry Andric                                            const MCFixup &Fixup,
2200b57cec5SDimitry Andric                                            bool IsPCRel) const {
2210b57cec5SDimitry Andric   // Determine the type of the relocation.
2228bcb0991SDimitry Andric   unsigned Kind = Fixup.getTargetKind();
22381ad6265SDimitry Andric   if (Kind >= FirstLiteralRelocationKind)
22481ad6265SDimitry Andric     return Kind - FirstLiteralRelocationKind;
2250b57cec5SDimitry Andric 
2260b57cec5SDimitry Andric   switch (Kind) {
2270b57cec5SDimitry Andric   case FK_NONE:
2280b57cec5SDimitry Andric     return ELF::R_MIPS_NONE;
2290b57cec5SDimitry Andric   case FK_Data_1:
2300b57cec5SDimitry Andric     Ctx.reportError(Fixup.getLoc(),
2310b57cec5SDimitry Andric                     "MIPS does not support one byte relocations");
2320b57cec5SDimitry Andric     return ELF::R_MIPS_NONE;
2330b57cec5SDimitry Andric   case Mips::fixup_Mips_16:
2340b57cec5SDimitry Andric   case FK_Data_2:
2350b57cec5SDimitry Andric     return IsPCRel ? ELF::R_MIPS_PC16 : ELF::R_MIPS_16;
2360b57cec5SDimitry Andric   case Mips::fixup_Mips_32:
2370b57cec5SDimitry Andric   case FK_Data_4:
2380b57cec5SDimitry Andric     return IsPCRel ? ELF::R_MIPS_PC32 : ELF::R_MIPS_32;
2395ffd83dbSDimitry Andric   case Mips::fixup_Mips_64:
2405ffd83dbSDimitry Andric   case FK_Data_8:
2415ffd83dbSDimitry Andric     return IsPCRel
2425ffd83dbSDimitry Andric                ? setRTypes(ELF::R_MIPS_PC32, ELF::R_MIPS_64, ELF::R_MIPS_NONE)
2435ffd83dbSDimitry Andric                : (unsigned)ELF::R_MIPS_64;
2440b57cec5SDimitry Andric   }
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   if (IsPCRel) {
2470b57cec5SDimitry Andric     switch (Kind) {
2480b57cec5SDimitry Andric     case Mips::fixup_Mips_Branch_PCRel:
2490b57cec5SDimitry Andric     case Mips::fixup_Mips_PC16:
2500b57cec5SDimitry Andric       return ELF::R_MIPS_PC16;
2510b57cec5SDimitry Andric     case Mips::fixup_MICROMIPS_PC7_S1:
2520b57cec5SDimitry Andric       return ELF::R_MICROMIPS_PC7_S1;
2530b57cec5SDimitry Andric     case Mips::fixup_MICROMIPS_PC10_S1:
2540b57cec5SDimitry Andric       return ELF::R_MICROMIPS_PC10_S1;
2550b57cec5SDimitry Andric     case Mips::fixup_MICROMIPS_PC16_S1:
2560b57cec5SDimitry Andric       return ELF::R_MICROMIPS_PC16_S1;
2570b57cec5SDimitry Andric     case Mips::fixup_MICROMIPS_PC26_S1:
2580b57cec5SDimitry Andric       return ELF::R_MICROMIPS_PC26_S1;
2590b57cec5SDimitry Andric     case Mips::fixup_MICROMIPS_PC19_S2:
2600b57cec5SDimitry Andric       return ELF::R_MICROMIPS_PC19_S2;
2610b57cec5SDimitry Andric     case Mips::fixup_MICROMIPS_PC18_S3:
2620b57cec5SDimitry Andric       return ELF::R_MICROMIPS_PC18_S3;
2630b57cec5SDimitry Andric     case Mips::fixup_MICROMIPS_PC21_S1:
2640b57cec5SDimitry Andric       return ELF::R_MICROMIPS_PC21_S1;
2650b57cec5SDimitry Andric     case Mips::fixup_MIPS_PC19_S2:
2660b57cec5SDimitry Andric       return ELF::R_MIPS_PC19_S2;
2670b57cec5SDimitry Andric     case Mips::fixup_MIPS_PC18_S3:
2680b57cec5SDimitry Andric       return ELF::R_MIPS_PC18_S3;
2690b57cec5SDimitry Andric     case Mips::fixup_MIPS_PC21_S2:
2700b57cec5SDimitry Andric       return ELF::R_MIPS_PC21_S2;
2710b57cec5SDimitry Andric     case Mips::fixup_MIPS_PC26_S2:
2720b57cec5SDimitry Andric       return ELF::R_MIPS_PC26_S2;
2730b57cec5SDimitry Andric     case Mips::fixup_MIPS_PCHI16:
2740b57cec5SDimitry Andric       return ELF::R_MIPS_PCHI16;
2750b57cec5SDimitry Andric     case Mips::fixup_MIPS_PCLO16:
2760b57cec5SDimitry Andric       return ELF::R_MIPS_PCLO16;
2770b57cec5SDimitry Andric     }
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric     llvm_unreachable("invalid PC-relative fixup kind!");
2800b57cec5SDimitry Andric   }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   switch (Kind) {
2830b57cec5SDimitry Andric   case FK_DTPRel_4:
2840b57cec5SDimitry Andric     return ELF::R_MIPS_TLS_DTPREL32;
2850b57cec5SDimitry Andric   case FK_DTPRel_8:
2860b57cec5SDimitry Andric     return ELF::R_MIPS_TLS_DTPREL64;
2870b57cec5SDimitry Andric   case FK_TPRel_4:
2880b57cec5SDimitry Andric     return ELF::R_MIPS_TLS_TPREL32;
2890b57cec5SDimitry Andric   case FK_TPRel_8:
2900b57cec5SDimitry Andric     return ELF::R_MIPS_TLS_TPREL64;
2910b57cec5SDimitry Andric   case FK_GPRel_4:
2925ffd83dbSDimitry Andric     return setRTypes(ELF::R_MIPS_GPREL32,
2935ffd83dbSDimitry Andric                      is64Bit() ? ELF::R_MIPS_64 : ELF::R_MIPS_NONE,
2945ffd83dbSDimitry Andric                      ELF::R_MIPS_NONE);
2950b57cec5SDimitry Andric   case Mips::fixup_Mips_GPREL16:
2960b57cec5SDimitry Andric     return ELF::R_MIPS_GPREL16;
2970b57cec5SDimitry Andric   case Mips::fixup_Mips_26:
2980b57cec5SDimitry Andric     return ELF::R_MIPS_26;
2990b57cec5SDimitry Andric   case Mips::fixup_Mips_CALL16:
3000b57cec5SDimitry Andric     return ELF::R_MIPS_CALL16;
3010b57cec5SDimitry Andric   case Mips::fixup_Mips_GOT:
3020b57cec5SDimitry Andric     return ELF::R_MIPS_GOT16;
3030b57cec5SDimitry Andric   case Mips::fixup_Mips_HI16:
3040b57cec5SDimitry Andric     return ELF::R_MIPS_HI16;
3050b57cec5SDimitry Andric   case Mips::fixup_Mips_LO16:
3060b57cec5SDimitry Andric     return ELF::R_MIPS_LO16;
3070b57cec5SDimitry Andric   case Mips::fixup_Mips_TLSGD:
3080b57cec5SDimitry Andric     return ELF::R_MIPS_TLS_GD;
3090b57cec5SDimitry Andric   case Mips::fixup_Mips_GOTTPREL:
3100b57cec5SDimitry Andric     return ELF::R_MIPS_TLS_GOTTPREL;
3110b57cec5SDimitry Andric   case Mips::fixup_Mips_TPREL_HI:
3120b57cec5SDimitry Andric     return ELF::R_MIPS_TLS_TPREL_HI16;
3130b57cec5SDimitry Andric   case Mips::fixup_Mips_TPREL_LO:
3140b57cec5SDimitry Andric     return ELF::R_MIPS_TLS_TPREL_LO16;
3150b57cec5SDimitry Andric   case Mips::fixup_Mips_TLSLDM:
3160b57cec5SDimitry Andric     return ELF::R_MIPS_TLS_LDM;
3170b57cec5SDimitry Andric   case Mips::fixup_Mips_DTPREL_HI:
3180b57cec5SDimitry Andric     return ELF::R_MIPS_TLS_DTPREL_HI16;
3190b57cec5SDimitry Andric   case Mips::fixup_Mips_DTPREL_LO:
3200b57cec5SDimitry Andric     return ELF::R_MIPS_TLS_DTPREL_LO16;
3210b57cec5SDimitry Andric   case Mips::fixup_Mips_GOT_PAGE:
3220b57cec5SDimitry Andric     return ELF::R_MIPS_GOT_PAGE;
3230b57cec5SDimitry Andric   case Mips::fixup_Mips_GOT_OFST:
3240b57cec5SDimitry Andric     return ELF::R_MIPS_GOT_OFST;
3250b57cec5SDimitry Andric   case Mips::fixup_Mips_GOT_DISP:
3260b57cec5SDimitry Andric     return ELF::R_MIPS_GOT_DISP;
3275ffd83dbSDimitry Andric   case Mips::fixup_Mips_GPOFF_HI:
3285ffd83dbSDimitry Andric     return setRTypes(ELF::R_MIPS_GPREL16, ELF::R_MIPS_SUB, ELF::R_MIPS_HI16);
3295ffd83dbSDimitry Andric   case Mips::fixup_MICROMIPS_GPOFF_HI:
3305ffd83dbSDimitry Andric     return setRTypes(ELF::R_MICROMIPS_GPREL16, ELF::R_MICROMIPS_SUB,
3315ffd83dbSDimitry Andric                      ELF::R_MICROMIPS_HI16);
3325ffd83dbSDimitry Andric   case Mips::fixup_Mips_GPOFF_LO:
3335ffd83dbSDimitry Andric     return setRTypes(ELF::R_MIPS_GPREL16, ELF::R_MIPS_SUB, ELF::R_MIPS_LO16);
3345ffd83dbSDimitry Andric   case Mips::fixup_MICROMIPS_GPOFF_LO:
3355ffd83dbSDimitry Andric     return setRTypes(ELF::R_MICROMIPS_GPREL16, ELF::R_MICROMIPS_SUB,
3365ffd83dbSDimitry Andric                      ELF::R_MICROMIPS_LO16);
3370b57cec5SDimitry Andric   case Mips::fixup_Mips_HIGHER:
3380b57cec5SDimitry Andric     return ELF::R_MIPS_HIGHER;
3390b57cec5SDimitry Andric   case Mips::fixup_Mips_HIGHEST:
3400b57cec5SDimitry Andric     return ELF::R_MIPS_HIGHEST;
3410b57cec5SDimitry Andric   case Mips::fixup_Mips_SUB:
3420b57cec5SDimitry Andric     return ELF::R_MIPS_SUB;
3430b57cec5SDimitry Andric   case Mips::fixup_Mips_GOT_HI16:
3440b57cec5SDimitry Andric     return ELF::R_MIPS_GOT_HI16;
3450b57cec5SDimitry Andric   case Mips::fixup_Mips_GOT_LO16:
3460b57cec5SDimitry Andric     return ELF::R_MIPS_GOT_LO16;
3470b57cec5SDimitry Andric   case Mips::fixup_Mips_CALL_HI16:
3480b57cec5SDimitry Andric     return ELF::R_MIPS_CALL_HI16;
3490b57cec5SDimitry Andric   case Mips::fixup_Mips_CALL_LO16:
3500b57cec5SDimitry Andric     return ELF::R_MIPS_CALL_LO16;
3510b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_26_S1:
3520b57cec5SDimitry Andric     return ELF::R_MICROMIPS_26_S1;
3530b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_HI16:
3540b57cec5SDimitry Andric     return ELF::R_MICROMIPS_HI16;
3550b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_LO16:
3560b57cec5SDimitry Andric     return ELF::R_MICROMIPS_LO16;
3570b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_GOT16:
3580b57cec5SDimitry Andric     return ELF::R_MICROMIPS_GOT16;
3590b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_CALL16:
3600b57cec5SDimitry Andric     return ELF::R_MICROMIPS_CALL16;
3610b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_GOT_DISP:
3620b57cec5SDimitry Andric     return ELF::R_MICROMIPS_GOT_DISP;
3630b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_GOT_PAGE:
3640b57cec5SDimitry Andric     return ELF::R_MICROMIPS_GOT_PAGE;
3650b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_GOT_OFST:
3660b57cec5SDimitry Andric     return ELF::R_MICROMIPS_GOT_OFST;
3670b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_TLS_GD:
3680b57cec5SDimitry Andric     return ELF::R_MICROMIPS_TLS_GD;
3690b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_TLS_LDM:
3700b57cec5SDimitry Andric     return ELF::R_MICROMIPS_TLS_LDM;
3710b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16:
3720b57cec5SDimitry Andric     return ELF::R_MICROMIPS_TLS_DTPREL_HI16;
3730b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16:
3740b57cec5SDimitry Andric     return ELF::R_MICROMIPS_TLS_DTPREL_LO16;
3750b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_GOTTPREL:
3760b57cec5SDimitry Andric     return ELF::R_MICROMIPS_TLS_GOTTPREL;
3770b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_TLS_TPREL_HI16:
3780b57cec5SDimitry Andric     return ELF::R_MICROMIPS_TLS_TPREL_HI16;
3790b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_TLS_TPREL_LO16:
3800b57cec5SDimitry Andric     return ELF::R_MICROMIPS_TLS_TPREL_LO16;
3810b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_SUB:
3820b57cec5SDimitry Andric     return ELF::R_MICROMIPS_SUB;
3830b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_HIGHER:
3840b57cec5SDimitry Andric     return ELF::R_MICROMIPS_HIGHER;
3850b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_HIGHEST:
3860b57cec5SDimitry Andric     return ELF::R_MICROMIPS_HIGHEST;
3870b57cec5SDimitry Andric   case Mips::fixup_Mips_JALR:
3880b57cec5SDimitry Andric     return ELF::R_MIPS_JALR;
3890b57cec5SDimitry Andric   case Mips::fixup_MICROMIPS_JALR:
3900b57cec5SDimitry Andric     return ELF::R_MICROMIPS_JALR;
3910b57cec5SDimitry Andric   }
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric   llvm_unreachable("invalid fixup kind!");
3940b57cec5SDimitry Andric }
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric /// Sort relocation table entries by offset except where another order is
3970b57cec5SDimitry Andric /// required by the MIPS ABI.
3980b57cec5SDimitry Andric ///
3990b57cec5SDimitry Andric /// MIPS has a few relocations that have an AHL component in the expression used
4000b57cec5SDimitry Andric /// to evaluate them. This AHL component is an addend with the same number of
4010b57cec5SDimitry Andric /// bits as a symbol value but not all of our ABI's are able to supply a
4020b57cec5SDimitry Andric /// sufficiently sized addend in a single relocation.
4030b57cec5SDimitry Andric ///
4040b57cec5SDimitry Andric /// The O32 ABI for example, uses REL relocations which store the addend in the
4050b57cec5SDimitry Andric /// section data. All the relocations with AHL components affect 16-bit fields
4060b57cec5SDimitry Andric /// so the addend for a single relocation is limited to 16-bit. This ABI
4070b57cec5SDimitry Andric /// resolves the limitation by linking relocations (e.g. R_MIPS_HI16 and
4080b57cec5SDimitry Andric /// R_MIPS_LO16) and distributing the addend between the linked relocations. The
4090b57cec5SDimitry Andric /// ABI mandates that such relocations must be next to each other in a
4100b57cec5SDimitry Andric /// particular order (e.g. R_MIPS_HI16 must be immediately followed by a
4110b57cec5SDimitry Andric /// matching R_MIPS_LO16) but the rule is less strict in practice.
4120b57cec5SDimitry Andric ///
4130b57cec5SDimitry Andric /// The de facto standard is lenient in the following ways:
4140b57cec5SDimitry Andric /// - 'Immediately following' does not refer to the next relocation entry but
4150b57cec5SDimitry Andric ///   the next matching relocation.
4160b57cec5SDimitry Andric /// - There may be multiple high parts relocations for one low part relocation.
4170b57cec5SDimitry Andric /// - There may be multiple low part relocations for one high part relocation.
4180b57cec5SDimitry Andric /// - The AHL addend in each part does not have to be exactly equal as long as
4190b57cec5SDimitry Andric ///   the difference does not affect the carry bit from bit 15 into 16. This is
4200b57cec5SDimitry Andric ///   to allow, for example, the use of %lo(foo) and %lo(foo+4) when loading
4210b57cec5SDimitry Andric ///   both halves of a long long.
4220b57cec5SDimitry Andric ///
4230b57cec5SDimitry Andric /// See getMatchingLoType() for a description of which high part relocations
4240b57cec5SDimitry Andric /// match which low part relocations. One particular thing to note is that
4250b57cec5SDimitry Andric /// R_MIPS_GOT16 and similar only have AHL addends if they refer to local
4260b57cec5SDimitry Andric /// symbols.
4270b57cec5SDimitry Andric ///
4280b57cec5SDimitry Andric /// It should also be noted that this function is not affected by whether
4290b57cec5SDimitry Andric /// the symbol was kept or rewritten into a section-relative equivalent. We
4300b57cec5SDimitry Andric /// always match using the expressions from the source.
4310b57cec5SDimitry Andric void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm,
4320b57cec5SDimitry Andric                                      std::vector<ELFRelocationEntry> &Relocs) {
4330b57cec5SDimitry Andric   // We do not need to sort the relocation table for RELA relocations which
4340b57cec5SDimitry Andric   // N32/N64 uses as the relocation addend contains the value we require,
4350b57cec5SDimitry Andric   // rather than it being split across a pair of relocations.
4360b57cec5SDimitry Andric   if (hasRelocationAddend())
4370b57cec5SDimitry Andric     return;
4380b57cec5SDimitry Andric 
4390b57cec5SDimitry Andric   if (Relocs.size() < 2)
4400b57cec5SDimitry Andric     return;
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   // Sort relocations by the address they are applied to.
4430b57cec5SDimitry Andric   llvm::sort(Relocs,
4440b57cec5SDimitry Andric              [](const ELFRelocationEntry &A, const ELFRelocationEntry &B) {
4450b57cec5SDimitry Andric                return A.Offset < B.Offset;
4460b57cec5SDimitry Andric              });
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric   std::list<MipsRelocationEntry> Sorted;
4490b57cec5SDimitry Andric   std::list<ELFRelocationEntry> Remainder;
4500b57cec5SDimitry Andric 
4510b57cec5SDimitry Andric   LLVM_DEBUG(dumpRelocs("R: ", Relocs));
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric   // Separate the movable relocations (AHL relocations using the high bits) from
4540b57cec5SDimitry Andric   // the immobile relocations (everything else). This does not preserve high/low
4550b57cec5SDimitry Andric   // matches that already existed in the input.
4560b57cec5SDimitry Andric   copy_if_else(Relocs.begin(), Relocs.end(), std::back_inserter(Remainder),
4570b57cec5SDimitry Andric                std::back_inserter(Sorted), [](const ELFRelocationEntry &Reloc) {
4580b57cec5SDimitry Andric                  return getMatchingLoType(Reloc) != ELF::R_MIPS_NONE;
4590b57cec5SDimitry Andric                });
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric   for (auto &R : Remainder) {
4620b57cec5SDimitry Andric     LLVM_DEBUG(dbgs() << "Matching: " << R << "\n");
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric     unsigned MatchingType = getMatchingLoType(R);
4650b57cec5SDimitry Andric     assert(MatchingType != ELF::R_MIPS_NONE &&
4660b57cec5SDimitry Andric            "Wrong list for reloc that doesn't need a match");
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric     // Find the best matching relocation for the current high part.
4690b57cec5SDimitry Andric     // See isMatchingReloc for a description of a matching relocation and
4700b57cec5SDimitry Andric     // compareMatchingRelocs for a description of what 'best' means.
4710b57cec5SDimitry Andric     auto InsertionPoint =
4720b57cec5SDimitry Andric         find_best(Sorted.begin(), Sorted.end(),
4730b57cec5SDimitry Andric                   [&R, &MatchingType](const MipsRelocationEntry &X) {
4740b57cec5SDimitry Andric                     return isMatchingReloc(X, R, MatchingType);
4750b57cec5SDimitry Andric                   },
4760b57cec5SDimitry Andric                   compareMatchingRelocs);
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric     // If we matched then insert the high part in front of the match and mark
4790b57cec5SDimitry Andric     // both relocations as being involved in a match. We only mark the high
4800b57cec5SDimitry Andric     // part for cosmetic reasons in the debug output.
4810b57cec5SDimitry Andric     //
4820b57cec5SDimitry Andric     // If we failed to find a match then the high part is orphaned. This is not
4830b57cec5SDimitry Andric     // permitted since the relocation cannot be evaluated without knowing the
4840b57cec5SDimitry Andric     // carry-in. We can sometimes handle this using a matching low part that is
4850b57cec5SDimitry Andric     // already used in a match but we already cover that case in
4860b57cec5SDimitry Andric     // isMatchingReloc and compareMatchingRelocs. For the remaining cases we
4870b57cec5SDimitry Andric     // should insert the high part at the end of the list. This will cause the
4880b57cec5SDimitry Andric     // linker to fail but the alternative is to cause the linker to bind the
4890b57cec5SDimitry Andric     // high part to a semi-matching low part and silently calculate the wrong
4900b57cec5SDimitry Andric     // value. Unfortunately we have no means to warn the user that we did this
4910b57cec5SDimitry Andric     // so leave it up to the linker to complain about it.
4920b57cec5SDimitry Andric     if (InsertionPoint != Sorted.end())
4930b57cec5SDimitry Andric       InsertionPoint->Matched = true;
4940b57cec5SDimitry Andric     Sorted.insert(InsertionPoint, R)->Matched = true;
4950b57cec5SDimitry Andric   }
4960b57cec5SDimitry Andric 
4970b57cec5SDimitry Andric   LLVM_DEBUG(dumpRelocs("S: ", Sorted));
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric   assert(Relocs.size() == Sorted.size() && "Some relocs were not consumed");
5000b57cec5SDimitry Andric 
501*0fca6ea1SDimitry Andric   // Overwrite the original vector with the sorted elements.
5020b57cec5SDimitry Andric   unsigned CopyTo = 0;
503*0fca6ea1SDimitry Andric   for (const auto &R : Sorted)
5040b57cec5SDimitry Andric     Relocs[CopyTo++] = R.R;
5050b57cec5SDimitry Andric }
5060b57cec5SDimitry Andric 
5075f757f3fSDimitry Andric bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCValue &Val,
5085f757f3fSDimitry Andric                                                   const MCSymbol &Sym,
5090b57cec5SDimitry Andric                                                   unsigned Type) const {
5100b57cec5SDimitry Andric   // If it's a compound relocation for N64 then we need the relocation if any
5110b57cec5SDimitry Andric   // sub-relocation needs it.
5120b57cec5SDimitry Andric   if (!isUInt<8>(Type))
5135f757f3fSDimitry Andric     return needsRelocateWithSymbol(Val, Sym, Type & 0xff) ||
5145f757f3fSDimitry Andric            needsRelocateWithSymbol(Val, Sym, (Type >> 8) & 0xff) ||
5155f757f3fSDimitry Andric            needsRelocateWithSymbol(Val, Sym, (Type >> 16) & 0xff);
5160b57cec5SDimitry Andric 
5170b57cec5SDimitry Andric   switch (Type) {
5180b57cec5SDimitry Andric   default:
5190b57cec5SDimitry Andric     errs() << Type << "\n";
5200b57cec5SDimitry Andric     llvm_unreachable("Unexpected relocation");
5210b57cec5SDimitry Andric     return true;
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric   // This relocation doesn't affect the section data.
5240b57cec5SDimitry Andric   case ELF::R_MIPS_NONE:
5250b57cec5SDimitry Andric     return false;
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   // On REL ABI's (e.g. O32), these relocations form pairs. The pairing is done
5280b57cec5SDimitry Andric   // by the static linker by matching the symbol and offset.
5290b57cec5SDimitry Andric   // We only see one relocation at a time but it's still safe to relocate with
5300b57cec5SDimitry Andric   // the section so long as both relocations make the same decision.
5310b57cec5SDimitry Andric   //
5320b57cec5SDimitry Andric   // Some older linkers may require the symbol for particular cases. Such cases
5330b57cec5SDimitry Andric   // are not supported yet but can be added as required.
5340b57cec5SDimitry Andric   case ELF::R_MIPS_GOT16:
5350b57cec5SDimitry Andric   case ELF::R_MIPS16_GOT16:
5360b57cec5SDimitry Andric   case ELF::R_MICROMIPS_GOT16:
5370b57cec5SDimitry Andric   case ELF::R_MIPS_HIGHER:
5380b57cec5SDimitry Andric   case ELF::R_MIPS_HIGHEST:
5390b57cec5SDimitry Andric   case ELF::R_MIPS_HI16:
5400b57cec5SDimitry Andric   case ELF::R_MIPS16_HI16:
5410b57cec5SDimitry Andric   case ELF::R_MICROMIPS_HI16:
5420b57cec5SDimitry Andric   case ELF::R_MIPS_LO16:
5430b57cec5SDimitry Andric   case ELF::R_MIPS16_LO16:
5440b57cec5SDimitry Andric   case ELF::R_MICROMIPS_LO16:
5450b57cec5SDimitry Andric     // FIXME: It should be safe to return false for the STO_MIPS_MICROMIPS but
5460b57cec5SDimitry Andric     //        we neglect to handle the adjustment to the LSB of the addend that
5470b57cec5SDimitry Andric     //        it causes in applyFixup() and similar.
5480b57cec5SDimitry Andric     if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS)
5490b57cec5SDimitry Andric       return true;
5500b57cec5SDimitry Andric     return false;
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   case ELF::R_MIPS_GOT_PAGE:
5530b57cec5SDimitry Andric   case ELF::R_MICROMIPS_GOT_PAGE:
5540b57cec5SDimitry Andric   case ELF::R_MIPS_GOT_OFST:
5550b57cec5SDimitry Andric   case ELF::R_MICROMIPS_GOT_OFST:
5560b57cec5SDimitry Andric   case ELF::R_MIPS_16:
5570b57cec5SDimitry Andric   case ELF::R_MIPS_32:
5580b57cec5SDimitry Andric   case ELF::R_MIPS_GPREL32:
5590b57cec5SDimitry Andric     if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS)
5600b57cec5SDimitry Andric       return true;
561bdd1243dSDimitry Andric     [[fallthrough]];
5620b57cec5SDimitry Andric   case ELF::R_MIPS_26:
5630b57cec5SDimitry Andric   case ELF::R_MIPS_64:
5640b57cec5SDimitry Andric   case ELF::R_MIPS_GPREL16:
5650b57cec5SDimitry Andric   case ELF::R_MIPS_PC16:
5660b57cec5SDimitry Andric   case ELF::R_MIPS_SUB:
5670b57cec5SDimitry Andric     return false;
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   // FIXME: Many of these relocations should probably return false but this
5700b57cec5SDimitry Andric   //        hasn't been confirmed to be safe yet.
5710b57cec5SDimitry Andric   case ELF::R_MIPS_REL32:
5720b57cec5SDimitry Andric   case ELF::R_MIPS_LITERAL:
5730b57cec5SDimitry Andric   case ELF::R_MIPS_CALL16:
5740b57cec5SDimitry Andric   case ELF::R_MIPS_SHIFT5:
5750b57cec5SDimitry Andric   case ELF::R_MIPS_SHIFT6:
5760b57cec5SDimitry Andric   case ELF::R_MIPS_GOT_DISP:
5770b57cec5SDimitry Andric   case ELF::R_MIPS_GOT_HI16:
5780b57cec5SDimitry Andric   case ELF::R_MIPS_GOT_LO16:
5790b57cec5SDimitry Andric   case ELF::R_MIPS_INSERT_A:
5800b57cec5SDimitry Andric   case ELF::R_MIPS_INSERT_B:
5810b57cec5SDimitry Andric   case ELF::R_MIPS_DELETE:
5820b57cec5SDimitry Andric   case ELF::R_MIPS_CALL_HI16:
5830b57cec5SDimitry Andric   case ELF::R_MIPS_CALL_LO16:
5840b57cec5SDimitry Andric   case ELF::R_MIPS_SCN_DISP:
5850b57cec5SDimitry Andric   case ELF::R_MIPS_REL16:
5860b57cec5SDimitry Andric   case ELF::R_MIPS_ADD_IMMEDIATE:
5870b57cec5SDimitry Andric   case ELF::R_MIPS_PJUMP:
5880b57cec5SDimitry Andric   case ELF::R_MIPS_RELGOT:
5890b57cec5SDimitry Andric   case ELF::R_MIPS_JALR:
5900b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_DTPMOD32:
5910b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_DTPREL32:
5920b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_DTPMOD64:
5930b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_DTPREL64:
5940b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_GD:
5950b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_LDM:
5960b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_DTPREL_HI16:
5970b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_DTPREL_LO16:
5980b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_GOTTPREL:
5990b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_TPREL32:
6000b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_TPREL64:
6010b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_TPREL_HI16:
6020b57cec5SDimitry Andric   case ELF::R_MIPS_TLS_TPREL_LO16:
6030b57cec5SDimitry Andric   case ELF::R_MIPS_GLOB_DAT:
6040b57cec5SDimitry Andric   case ELF::R_MIPS_PC21_S2:
6050b57cec5SDimitry Andric   case ELF::R_MIPS_PC26_S2:
6060b57cec5SDimitry Andric   case ELF::R_MIPS_PC18_S3:
6070b57cec5SDimitry Andric   case ELF::R_MIPS_PC19_S2:
6080b57cec5SDimitry Andric   case ELF::R_MIPS_PCHI16:
6090b57cec5SDimitry Andric   case ELF::R_MIPS_PCLO16:
6100b57cec5SDimitry Andric   case ELF::R_MIPS_COPY:
6110b57cec5SDimitry Andric   case ELF::R_MIPS_JUMP_SLOT:
6120b57cec5SDimitry Andric   case ELF::R_MIPS_NUM:
6130b57cec5SDimitry Andric   case ELF::R_MIPS_PC32:
6140b57cec5SDimitry Andric   case ELF::R_MIPS_EH:
6150b57cec5SDimitry Andric   case ELF::R_MICROMIPS_26_S1:
6160b57cec5SDimitry Andric   case ELF::R_MICROMIPS_GPREL16:
6170b57cec5SDimitry Andric   case ELF::R_MICROMIPS_LITERAL:
6180b57cec5SDimitry Andric   case ELF::R_MICROMIPS_PC7_S1:
6190b57cec5SDimitry Andric   case ELF::R_MICROMIPS_PC10_S1:
6200b57cec5SDimitry Andric   case ELF::R_MICROMIPS_PC16_S1:
6210b57cec5SDimitry Andric   case ELF::R_MICROMIPS_CALL16:
6220b57cec5SDimitry Andric   case ELF::R_MICROMIPS_GOT_DISP:
6230b57cec5SDimitry Andric   case ELF::R_MICROMIPS_GOT_HI16:
6240b57cec5SDimitry Andric   case ELF::R_MICROMIPS_GOT_LO16:
6250b57cec5SDimitry Andric   case ELF::R_MICROMIPS_SUB:
6260b57cec5SDimitry Andric   case ELF::R_MICROMIPS_HIGHER:
6270b57cec5SDimitry Andric   case ELF::R_MICROMIPS_HIGHEST:
6280b57cec5SDimitry Andric   case ELF::R_MICROMIPS_CALL_HI16:
6290b57cec5SDimitry Andric   case ELF::R_MICROMIPS_CALL_LO16:
6300b57cec5SDimitry Andric   case ELF::R_MICROMIPS_SCN_DISP:
6310b57cec5SDimitry Andric   case ELF::R_MICROMIPS_JALR:
6320b57cec5SDimitry Andric   case ELF::R_MICROMIPS_HI0_LO16:
6330b57cec5SDimitry Andric   case ELF::R_MICROMIPS_TLS_GD:
6340b57cec5SDimitry Andric   case ELF::R_MICROMIPS_TLS_LDM:
6350b57cec5SDimitry Andric   case ELF::R_MICROMIPS_TLS_DTPREL_HI16:
6360b57cec5SDimitry Andric   case ELF::R_MICROMIPS_TLS_DTPREL_LO16:
6370b57cec5SDimitry Andric   case ELF::R_MICROMIPS_TLS_GOTTPREL:
6380b57cec5SDimitry Andric   case ELF::R_MICROMIPS_TLS_TPREL_HI16:
6390b57cec5SDimitry Andric   case ELF::R_MICROMIPS_TLS_TPREL_LO16:
6400b57cec5SDimitry Andric   case ELF::R_MICROMIPS_GPREL7_S2:
6410b57cec5SDimitry Andric   case ELF::R_MICROMIPS_PC23_S2:
6420b57cec5SDimitry Andric   case ELF::R_MICROMIPS_PC21_S1:
6430b57cec5SDimitry Andric   case ELF::R_MICROMIPS_PC26_S1:
6440b57cec5SDimitry Andric   case ELF::R_MICROMIPS_PC18_S3:
6450b57cec5SDimitry Andric   case ELF::R_MICROMIPS_PC19_S2:
6460b57cec5SDimitry Andric     return true;
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric   // FIXME: Many of these should probably return false but MIPS16 isn't
6490b57cec5SDimitry Andric   //        supported by the integrated assembler.
6500b57cec5SDimitry Andric   case ELF::R_MIPS16_26:
6510b57cec5SDimitry Andric   case ELF::R_MIPS16_GPREL:
6520b57cec5SDimitry Andric   case ELF::R_MIPS16_CALL16:
6530b57cec5SDimitry Andric   case ELF::R_MIPS16_TLS_GD:
6540b57cec5SDimitry Andric   case ELF::R_MIPS16_TLS_LDM:
6550b57cec5SDimitry Andric   case ELF::R_MIPS16_TLS_DTPREL_HI16:
6560b57cec5SDimitry Andric   case ELF::R_MIPS16_TLS_DTPREL_LO16:
6570b57cec5SDimitry Andric   case ELF::R_MIPS16_TLS_GOTTPREL:
6580b57cec5SDimitry Andric   case ELF::R_MIPS16_TLS_TPREL_HI16:
6590b57cec5SDimitry Andric   case ELF::R_MIPS16_TLS_TPREL_LO16:
6600b57cec5SDimitry Andric     llvm_unreachable("Unsupported MIPS16 relocation");
6610b57cec5SDimitry Andric     return true;
6620b57cec5SDimitry Andric   }
6630b57cec5SDimitry Andric }
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric std::unique_ptr<MCObjectTargetWriter>
6660b57cec5SDimitry Andric llvm::createMipsELFObjectWriter(const Triple &TT, bool IsN32) {
6670b57cec5SDimitry Andric   uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
6680b57cec5SDimitry Andric   bool IsN64 = TT.isArch64Bit() && !IsN32;
6690b57cec5SDimitry Andric   bool HasRelocationAddend = TT.isArch64Bit();
6708bcb0991SDimitry Andric   return std::make_unique<MipsELFObjectWriter>(OSABI, HasRelocationAddend,
6710b57cec5SDimitry Andric                                                 IsN64);
6720b57cec5SDimitry Andric }
673