llvm-project/lld/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp
Simon Atanasyan c88db09cc5 [Mips] Take into account that PIC code is inherently CPIC
Follow-up to r221439.

llvm-svn: 221442
2014-11-06 07:07:29 +00:00

93 lines
3.1 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;
MipsELFFlagsMerger::MipsELFFlagsMerger() : _flags(0) {}
uint32_t MipsELFFlagsMerger::getMergedELFFlags() const { return _flags; }
std::error_code MipsELFFlagsMerger::merge(uint8_t newClass, uint32_t newFlags) {
// Reject 64-bit binaries.
if (newClass != llvm::ELF::ELFCLASS32)
return make_dynamic_error_code(
Twine("Bitness is incompatible with that of the selected target"));
// We support the only ABI - O32 ...
uint32_t abi = newFlags & llvm::ELF::EF_MIPS_ABI;
if (abi != llvm::ELF::EF_MIPS_ABI_O32)
return make_dynamic_error_code(Twine("Unsupported ABI"));
// ... and reduced set of architectures ...
uint32_t newArch = newFlags & llvm::ELF::EF_MIPS_ARCH;
switch (newArch) {
case llvm::ELF::EF_MIPS_ARCH_1:
case llvm::ELF::EF_MIPS_ARCH_2:
case llvm::ELF::EF_MIPS_ARCH_32:
case llvm::ELF::EF_MIPS_ARCH_32R2:
case llvm::ELF::EF_MIPS_ARCH_32R6:
break;
default:
return make_dynamic_error_code(Twine("Unsupported architecture"));
}
// ... and still do not support MIPS-16 extension.
if (newFlags & llvm::ELF::EF_MIPS_ARCH_ASE_M16)
return make_dynamic_error_code(Twine("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 & llvm::ELF::EF_MIPS_PIC)
newFlags |= llvm::ELF::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 & (llvm::ELF::EF_MIPS_PIC | llvm::ELF::EF_MIPS_CPIC);
uint32_t oldPic = _flags & (llvm::ELF::EF_MIPS_PIC | llvm::ELF::EF_MIPS_CPIC);
if ((newPic != 0) != (oldPic != 0))
llvm::errs() << "lld warning: linking abicalls and non-abicalls files\n";
if (!(newPic & llvm::ELF::EF_MIPS_PIC))
_flags &= ~llvm::ELF::EF_MIPS_PIC;
if (newPic)
_flags |= llvm::ELF::EF_MIPS_CPIC;
// Check mixing -mnan=2008 / -mnan=legacy modules.
if ((newFlags & llvm::ELF::EF_MIPS_NAN2008) !=
(_flags & llvm::ELF::EF_MIPS_NAN2008))
return make_dynamic_error_code(
Twine("Linking -mnan=2008 and -mnan=legacy modules"));
// Set the "largest" ISA.
uint32_t oldArch = _flags & llvm::ELF::EF_MIPS_ARCH;
_flags |= std::max(newArch, oldArch);
_flags |= newFlags & llvm::ELF::EF_MIPS_NOREORDER;
_flags |= newFlags & llvm::ELF::EF_MIPS_MICROMIPS;
_flags |= newFlags & llvm::ELF::EF_MIPS_NAN2008;
return std::error_code();
}