summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp')
-rw-r--r--lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp675
1 files changed, 0 insertions, 675 deletions
diff --git a/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp b/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
deleted file mode 100644
index ad4e62e6468..00000000000
--- a/lld/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
+++ /dev/null
@@ -1,675 +0,0 @@
-//===- lib/ReaderWriter/ELF/MipsAbiInfoHandler.cpp ------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsAbiInfoHandler.h"
-#include "lld/Core/Error.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/MipsABIFlags.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm;
-using namespace llvm::ELF;
-using namespace llvm::Mips;
-
-namespace {
-
-// The joined set of MIPS ISAs and MIPS ISA extensions.
-enum MipsISAs {
- ArchNone,
-
- // General ISAs
- Arch1,
- Arch2,
- Arch3,
- Arch4,
- Arch5,
- Arch32,
- Arch32r2,
- Arch32r3,
- Arch32r5,
- Arch32r6,
- Arch64,
- Arch64r2,
- Arch64r3,
- Arch64r5,
- Arch64r6,
-
- // CPU specific ISAs
- Arch3900,
- Arch4010,
- Arch4100,
- Arch4111,
- Arch4120,
- Arch4650,
- Arch5400,
- Arch5500,
- Arch5900,
- Arch9000,
- Arch10000,
- ArchLs2e,
- ArchLs2f,
- ArchLs3a,
- ArchOcteon,
- ArchOcteonP,
- ArchOcteon2,
- ArchOcteon3,
- ArchSB1,
- ArchXLR
-};
-
-struct MipsISATreeEdge {
- MipsISAs child;
- MipsISAs parent;
-};
-
-struct ElfArchPair {
- uint32_t _elfFlag;
- MipsISAs _arch;
-};
-
-struct AbiIsaArchPair {
- uint8_t _isaLevel;
- uint8_t _isaRev;
- uint8_t _isaExt;
- MipsISAs _arch;
-};
-}
-
-static const MipsISATreeEdge isaTree[] = {
- // MIPS32R6 and MIPS64R6 are not compatible with other extensions
-
- // MIPS64R2 extensions.
- {ArchOcteon3, ArchOcteon2},
- {ArchOcteon2, ArchOcteonP},
- {ArchOcteonP, ArchOcteon},
- {ArchOcteon, Arch64r2},
- {ArchLs3a, Arch64r2},
-
- // MIPS64 extensions.
- {Arch64r2, Arch64},
- {ArchSB1, Arch64},
- {ArchXLR, Arch64},
-
- // MIPS V extensions.
- {Arch64, Arch5},
-
- // R5000 extensions.
- {Arch5500, Arch5400},
-
- // MIPS IV extensions.
- {Arch5, Arch4},
- {Arch5400, Arch4},
- {Arch9000, Arch4},
-
- // VR4100 extensions.
- {Arch4120, Arch4100},
- {Arch4111, Arch4100},
-
- // MIPS III extensions.
- {ArchLs2e, Arch3},
- {ArchLs2f, Arch3},
- {Arch4650, Arch3},
- {Arch4100, Arch3},
- {Arch4010, Arch3},
- {Arch5900, Arch3},
- {Arch4, Arch3},
-
- // MIPS32 extensions.
- {Arch32r2, Arch32},
-
- // MIPS II extensions.
- {Arch3, Arch2},
- {Arch32, Arch2},
-
- // MIPS I extensions.
- {Arch3900, Arch1},
- {Arch2, Arch1},
-};
-
-// Conversion ELF arch flags => MipsISAs
-static const ElfArchPair elfArchPairs[] = {
- {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, Arch3900},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, Arch4010},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, Arch4100},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, Arch4111},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, Arch4120},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, Arch4650},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, Arch5400},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, Arch5500},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, Arch5900},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, Arch9000},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, ArchLs2e},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, ArchLs2f},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, ArchLs3a},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, ArchOcteon},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, ArchOcteon2},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, ArchOcteon3},
- {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, ArchSB1},
- {EF_MIPS_ARCH_64 | EF_MIPS_MACH_XLR, ArchXLR},
- {EF_MIPS_ARCH_1, Arch1},
- {EF_MIPS_ARCH_2, Arch2},
- {EF_MIPS_ARCH_3, Arch3},
- {EF_MIPS_ARCH_4, Arch4},
- {EF_MIPS_ARCH_5, Arch5},
- {EF_MIPS_ARCH_32, Arch32},
- {EF_MIPS_ARCH_32R2, Arch32r2},
- {EF_MIPS_ARCH_32R6, Arch32r6},
- {EF_MIPS_ARCH_64, Arch64},
- {EF_MIPS_ARCH_64R2, Arch64r2},
- {EF_MIPS_ARCH_64R6, Arch64r6}
-};
-
-// Conversion MipsISAs => ELF arch flags
-static const ElfArchPair archElfPairs[] = {
- {EF_MIPS_ARCH_1, Arch1},
- {EF_MIPS_ARCH_2, Arch2},
- {EF_MIPS_ARCH_3, Arch3},
- {EF_MIPS_ARCH_4, Arch4},
- {EF_MIPS_ARCH_5, Arch5},
- {EF_MIPS_ARCH_32, Arch32},
- {EF_MIPS_ARCH_32R2, Arch32r2},
- {EF_MIPS_ARCH_32R2, Arch32r3},
- {EF_MIPS_ARCH_32R2, Arch32r5},
- {EF_MIPS_ARCH_32R6, Arch32r6},
- {EF_MIPS_ARCH_64, Arch64},
- {EF_MIPS_ARCH_64R2, Arch64r2},
- {EF_MIPS_ARCH_64R2, Arch64r3},
- {EF_MIPS_ARCH_64R2, Arch64r5},
- {EF_MIPS_ARCH_64R6, Arch64r6},
- {EF_MIPS_ARCH_1 | EF_MIPS_MACH_3900, Arch3900},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4010, Arch4010},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4100, Arch4100},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4111, Arch4111},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4120, Arch4120},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_4650, Arch4650},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5400, Arch5400},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_5500, Arch5500},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_5900, Arch5900},
- {EF_MIPS_ARCH_4 | EF_MIPS_MACH_9000, Arch9000},
- {EF_MIPS_ARCH_4, Arch10000},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2E, ArchLs2e},
- {EF_MIPS_ARCH_3 | EF_MIPS_MACH_LS2F, ArchLs2f},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_LS3A, ArchLs3a},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, ArchOcteon},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON, ArchOcteonP},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON2, ArchOcteon2},
- {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, ArchOcteon3},
- {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, ArchSB1},
- {EF_MIPS_ARCH_64 | EF_MIPS_MACH_SB1, ArchXLR}
-};
-
-// Conversion .MIPS.abiflags isa/level/extension <=> MipsISAs
-static const AbiIsaArchPair abiIsaArchPair[] = {
- { 0, 0, 0, ArchNone},
- { 1, 0, 0, Arch1},
- { 2, 0, 0, Arch2},
- { 3, 0, 0, Arch3},
- { 4, 0, 0, Arch4},
- { 5, 0, 0, Arch5},
- {32, 1, 0, Arch32},
- {32, 2, 0, Arch32r2},
- {32, 3, 0, Arch32r3},
- {32, 5, 0, Arch32r5},
- {32, 6, 0, Arch32r6},
- {64, 1, 0, Arch64},
- {64, 2, 0, Arch64r2},
- {64, 3, 0, Arch64r3},
- {64, 5, 0, Arch64r5},
- {64, 6, 0, Arch64r6},
- { 1, 0, AFL_EXT_3900, Arch3900},
- { 3, 0, AFL_EXT_4010, Arch4010},
- { 3, 0, AFL_EXT_4100, Arch4100},
- { 3, 0, AFL_EXT_4111, Arch4111},
- { 3, 0, AFL_EXT_4120, Arch4120},
- { 3, 0, AFL_EXT_4650, Arch4650},
- { 4, 0, AFL_EXT_5400, Arch5400},
- { 4, 0, AFL_EXT_5500, Arch5500},
- { 3, 0, AFL_EXT_5900, Arch5900},
- { 4, 0, AFL_EXT_10000, Arch10000},
- { 3, 0, AFL_EXT_LOONGSON_2E, ArchLs2e},
- { 3, 0, AFL_EXT_LOONGSON_2F, ArchLs2f},
- {64, 2, AFL_EXT_LOONGSON_3A, ArchLs3a},
- {64, 2, AFL_EXT_OCTEON, ArchOcteon},
- {64, 2, AFL_EXT_OCTEON2, ArchOcteon2},
- {64, 2, AFL_EXT_OCTEON3, ArchOcteon3},
- {64, 1, AFL_EXT_SB1, ArchSB1},
- {64, 1, AFL_EXT_XLR, ArchXLR}
-};
-
-static bool matchMipsISA(MipsISAs base, MipsISAs ext) {
- if (base == ext)
- return true;
- if (base == Arch32 && matchMipsISA(Arch64, ext))
- return true;
- if (base == Arch32r2 && matchMipsISA(Arch64r2, ext))
- return true;
- for (const auto &edge : isaTree) {
- if (ext == edge.child) {
- ext = edge.parent;
- if (ext == base)
- return true;
- }
- }
- return false;
-}
-
-static bool is32BitElfFlags(unsigned flags) {
- if (flags & EF_MIPS_32BITMODE)
- return true;
-
- unsigned arch = flags & EF_MIPS_ARCH;
- if (arch == EF_MIPS_ARCH_1 || arch == EF_MIPS_ARCH_2 ||
- arch == EF_MIPS_ARCH_32 || arch == EF_MIPS_ARCH_32R2 ||
- arch == EF_MIPS_ARCH_32R6)
- return true;
-
- unsigned abi = flags & EF_MIPS_ABI;
- if (abi == EF_MIPS_ABI_O32 || abi == EF_MIPS_ABI_EABI32)
- return true;
-
- return false;
-}
-
-static ErrorOr<MipsISAs> headerFlagsToIsa(uint32_t flags) {
- uint32_t arch = flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
- for (const auto &p : elfArchPairs)
- if (p._elfFlag == arch)
- return p._arch;
- return make_dynamic_error_code(
- StringRef("Unknown EF_MIPS_ARCH | EF_MIPS_MACH flags (0x") +
- Twine::utohexstr(arch) + ")");
-}
-
-static uint32_t isaToHeaderFlags(unsigned isa) {
- for (const auto &p : archElfPairs)
- if (p._arch == isa)
- return p._elfFlag;
- llvm_unreachable("Unknown MIPS ISA");
-}
-
-static ErrorOr<uint32_t> flagsToAses(uint32_t flags) {
- uint32_t ases = flags & EF_MIPS_ARCH_ASE;
- switch (ases) {
- case 0:
- return 0;
- case EF_MIPS_MICROMIPS:
- return AFL_ASE_MICROMIPS;
- case EF_MIPS_ARCH_ASE_M16:
- return AFL_ASE_MIPS16;
- case EF_MIPS_ARCH_ASE_MDMX:
- return AFL_ASE_MDMX;
- default:
- return make_dynamic_error_code(
- StringRef("Unknown EF_MIPS_ARCH_ASE flag (0x") +
- Twine::utohexstr(ases) + ")");
- }
-}
-
-static uint32_t asesToFlags(uint32_t ases) {
- switch (ases) {
- case AFL_ASE_MICROMIPS:
- return EF_MIPS_MICROMIPS;
- case AFL_ASE_MIPS16:
- return EF_MIPS_ARCH_ASE_M16;
- case AFL_ASE_MDMX:
- return EF_MIPS_ARCH_ASE_MDMX;
- default:
- return 0;
- }
-}
-
-static ErrorOr<MipsISAs> sectionFlagsToIsa(uint8_t isaLevel, uint8_t isaRev,
- uint8_t isaExt) {
- for (const auto &p : abiIsaArchPair)
- if (p._isaLevel == isaLevel && p._isaRev == isaRev && p._isaExt == isaExt)
- return p._arch;
- return make_dynamic_error_code(
- StringRef("Unknown ISA level/revision/extension ") + Twine(isaLevel) +
- "/" + Twine(isaRev) + "/" + Twine(isaExt));
-}
-
-static std::tuple<uint8_t, uint8_t, uint32_t> isaToSectionFlags(unsigned isa) {
- for (const auto &p : abiIsaArchPair)
- if (p._arch == isa)
- return std::make_tuple(p._isaLevel, p._isaRev, p._isaExt);
- llvm_unreachable("Unknown MIPS ISA");
-}
-
-static bool checkCompatibility(const MipsAbiFlags &hdr,
- const MipsAbiFlags &sec) {
- uint32_t secIsa = ArchNone;
- switch (sec._isa) {
- case Arch32r3:
- case Arch32r5:
- secIsa = Arch32r2;
- break;
- case Arch64r3:
- case Arch64r5:
- secIsa = Arch64r2;
- break;
- default:
- secIsa = sec._isa;
- break;
- }
- if (secIsa != hdr._isa) {
- llvm::errs() << "inconsistent ISA between .MIPS.abiflags "
- "and ELF header e_flags field\n";
- return false;
- }
- if ((sec._ases & hdr._ases) != hdr._ases) {
- llvm::errs() << "inconsistent ASEs between .MIPS.abiflags "
- "and ELF header e_flags field\n";
- return false;
- }
- return true;
-}
-
-static int compareFpAbi(uint32_t fpA, uint32_t fpB) {
- if (fpA == fpB)
- return 0;
- if (fpB == Val_GNU_MIPS_ABI_FP_ANY)
- return 1;
- if (fpB == Val_GNU_MIPS_ABI_FP_64A && fpA == Val_GNU_MIPS_ABI_FP_64)
- return 1;
- if (fpB != Val_GNU_MIPS_ABI_FP_XX)
- return -1;
- if (fpA == Val_GNU_MIPS_ABI_FP_DOUBLE || fpA == Val_GNU_MIPS_ABI_FP_64 ||
- fpA == Val_GNU_MIPS_ABI_FP_64A)
- return 1;
- return -1;
-}
-
-static StringRef getFpAbiName(uint32_t fpAbi) {
- switch (fpAbi) {
- case Val_GNU_MIPS_ABI_FP_ANY:
- return "<any>";
- case Val_GNU_MIPS_ABI_FP_DOUBLE:
- return "-mdouble-float";
- case Val_GNU_MIPS_ABI_FP_SINGLE:
- return "-msingle-float";
- case Val_GNU_MIPS_ABI_FP_SOFT:
- return "-msoft-float";
- case Val_GNU_MIPS_ABI_FP_OLD_64:
- return "-mips32r2 -mfp64 (old)";
- case Val_GNU_MIPS_ABI_FP_XX:
- return "-mfpxx";
- case Val_GNU_MIPS_ABI_FP_64:
- return "-mgp32 -mfp64";
- case Val_GNU_MIPS_ABI_FP_64A:
- return "-mgp32 -mfp64 -mno-odd-spreg";
- default:
- return "<unknown>";
- }
-}
-
-static uint32_t selectFpAbiFlag(uint32_t oldFp, uint32_t newFp) {
- if (compareFpAbi(newFp, oldFp) >= 0)
- return newFp;
- if (compareFpAbi(oldFp, newFp) < 0)
- llvm::errs() << "FP ABI " << getFpAbiName(oldFp) << " is incompatible with "
- << getFpAbiName(newFp) << "\n";
- return oldFp;
-}
-
-namespace lld {
-namespace elf {
-
-template <class ELFT> bool MipsAbiInfoHandler<ELFT>::isMicroMips() const {
- assert(_abiFlags.hasValue());
- return _abiFlags->_ases & AFL_ASE_MICROMIPS;
-}
-
-template <class ELFT> bool MipsAbiInfoHandler<ELFT>::isMipsR6() const {
- assert(_abiFlags.hasValue());
- return _abiFlags->_isa == Arch32r6 || _abiFlags->_isa == Arch64r6;
-}
-
-template <class ELFT> bool MipsAbiInfoHandler<ELFT>::isFp64() const {
- assert(_abiFlags.hasValue());
- return _abiFlags->_fpAbi == Val_GNU_MIPS_ABI_FP_64 ||
- _abiFlags->_fpAbi == Val_GNU_MIPS_ABI_FP_64A;
-}
-
-template <class ELFT> bool MipsAbiInfoHandler<ELFT>::isCPicOnly() const {
- assert(_abiFlags.hasValue());
- return _abiFlags->_isCPic && !_abiFlags->_isPic;
-}
-
-template <class ELFT> uint32_t MipsAbiInfoHandler<ELFT>::getFlags() const {
- std::lock_guard<std::mutex> lock(_mutex);
- uint32_t flags = 0;
- if (_abiFlags.hasValue()) {
- flags |= isaToHeaderFlags(_abiFlags->_isa);
- flags |= asesToFlags(_abiFlags->_ases);
- flags |= _abiFlags->_abi;
- flags |= _abiFlags->_isPic ? EF_MIPS_PIC : 0u;
- flags |= _abiFlags->_isCPic ? EF_MIPS_CPIC : 0u;
- flags |= _abiFlags->_isNoReorder ? EF_MIPS_NOREORDER : 0u;
- flags |= _abiFlags->_is32BitMode ? EF_MIPS_32BITMODE : 0u;
- flags |= _abiFlags->_isNan2008 ? EF_MIPS_NAN2008 : 0u;
- }
- return flags;
-}
-
-template <class ELFT>
-llvm::Optional<typename MipsAbiInfoHandler<ELFT>::Elf_Mips_RegInfo>
-MipsAbiInfoHandler<ELFT>::getRegistersMask() const {
- std::lock_guard<std::mutex> lock(_mutex);
- return _regMask;
-}
-
-template <class ELFT>
-llvm::Optional<typename MipsAbiInfoHandler<ELFT>::Elf_Mips_ABIFlags>
-MipsAbiInfoHandler<ELFT>::getAbiFlags() const {
- std::lock_guard<std::mutex> lock(_mutex);
- if (!_hasAbiSection)
- return llvm::Optional<Elf_Mips_ABIFlags>();
-
- Elf_Mips_ABIFlags sec;
- sec.version = 0;
- std::tie(sec.isa_level, sec.isa_rev, sec.isa_ext) =
- isaToSectionFlags(_abiFlags->_isa);
- sec.gpr_size = _abiFlags->_gprSize;
- sec.cpr1_size = _abiFlags->_cpr1Size;
- sec.cpr2_size = _abiFlags->_cpr2Size;
- sec.fp_abi = _abiFlags->_fpAbi;
- sec.ases = _abiFlags->_ases;
- sec.flags1 = _abiFlags->_flags1;
- sec.flags2 = 0;
- return sec;
-}
-
-template <class ELFT> MipsAbi MipsAbiInfoHandler<ELFT>::getAbi() const {
- if (!_abiFlags.hasValue())
- return ELFT::Is64Bits ? MipsAbi::N64 : MipsAbi::O32;
- switch (_abiFlags->_abi & (EF_MIPS_ABI_O32 | EF_MIPS_ABI2)) {
- case EF_MIPS_ABI_O32:
- return MipsAbi::O32;
- case EF_MIPS_ABI2:
- return MipsAbi::N32;
- case 0:
- return MipsAbi::N64;
- default:
- llvm_unreachable("Unknown ABI flag");
- }
-}
-
-template <class ELFT>
-std::error_code
-MipsAbiInfoHandler<ELFT>::mergeFlags(uint32_t newFlags,
- const Elf_Mips_ABIFlags *newSec) {
- std::lock_guard<std::mutex> lock(_mutex);
-
- ErrorOr<MipsAbiFlags> abiFlags = createAbiFlags(newFlags, newSec);
- if (auto ec = abiFlags.getError())
- return ec;
-
- // We support three ABI: O32, N32, and N64. The last one does not have
- // the corresponding ELF flag.
- if (ELFT::Is64Bits) {
- if (abiFlags->_abi)
- return make_dynamic_error_code("Unsupported ABI");
- } else {
- if (!(abiFlags->_abi & (EF_MIPS_ABI_O32 | EF_MIPS_ABI2)))
- return make_dynamic_error_code("Unsupported ABI");
- }
-
- // ... and still do not support MIPS-16 extension.
- if (abiFlags->_ases & AFL_ASE_MIPS16)
- return make_dynamic_error_code("Unsupported extension: MIPS16");
-
- // PIC code is inherently CPIC and may not set CPIC flag explicitly.
- // Ensure that this flag will exist in the linked file.
- if (abiFlags->_isPic)
- abiFlags->_isCPic = true;
-
- // If the old set of flags is empty, use the new one as a result.
- if (!_abiFlags.hasValue()) {
- _abiFlags = *abiFlags;
- return std::error_code();
- }
-
- // Check ABI compatibility.
- if (abiFlags->_abi != _abiFlags->_abi)
- return make_dynamic_error_code("Linking modules with incompatible ABI");
-
- // Check PIC / CPIC flags compatibility.
- if (abiFlags->_isCPic != _abiFlags->_isCPic)
- llvm::errs() << "lld warning: linking abicalls and non-abicalls files\n";
-
- if (!abiFlags->_isPic)
- _abiFlags->_isPic = false;
- if (abiFlags->_isCPic)
- _abiFlags->_isCPic = true;
-
- // Check mixing -mnan=2008 / -mnan=legacy modules.
- if (abiFlags->_isNan2008 != _abiFlags->_isNan2008)
- return make_dynamic_error_code(
- "Linking -mnan=2008 and -mnan=legacy modules");
-
- // Check ISA compatibility and update the extension flag.
- if (!matchMipsISA(MipsISAs(abiFlags->_isa), MipsISAs(_abiFlags->_isa))) {
- if (!matchMipsISA(MipsISAs(_abiFlags->_isa), MipsISAs(abiFlags->_isa)))
- return make_dynamic_error_code("Linking modules with incompatible ISA");
- _abiFlags->_isa = abiFlags->_isa;
- }
-
- _abiFlags->_ases |= abiFlags->_ases;
- _abiFlags->_isNoReorder = _abiFlags->_isNoReorder || abiFlags->_isNoReorder;
- _abiFlags->_is32BitMode = _abiFlags->_is32BitMode || abiFlags->_is32BitMode;
-
- _abiFlags->_fpAbi = selectFpAbiFlag(_abiFlags->_fpAbi, abiFlags->_fpAbi);
- _abiFlags->_gprSize = std::max(_abiFlags->_gprSize, abiFlags->_gprSize);
- _abiFlags->_cpr1Size = std::max(_abiFlags->_cpr1Size, abiFlags->_cpr1Size);
- _abiFlags->_cpr2Size = std::max(_abiFlags->_cpr2Size, abiFlags->_cpr2Size);
- _abiFlags->_flags1 |= abiFlags->_flags1;
-
- return std::error_code();
-}
-
-template <class ELFT>
-void MipsAbiInfoHandler<ELFT>::mergeRegistersMask(
- const Elf_Mips_RegInfo &info) {
- std::lock_guard<std::mutex> lock(_mutex);
- if (!_regMask.hasValue()) {
- _regMask = info;
- return;
- }
- _regMask->ri_gprmask = _regMask->ri_gprmask | info.ri_gprmask;
- _regMask->ri_cprmask[0] = _regMask->ri_cprmask[0] | info.ri_cprmask[0];
- _regMask->ri_cprmask[1] = _regMask->ri_cprmask[1] | info.ri_cprmask[1];
- _regMask->ri_cprmask[2] = _regMask->ri_cprmask[2] | info.ri_cprmask[2];
- _regMask->ri_cprmask[3] = _regMask->ri_cprmask[3] | info.ri_cprmask[3];
-}
-
-template <class ELFT>
-ErrorOr<MipsAbiFlags>
-MipsAbiInfoHandler<ELFT>::createAbiFlags(uint32_t flags,
- const Elf_Mips_ABIFlags *sec) {
- ErrorOr<MipsAbiFlags> hdrFlags = createAbiFromHeaderFlags(flags);
- if (auto ec = hdrFlags.getError())
- return ec;
- if (!sec)
- return *hdrFlags;
- ErrorOr<MipsAbiFlags> secFlags = createAbiFromSection(*sec);
- if (auto ec = secFlags.getError())
- return ec;
- if (!checkCompatibility(*hdrFlags, *secFlags))
- return *hdrFlags;
-
- _hasAbiSection = true;
-
- secFlags->_abi = hdrFlags->_abi;
- secFlags->_isPic = hdrFlags->_isPic;
- secFlags->_isCPic = hdrFlags->_isCPic;
- secFlags->_isNoReorder = hdrFlags->_isNoReorder;
- secFlags->_is32BitMode = hdrFlags->_is32BitMode;
- secFlags->_isNan2008 = hdrFlags->_isNan2008;
- return *secFlags;
-}
-
-template <class ELFT>
-ErrorOr<MipsAbiFlags>
-MipsAbiInfoHandler<ELFT>::createAbiFromHeaderFlags(uint32_t flags) {
- MipsAbiFlags abi;
- ErrorOr<MipsISAs> isa = headerFlagsToIsa(flags);
- if (auto ec = isa.getError())
- return ec;
- abi._isa = *isa;
-
- abi._fpAbi = Val_GNU_MIPS_ABI_FP_ANY;
- abi._cpr1Size = AFL_REG_NONE;
- abi._cpr2Size = AFL_REG_NONE;
- abi._gprSize = is32BitElfFlags(flags) ? AFL_REG_32 : AFL_REG_64;
-
- ErrorOr<uint32_t> ases = flagsToAses(flags);
- if (auto ec = ases.getError())
- return ec;
- abi._ases = *ases;
- abi._flags1 = 0;
- abi._abi = flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
- abi._isPic = flags & EF_MIPS_PIC;
- abi._isCPic = flags & EF_MIPS_CPIC;
- abi._isNoReorder = flags & EF_MIPS_NOREORDER;
- abi._is32BitMode = flags & EF_MIPS_32BITMODE;
- abi._isNan2008 = flags & EF_MIPS_NAN2008;
- return abi;
-}
-
-template <class ELFT>
-ErrorOr<MipsAbiFlags>
-MipsAbiInfoHandler<ELFT>::createAbiFromSection(const Elf_Mips_ABIFlags &sec) {
- MipsAbiFlags abi;
- ErrorOr<MipsISAs> isa =
- sectionFlagsToIsa(sec.isa_level, sec.isa_rev, sec.isa_ext);
- if (auto ec = isa.getError())
- return ec;
- abi._isa = *isa;
- abi._fpAbi = sec.fp_abi;
- abi._cpr1Size = sec.cpr1_size;
- abi._cpr2Size = sec.cpr2_size;
- abi._gprSize = sec.gpr_size;
- abi._ases = sec.ases;
- abi._flags1 = sec.flags1;
- if (sec.flags2 != 0)
- return make_dynamic_error_code("unexpected non-zero 'flags2' value");
- return abi;
-}
-
-template class MipsAbiInfoHandler<ELF32BE>;
-template class MipsAbiInfoHandler<ELF32LE>;
-template class MipsAbiInfoHandler<ELF64BE>;
-template class MipsAbiInfoHandler<ELF64LE>;
-
-}
-}
OpenPOWER on IntegriCloud