Add {,ELF,MachO}TargetInfo.

llvm-svn: 173117
This commit is contained in:
Michael J. Spencer 2013-01-22 02:15:30 +00:00
parent df0b43d1f9
commit d68d6196af
14 changed files with 387 additions and 12 deletions

View File

@ -1,4 +1,4 @@
//===- lld/Driver/LinkerOptions.h - Linker Options ------------------------===//
//===- lld/Core/LinkerOptions.h - Linker Options --------------------------===//
//
// The LLVM Linker
//
@ -13,8 +13,8 @@
///
//===----------------------------------------------------------------------===//
#ifndef LLD_DRIVER_LINKER_OPTIONS_H
#define LLD_DRIVER_LINKER_OPTIONS_H
#ifndef LLD_CORE_LINKER_OPTIONS_H
#define LLD_CORE_LINKER_OPTIONS_H
#include "lld/Core/LLVM.h"
@ -46,8 +46,9 @@ public:
: _file(file)
, _kind(kind) {}
LinkerInput(llvm::MemoryBuffer *buffer, InputKind kind = InputKind::Unknown)
: _buffer(buffer)
LinkerInput(std::unique_ptr<llvm::MemoryBuffer> buffer,
InputKind kind = InputKind::Unknown)
: _buffer(std::move(buffer))
, _file(_buffer->getBufferIdentifier())
, _kind(kind) {}
@ -105,37 +106,88 @@ public:
return _file;
}
std::unique_ptr<llvm::MemoryBuffer> takeBuffer() {
getBuffer();
return std::move(_buffer);
}
private:
mutable std::unique_ptr<llvm::MemoryBuffer> _buffer;
std::string _file;
mutable InputKind _kind;
};
enum class OutputKind {
Executable,
Relocatable,
Shared,
};
struct LinkerOptions {
LinkerOptions() {}
LinkerOptions()
: _baseAddress(0)
, _outputKind(OutputKind::Executable)
, _outputCommands(false)
, _outputYAML(false)
, _noInhibitExec(true)
, _deadStrip(false)
, _globalsAreDeadStripRoots(false)
, _searchArchivesToOverrideTentativeDefinitions(false)
, _searchSharedLibrariesToOverrideTentativeDefinitions(false)
, _warnIfCoalesableAtomsHaveDifferentCanBeNull(false)
, _warnIfCoalesableAtomsHaveDifferentLoadName(false)
, _forceLoadArchives(false)
, _textRelocations(false)
, _relocatable(false) {}
// This exists because MSVC doesn't support = default :(
LinkerOptions(LinkerOptions &&other)
: _input(std::move(other._input))
, _llvmArgs(std::move(other._llvmArgs))
, _deadStripRoots(std::move(other._deadStripRoots))
, _target(std::move(other._target))
, _outputPath(std::move(other._outputPath))
, _entrySymbol(std::move(other._entrySymbol))
, _relocatable(other._relocatable)
, _baseAddress(other._baseAddress)
, _outputKind(other._outputKind)
, _outputCommands(other._outputCommands)
, _outputYAML(other._outputYAML)
, _noInhibitExec(other._noInhibitExec) {}
, _noInhibitExec(other._noInhibitExec)
, _deadStrip(other._deadStrip)
, _globalsAreDeadStripRoots(other._globalsAreDeadStripRoots)
, _searchArchivesToOverrideTentativeDefinitions(
other._searchArchivesToOverrideTentativeDefinitions)
, _searchSharedLibrariesToOverrideTentativeDefinitions(
other._searchSharedLibrariesToOverrideTentativeDefinitions)
, _warnIfCoalesableAtomsHaveDifferentCanBeNull(
other._warnIfCoalesableAtomsHaveDifferentCanBeNull)
, _warnIfCoalesableAtomsHaveDifferentLoadName(
other._warnIfCoalesableAtomsHaveDifferentLoadName)
, _forceLoadArchives(other._forceLoadArchives)
, _textRelocations(other._textRelocations)
, _relocatable(other._relocatable) {}
std::vector<LinkerInput> _input;
std::vector<std::string> _llvmArgs;
std::vector<std::string> _deadStripRoots;
std::string _target;
std::string _outputPath;
std::string _entrySymbol;
unsigned _relocatable : 1;
uint64_t _baseAddress;
OutputKind _outputKind : 2;
/// \brief -###
unsigned _outputCommands : 1;
unsigned _outputYAML : 1;
unsigned _noInhibitExec : 1;
unsigned _deadStrip : 1;
unsigned _globalsAreDeadStripRoots : 1;
unsigned _searchArchivesToOverrideTentativeDefinitions : 1;
unsigned _searchSharedLibrariesToOverrideTentativeDefinitions : 1;
unsigned _warnIfCoalesableAtomsHaveDifferentCanBeNull : 1;
unsigned _warnIfCoalesableAtomsHaveDifferentLoadName : 1;
unsigned _forceLoadArchives : 1;
unsigned _textRelocations : 1;
unsigned _relocatable : 1;
private:
LinkerOptions(const LinkerOptions&) LLVM_DELETED_FUNCTION;

View File

@ -0,0 +1,79 @@
//===- lld/Core/TargetInfo.h - Linker Target Info Interface ---------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// Interface for target specific information to be used be readers, writers,
/// and the resolver.
///
//===----------------------------------------------------------------------===//
#ifndef LLD_CORE_TARGET_INFO_H
#define LLD_CORE_TARGET_INFO_H
#include "lld/Core/Error.h"
#include "lld/Core/LLVM.h"
#include "llvm/Support/DataTypes.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
namespace llvm {
class Triple;
}
namespace lld {
struct LinkerOptions;
class GOTPass;
class StubsPass;
class TargetInfo {
protected:
TargetInfo(const LinkerOptions &lo) : _options(lo) {}
public:
virtual ~TargetInfo();
const LinkerOptions &getLinkerOptions() const { return _options; }
llvm::Triple getTriple() const;
virtual bool is64Bits() const;
virtual bool isLittleEndian() const;
virtual uint64_t getPageSize() const = 0;
virtual StringRef getEntry() const;
virtual StubsPass *getStubPass() const { return nullptr; }
virtual GOTPass *getGOTPass() const { return nullptr; }
// TODO: Split out to TargetRelocationInfo.
virtual ErrorOr<uint32_t> relocKindFromString(StringRef str) const {
uint32_t val;
if (str.getAsInteger(10, val))
return llvm::make_error_code(llvm::errc::invalid_argument);
return val;
}
virtual ErrorOr<std::string> stringFromRelocKind(uint32_t kind) const {
std::string s;
llvm::raw_string_ostream str(s);
str << kind;
str.flush();
return s;
}
protected:
const LinkerOptions &_options;
};
} // end namespace lld
#endif

View File

@ -16,7 +16,7 @@
#ifndef LLD_DRIVER_LINKER_INVOCATION_H
#define LLD_DRIVER_LINKER_INVOCATION_H
#include "lld/Driver/LinkerOptions.h"
#include "lld/Core/LinkerOptions.h"
namespace lld {
class LinkerInvocation {

View File

@ -17,9 +17,9 @@
#ifndef LLD_DRIVER_TARGET_H
#define LLD_DRIVER_TARGET_H
#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/Reader.h"
#include "lld/ReaderWriter/Writer.h"
#include "lld/Driver/LinkerOptions.h"
namespace lld {
/// \brief Represents a specific target.

View File

@ -0,0 +1,30 @@
//===- lld/ReaderWriter/ELFTargetInfo.h -----------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_TARGET_INFO_H
#define LLD_READER_WRITER_ELF_TARGET_INFO_H
#include "lld/Core/TargetInfo.h"
#include <memory>
namespace lld {
class ELFTargetInfo : public TargetInfo {
protected:
ELFTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {}
public:
uint16_t getOutputType() const;
uint16_t getOutputMachine() const;
static std::unique_ptr<ELFTargetInfo> create(const LinkerOptions &lo);
};
} // end namespace lld
#endif

View File

@ -0,0 +1,32 @@
//===- lld/ReaderWriter/MachOTargetInfo.h ---------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_MACHO_TARGET_INFO_H
#define LLD_READER_WRITER_MACHO_TARGET_INFO_H
#include "lld/Core/TargetInfo.h"
#include <memory>
namespace lld {
class MachOTargetInfo : public TargetInfo {
protected:
MachOTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {}
public:
uint32_t getCPUType() const;
uint32_t getCPUSubType() const;
virtual uint64_t getPageZeroSize() const = 0;
static std::unique_ptr<MachOTargetInfo> create(const LinkerOptions &lo);
};
} // end namespace lld
#endif

View File

@ -7,4 +7,5 @@ add_lld_library(lldCore
InputFiles.cpp
Resolver.cpp
SymbolTable.cpp
TargetInfo.cpp
)

View File

@ -0,0 +1,35 @@
//===- lib/Core/TargetInfo.cpp - Linker Target Info Interface -------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lld/Core/TargetInfo.h"
#include "lld/Core/LinkerOptions.h"
#include "llvm/ADT/Triple.h"
namespace lld {
TargetInfo::~TargetInfo() {}
llvm::Triple TargetInfo::getTriple() const {
return llvm::Triple(llvm::Triple::normalize(_options._target));
}
bool TargetInfo::is64Bits() const {
return getTriple().isArch64Bit();
}
bool TargetInfo::isLittleEndian() const {
// TODO: Do this properly. It is not defined purely by arch.
return true;
}
StringRef TargetInfo::getEntry() const {
return _options._entrySymbol;
}
} // end namespace lld

View File

@ -15,7 +15,7 @@
#include "lld/Driver/Driver.h"
#include "lld/Driver/LinkerOptions.h"
#include "lld/Core/LinkerOptions.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"

View File

@ -15,6 +15,7 @@
#include "lld/Driver/Target.h"
#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/ReaderArchive.h"
#include "lld/ReaderWriter/ReaderELF.h"
#include "lld/ReaderWriter/ReaderYAML.h"

View File

@ -1,4 +1,5 @@
add_lld_library(lldELF
ELFTargetInfo.cpp
HexagonReference.cpp
PPCReference.cpp
ReaderELF.cpp

View File

@ -0,0 +1,81 @@
//===- lib/ReaderWriter/ELF/ELFTargetInfo.cpp -----------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "lld/Core/LinkerOptions.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ELF.h"
namespace lld {
uint16_t ELFTargetInfo::getOutputType() const {
switch (_options._outputKind) {
case OutputKind::Executable:
return llvm::ELF::ET_EXEC;
case OutputKind::Relocatable:
return llvm::ELF::ET_REL;
case OutputKind::Shared:
return llvm::ELF::ET_DYN;
}
llvm_unreachable("Unhandled OutputKind");
}
uint16_t ELFTargetInfo::getOutputMachine() const {
switch (getTriple().getArch()) {
case llvm::Triple::x86:
return llvm::ELF::EM_386;
case llvm::Triple::x86_64:
return llvm::ELF::EM_X86_64;
case llvm::Triple::hexagon:
return llvm::ELF::EM_HEXAGON;
case llvm::Triple::ppc:
return llvm::ELF::EM_PPC;
default:
llvm_unreachable("Unhandled arch");
}
}
class X86ELFTargetInfo final : public ELFTargetInfo {
public:
X86ELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {}
virtual uint64_t getPageSize() const { return 0x1000; }
};
class HexagonELFTargetInfo final : public ELFTargetInfo {
public:
HexagonELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {}
virtual uint64_t getPageSize() const { return 0x1000; }
};
class PPCELFTargetInfo final : public ELFTargetInfo {
public:
PPCELFTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {}
virtual bool isLittleEndian() const { return false; }
virtual uint64_t getPageSize() const { return 0x1000; }
};
std::unique_ptr<ELFTargetInfo> ELFTargetInfo::create(const LinkerOptions &lo) {
switch (llvm::Triple(llvm::Triple::normalize(lo._target)).getArch()) {
case llvm::Triple::x86:
case llvm::Triple::x86_64:
return std::unique_ptr<ELFTargetInfo>(new X86ELFTargetInfo(lo));
case llvm::Triple::hexagon:
return std::unique_ptr<ELFTargetInfo>(new HexagonELFTargetInfo(lo));
case llvm::Triple::ppc:
return std::unique_ptr<ELFTargetInfo>(new PPCELFTargetInfo(lo));
default:
return std::unique_ptr<ELFTargetInfo>();
}
}
} // end namespace lld

View File

@ -1,4 +1,5 @@
add_lld_library(lldMachO
MachOTargetInfo.cpp
WriterMachO.cpp
WriterOptionsMachO.cpp
ReferenceKinds.cpp

View File

@ -0,0 +1,62 @@
//===- lib/ReaderWriter/MachO/MachOTargetInfo.cpp -------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lld/ReaderWriter/MachOTargetInfo.h"
#include "lld/Core/LinkerOptions.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/MachO.h"
namespace lld {
uint32_t MachOTargetInfo::getCPUType() const {
switch (getTriple().getArch()) {
case llvm::Triple::x86:
return llvm::MachO::CPUTypeI386;
case llvm::Triple::x86_64:
return llvm::MachO::CPUTypeX86_64;
case llvm::Triple::arm:
return llvm::MachO::CPUTypeARM;
default:
llvm_unreachable("Unknown arch type");
}
}
uint32_t MachOTargetInfo::getCPUSubType() const {
switch (getTriple().getArch()) {
case llvm::Triple::x86:
return llvm::MachO::CPUSubType_I386_ALL;
case llvm::Triple::x86_64:
return llvm::MachO::CPUSubType_X86_64_ALL;
case llvm::Triple::arm:
return llvm::MachO::CPUSubType_ARM_ALL;
default:
llvm_unreachable("Unknown arch type");
}
}
class GenericMachOTargetInfo final : public MachOTargetInfo {
public:
GenericMachOTargetInfo(const LinkerOptions &lo) : MachOTargetInfo(lo) {}
virtual uint64_t getPageSize() const { return 0x1000; }
virtual uint64_t getPageZeroSize() const { return getPageSize(); }
virtual StringRef getEntry() const {
if (!_options._entrySymbol.empty())
return _options._entrySymbol;
return "_main";
}
};
std::unique_ptr<MachOTargetInfo>
MachOTargetInfo::create(const LinkerOptions &lo) {
return std::unique_ptr<MachOTargetInfo>(new GenericMachOTargetInfo(lo));
}
} // end namespace lld