The function took either StringRef or Twine. Since string literals are
ambiguous when resolving the overloading, many code calls used this
function with explicit type conversion. That led awkward code like
make_dynamic_error_code(Twine("Error occurred")).
This patch adds a function definition for string literals, so that
you can directly call the function with literals.
llvm-svn: 234841
150 lines
4.5 KiB
C++
150 lines
4.5 KiB
C++
//===- lib/ReaderWriter/ELF/MipsELFFlagsMerger.cpp ------------------------===//
|
|
//
|
|
// The LLVM Linker
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "MipsELFFlagsMerger.h"
|
|
#include "lld/Core/Error.h"
|
|
#include "llvm/ADT/Twine.h"
|
|
#include "llvm/Support/ELF.h"
|
|
#include "llvm/Support/raw_ostream.h"
|
|
|
|
using namespace lld;
|
|
using namespace lld::elf;
|
|
using namespace llvm::ELF;
|
|
|
|
struct MipsISATreeEdge {
|
|
unsigned child;
|
|
unsigned parent;
|
|
};
|
|
|
|
static MipsISATreeEdge isaTree[] = {
|
|
// MIPS32R6 and MIPS64R6 are not compatible with other extensions
|
|
|
|
// MIPS64 extensions.
|
|
{EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
|
|
// MIPS V extensions.
|
|
{EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
|
|
// MIPS IV extensions.
|
|
{EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
|
|
// MIPS III extensions.
|
|
{EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
|
|
// MIPS32 extensions.
|
|
{EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
|
|
// MIPS II extensions.
|
|
{EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
|
|
{EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
|
|
// MIPS I extensions.
|
|
{EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
|
|
};
|
|
|
|
static bool matchMipsISA(unsigned base, unsigned ext) {
|
|
if (base == ext)
|
|
return true;
|
|
if (base == EF_MIPS_ARCH_32 && matchMipsISA(EF_MIPS_ARCH_64, ext))
|
|
return true;
|
|
if (base == EF_MIPS_ARCH_32R2 && matchMipsISA(EF_MIPS_ARCH_64R2, ext))
|
|
return true;
|
|
for (const auto &edge : isaTree) {
|
|
if (ext == edge.child) {
|
|
ext = edge.parent;
|
|
if (ext == base)
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
MipsELFFlagsMerger::MipsELFFlagsMerger(bool is64Bits)
|
|
: _is64Bit(is64Bits), _flags(0) {}
|
|
|
|
uint32_t MipsELFFlagsMerger::getMergedELFFlags() const { return _flags; }
|
|
|
|
std::error_code MipsELFFlagsMerger::mergeHeaderFlags(uint8_t newClass,
|
|
uint32_t newFlags) {
|
|
// Check bitness.
|
|
if (_is64Bit != (newClass == ELFCLASS64))
|
|
return make_dynamic_error_code(
|
|
"Bitness is incompatible with that of the selected target");
|
|
|
|
// We support two ABI: O32 and N64. The last one does not have
|
|
// the corresponding ELF flag.
|
|
uint32_t inAbi = newFlags & EF_MIPS_ABI;
|
|
uint32_t supportedAbi = _is64Bit ? 0 : uint32_t(EF_MIPS_ABI_O32);
|
|
if (inAbi != supportedAbi)
|
|
return make_dynamic_error_code("Unsupported ABI");
|
|
|
|
// ... and reduced set of architectures ...
|
|
uint32_t newArch = newFlags & EF_MIPS_ARCH;
|
|
switch (newArch) {
|
|
case EF_MIPS_ARCH_1:
|
|
case EF_MIPS_ARCH_2:
|
|
case EF_MIPS_ARCH_3:
|
|
case EF_MIPS_ARCH_4:
|
|
case EF_MIPS_ARCH_5:
|
|
case EF_MIPS_ARCH_32:
|
|
case EF_MIPS_ARCH_64:
|
|
case EF_MIPS_ARCH_32R2:
|
|
case EF_MIPS_ARCH_64R2:
|
|
case EF_MIPS_ARCH_32R6:
|
|
case EF_MIPS_ARCH_64R6:
|
|
break;
|
|
default:
|
|
return make_dynamic_error_code("Unsupported instruction set");
|
|
}
|
|
|
|
// ... and still do not support MIPS-16 extension.
|
|
if (newFlags & EF_MIPS_ARCH_ASE_M16)
|
|
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 (newFlags & EF_MIPS_PIC)
|
|
newFlags |= EF_MIPS_CPIC;
|
|
|
|
std::lock_guard<std::mutex> lock(_mutex);
|
|
|
|
// If the old set of flags is empty, use the new one as a result.
|
|
if (!_flags) {
|
|
_flags = newFlags;
|
|
return std::error_code();
|
|
}
|
|
|
|
// Check PIC / CPIC flags compatibility.
|
|
uint32_t newPic = newFlags & (EF_MIPS_PIC | EF_MIPS_CPIC);
|
|
uint32_t oldPic = _flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
|
|
|
|
if ((newPic != 0) != (oldPic != 0))
|
|
llvm::errs() << "lld warning: linking abicalls and non-abicalls files\n";
|
|
|
|
if (!(newPic & EF_MIPS_PIC))
|
|
_flags &= ~EF_MIPS_PIC;
|
|
if (newPic)
|
|
_flags |= EF_MIPS_CPIC;
|
|
|
|
// Check mixing -mnan=2008 / -mnan=legacy modules.
|
|
if ((newFlags & EF_MIPS_NAN2008) != (_flags & EF_MIPS_NAN2008))
|
|
return make_dynamic_error_code(
|
|
"Linking -mnan=2008 and -mnan=legacy modules");
|
|
|
|
// Check ISA compatibility and update the extension flag.
|
|
uint32_t oldArch = _flags & EF_MIPS_ARCH;
|
|
if (!matchMipsISA(newArch, oldArch)) {
|
|
if (!matchMipsISA(oldArch, newArch))
|
|
return make_dynamic_error_code("Linking modules with incompatible ISA");
|
|
_flags &= ~EF_MIPS_ARCH;
|
|
_flags |= newArch;
|
|
}
|
|
|
|
_flags |= newFlags & EF_MIPS_NOREORDER;
|
|
_flags |= newFlags & EF_MIPS_MICROMIPS;
|
|
_flags |= newFlags & EF_MIPS_NAN2008;
|
|
_flags |= newFlags & EF_MIPS_32BITMODE;
|
|
|
|
return std::error_code();
|
|
}
|