[Driver] Replace Target with TargetInfo. Simplify LinkerInput.
This removes Target and moves the functionality it had over to TargetInfo. This also simplifies LinkerInput by removing the InputKind. This will be handled elsewhere. llvm-svn: 174589
This commit is contained in:
parent
589baf98b4
commit
cfe59fd0d3
|
@ -29,38 +29,31 @@
|
|||
#include <vector>
|
||||
|
||||
namespace lld {
|
||||
enum class InputKind {
|
||||
Unknown,
|
||||
YAML,
|
||||
Native,
|
||||
Object,
|
||||
LLVM,
|
||||
Script
|
||||
};
|
||||
|
||||
/// \brief An input to the linker.
|
||||
///
|
||||
/// This class represents an input to the linker. It create the MemoryBuffer
|
||||
/// lazily when needed based on the file path. It can also take a MemoryBuffer
|
||||
/// directly.
|
||||
///
|
||||
/// The intent is that we only open each file once. And have strong ownership
|
||||
/// semantics.
|
||||
class LinkerInput {
|
||||
LinkerInput(const LinkerInput &) LLVM_DELETED_FUNCTION;
|
||||
|
||||
public:
|
||||
LinkerInput(StringRef file, InputKind kind = InputKind::Unknown)
|
||||
: _file(file)
|
||||
, _kind(kind) {}
|
||||
LinkerInput(StringRef file) : _file(file) {}
|
||||
|
||||
LinkerInput(std::unique_ptr<llvm::MemoryBuffer> buffer,
|
||||
InputKind kind = InputKind::Unknown)
|
||||
: _buffer(std::move(buffer))
|
||||
, _file(_buffer->getBufferIdentifier())
|
||||
, _kind(kind) {}
|
||||
LinkerInput(std::unique_ptr<llvm::MemoryBuffer> buffer)
|
||||
: _buffer(std::move(buffer)), _file(_buffer->getBufferIdentifier()) {
|
||||
}
|
||||
|
||||
LinkerInput(LinkerInput &&other)
|
||||
: _buffer(std::move(other._buffer))
|
||||
, _file(std::move(other._file))
|
||||
, _kind(other._kind) {}
|
||||
LinkerInput(LinkerInput && other)
|
||||
: _buffer(std::move(other._buffer)), _file(std::move(other._file)) {
|
||||
}
|
||||
|
||||
LinkerInput &operator=(LinkerInput &&rhs) {
|
||||
_buffer = std::move(rhs._buffer);
|
||||
_file = std::move(rhs._file);
|
||||
_kind = rhs._kind;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@ -75,33 +68,6 @@ public:
|
|||
return *_buffer;
|
||||
}
|
||||
|
||||
ErrorOr<InputKind> getKind() const {
|
||||
if (_kind == InputKind::Unknown) {
|
||||
_kind = llvm::StringSwitch<InputKind>(getPath())
|
||||
.EndsWith(".objtxt", InputKind::YAML)
|
||||
.EndsWith(".yaml", InputKind::YAML)
|
||||
.Default(InputKind::Unknown);
|
||||
|
||||
if (_kind != InputKind::Unknown)
|
||||
return _kind;
|
||||
|
||||
auto buf = getBuffer();
|
||||
if (!buf)
|
||||
return error_code(buf);
|
||||
|
||||
llvm::sys::fs::file_magic magic =
|
||||
llvm::sys::fs::identify_magic(buf->getBuffer());
|
||||
|
||||
switch (magic) {
|
||||
case llvm::sys::fs::file_magic::elf_relocatable:
|
||||
_kind = InputKind::Object;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return _kind;
|
||||
}
|
||||
|
||||
StringRef getPath() const {
|
||||
return _file;
|
||||
}
|
||||
|
@ -114,7 +80,6 @@ public:
|
|||
private:
|
||||
mutable std::unique_ptr<llvm::MemoryBuffer> _buffer;
|
||||
std::string _file;
|
||||
mutable InputKind _kind;
|
||||
};
|
||||
|
||||
enum OutputKind {
|
||||
|
|
|
@ -31,8 +31,11 @@ namespace llvm {
|
|||
}
|
||||
|
||||
namespace lld {
|
||||
class LinkerInput;
|
||||
struct LinkerOptions;
|
||||
class PassManager;
|
||||
class Reader;
|
||||
class Writer;
|
||||
|
||||
class TargetInfo {
|
||||
protected:
|
||||
|
@ -53,6 +56,14 @@ public:
|
|||
|
||||
virtual void addPasses(PassManager &pm) const {}
|
||||
|
||||
/// \brief Get a reference to a Reader for the given input.
|
||||
///
|
||||
/// Will always return the same object for the same input.
|
||||
virtual ErrorOr<Reader &> getReader(const LinkerInput &input) const = 0;
|
||||
|
||||
/// \brief Get the writer.
|
||||
virtual ErrorOr<Writer &> getWriter() const = 0;
|
||||
|
||||
// TODO: Split out to TargetRelocationInfo.
|
||||
virtual ErrorOr<int32_t> relocKindFromString(StringRef str) const {
|
||||
int32_t val;
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
//===- lld/Driver/Target.h - Linker Target Abstraction --------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
///
|
||||
/// Interface and factory for creating a specific Target. A Target is used to
|
||||
/// encapsulate all of the target specific configurations for the linker.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLD_DRIVER_TARGET_H
|
||||
#define LLD_DRIVER_TARGET_H
|
||||
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
|
||||
#include "llvm/Support/ErrorOr.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace lld {
|
||||
class LinkerInput;
|
||||
struct LinkerOptions;
|
||||
class Reader;
|
||||
class TargetInfo;
|
||||
class Writer;
|
||||
|
||||
/// \brief Represents a specific target.
|
||||
class Target {
|
||||
protected:
|
||||
Target(std::unique_ptr<TargetInfo> ti) : _targetInfo(std::move(ti)) {}
|
||||
|
||||
public:
|
||||
virtual ~Target();
|
||||
|
||||
const TargetInfo &getTargetInfo() const { return *_targetInfo; };
|
||||
|
||||
/// \brief Get a reference to a Reader for the given input.
|
||||
///
|
||||
/// Will always return the same object for the same input.
|
||||
virtual ErrorOr<lld::Reader&> getReader(const LinkerInput &input) = 0;
|
||||
|
||||
/// \brief Get the writer.
|
||||
virtual ErrorOr<lld::Writer&> getWriter() = 0;
|
||||
|
||||
static std::unique_ptr<Target> create(const LinkerOptions&);
|
||||
|
||||
protected:
|
||||
std::unique_ptr<TargetInfo> _targetInfo;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
|
@ -12,6 +12,9 @@
|
|||
|
||||
#include "lld/Core/LinkerOptions.h"
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
#include "llvm/Object/ELF.h"
|
||||
#include "llvm/Support/ELF.h"
|
||||
|
||||
|
@ -30,7 +33,7 @@ public:
|
|||
|
||||
class ELFTargetInfo : public TargetInfo {
|
||||
protected:
|
||||
ELFTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {}
|
||||
ELFTargetInfo(const LinkerOptions &lo);
|
||||
|
||||
public:
|
||||
uint16_t getOutputType() const;
|
||||
|
@ -44,6 +47,10 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
virtual ErrorOr<Reader &> getReader(const LinkerInput &input) const;
|
||||
|
||||
virtual ErrorOr<Writer &> getWriter() const;
|
||||
|
||||
static std::unique_ptr<ELFTargetInfo> create(const LinkerOptions &lo);
|
||||
|
||||
template <typename ELFT>
|
||||
|
@ -54,6 +61,8 @@ public:
|
|||
|
||||
protected:
|
||||
std::unique_ptr<TargetHandlerBase> _targetHandler;
|
||||
mutable std::unique_ptr<Reader> _reader;
|
||||
mutable std::unique_ptr<Writer> _writer;
|
||||
};
|
||||
} // end namespace lld
|
||||
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace lld {
|
||||
|
@ -28,6 +30,14 @@ public:
|
|||
|
||||
virtual uint64_t getPageZeroSize() const = 0;
|
||||
|
||||
virtual ErrorOr<Reader &> getReader(const LinkerInput &input) const {
|
||||
llvm_unreachable("Unimplemented!");
|
||||
}
|
||||
|
||||
virtual ErrorOr<Writer &> getWriter() const {
|
||||
llvm_unreachable("Unimplemented!");
|
||||
}
|
||||
|
||||
static std::unique_ptr<MachOTargetInfo> create(const LinkerOptions &lo);
|
||||
};
|
||||
} // end namespace lld
|
||||
|
|
|
@ -8,8 +8,6 @@ add_lld_library(lldDriver
|
|||
Driver.cpp
|
||||
Drivers.cpp
|
||||
LinkerInvocation.cpp
|
||||
Target.cpp
|
||||
Targets.cpp
|
||||
)
|
||||
|
||||
add_dependencies(lldDriver DriverOptionsTableGen)
|
||||
|
|
|
@ -218,7 +218,7 @@ LinkerOptions lld::generateOptions(const llvm::opt::ArgList &args) {
|
|||
for (llvm::opt::arg_iterator it = args.filtered_begin(ld::OPT_INPUT),
|
||||
ie = args.filtered_end();
|
||||
it != ie; ++it) {
|
||||
ret._input.push_back(LinkerInput((*it)->getValue(), InputKind::Object));
|
||||
ret._input.push_back(LinkerInput((*it)->getValue()));
|
||||
}
|
||||
|
||||
ret._llvmArgs = args.getAllArgValues(core::OPT_mllvm);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include "lld/Core/InputFiles.h"
|
||||
#include "lld/Core/PassManager.h"
|
||||
#include "lld/Core/Resolver.h"
|
||||
#include "lld/Driver/Target.h"
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
|
||||
|
@ -21,6 +21,12 @@
|
|||
|
||||
using namespace lld;
|
||||
|
||||
namespace {
|
||||
std::unique_ptr<TargetInfo> createTargetInfo(const LinkerOptions &lo) {
|
||||
return ELFTargetInfo::create(lo);
|
||||
}
|
||||
}
|
||||
|
||||
void LinkerInvocation::operator()() {
|
||||
// Honor -mllvm
|
||||
if (!_options._llvmArgs.empty()) {
|
||||
|
@ -34,9 +40,9 @@ void LinkerInvocation::operator()() {
|
|||
}
|
||||
|
||||
// Create target.
|
||||
std::unique_ptr<Target> target(Target::create(_options));
|
||||
std::unique_ptr<TargetInfo> targetInfo(createTargetInfo(_options));
|
||||
|
||||
if (!target) {
|
||||
if (!targetInfo) {
|
||||
llvm::errs() << "Failed to create target for " << _options._target
|
||||
<< "\n";
|
||||
return;
|
||||
|
@ -45,7 +51,7 @@ void LinkerInvocation::operator()() {
|
|||
// Read inputs
|
||||
InputFiles inputs;
|
||||
for (const auto &input : _options._input) {
|
||||
auto reader = target->getReader(input);
|
||||
auto reader = targetInfo->getReader(input);
|
||||
if (error_code ec = reader) {
|
||||
llvm::errs() << "Failed to get reader for: " << input.getPath() << ": "
|
||||
<< ec.message() << "\n";
|
||||
|
@ -69,17 +75,17 @@ void LinkerInvocation::operator()() {
|
|||
inputs.appendFiles(files);
|
||||
}
|
||||
|
||||
auto writer = target->getWriter();
|
||||
auto writer = targetInfo->getWriter();
|
||||
|
||||
// Give writer a chance to add files
|
||||
writer->addFiles(inputs);
|
||||
|
||||
Resolver resolver(target->getTargetInfo(), inputs);
|
||||
Resolver resolver(*targetInfo, inputs);
|
||||
resolver.resolve();
|
||||
MutableFile &merged = resolver.resultFile();
|
||||
|
||||
PassManager pm;
|
||||
target->getTargetInfo().addPasses(pm);
|
||||
targetInfo->addPasses(pm);
|
||||
pm.runOnFile(merged);
|
||||
|
||||
if (error_code ec = writer) {
|
||||
|
|
|
@ -1,14 +0,0 @@
|
|||
//===- lib/Driver/Target.cpp - Linker Target Abstraction ------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Driver/Target.h"
|
||||
|
||||
using namespace lld;
|
||||
|
||||
Target::~Target() {}
|
|
@ -1,92 +0,0 @@
|
|||
//===- lib/Driver/Targets.cpp - Linker Targets ----------------------------===//
|
||||
//
|
||||
// The LLVM Linker
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
///
|
||||
/// Concrete instances of the Target interface.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "lld/Driver/Target.h"
|
||||
|
||||
#include "lld/Core/LinkerOptions.h"
|
||||
#include "lld/Core/TargetInfo.h"
|
||||
#include "lld/ReaderWriter/Reader.h"
|
||||
#include "lld/ReaderWriter/Writer.h"
|
||||
#include "lld/ReaderWriter/ELFTargetInfo.h"
|
||||
|
||||
#include "llvm/ADT/Triple.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
using namespace lld;
|
||||
using namespace std::placeholders;
|
||||
|
||||
class ELFTarget : public Target {
|
||||
public:
|
||||
ELFTarget(std::unique_ptr<ELFTargetInfo> ti)
|
||||
: Target(std::unique_ptr<TargetInfo>(ti.get())),
|
||||
_elfTargetInfo(*ti.release()), _readerELF(createReaderELF(
|
||||
_elfTargetInfo, std::bind(&ELFTarget::getReader, this, _1))),
|
||||
_readerYAML(createReaderYAML(*_targetInfo)),
|
||||
_writer(createWriterELF(_elfTargetInfo)),
|
||||
_writerYAML(createWriterYAML(*_targetInfo)) {
|
||||
}
|
||||
|
||||
virtual ErrorOr<lld::Reader&> getReader(const LinkerInput &input) {
|
||||
auto kind = input.getKind();
|
||||
if (!kind)
|
||||
return error_code(kind);
|
||||
|
||||
if (*kind == InputKind::YAML)
|
||||
return *_readerYAML;
|
||||
|
||||
if (*kind == InputKind::Object)
|
||||
return *_readerELF;
|
||||
|
||||
return llvm::make_error_code(llvm::errc::invalid_argument);
|
||||
}
|
||||
|
||||
virtual ErrorOr<lld::Writer&> getWriter() {
|
||||
return _targetInfo->getLinkerOptions()._outputYAML ? *_writerYAML
|
||||
: *_writer;
|
||||
}
|
||||
|
||||
protected:
|
||||
const ELFTargetInfo &_elfTargetInfo;
|
||||
std::unique_ptr<lld::Reader> _readerELF, _readerYAML;
|
||||
std::unique_ptr<lld::Writer> _writer, _writerYAML;
|
||||
};
|
||||
|
||||
class X86LinuxTarget LLVM_FINAL : public ELFTarget {
|
||||
public:
|
||||
X86LinuxTarget(std::unique_ptr<ELFTargetInfo> ti)
|
||||
: ELFTarget(std::move(ti)) {}
|
||||
};
|
||||
|
||||
class HexagonTarget LLVM_FINAL : public ELFTarget {
|
||||
public:
|
||||
HexagonTarget(std::unique_ptr<ELFTargetInfo> ti)
|
||||
: ELFTarget(std::move(ti)) {}
|
||||
};
|
||||
|
||||
std::unique_ptr<Target> Target::create(const LinkerOptions &lo) {
|
||||
llvm::Triple t(lo._target);
|
||||
// Create a TargetInfo.
|
||||
std::unique_ptr<ELFTargetInfo> ti(ELFTargetInfo::create(lo));
|
||||
|
||||
// Create the Target
|
||||
if (t.getOS() == llvm::Triple::Linux && (t.getArch() == llvm::Triple::x86 ||
|
||||
t.getArch() == llvm::Triple::x86_64))
|
||||
return std::unique_ptr<Target>(new X86LinuxTarget(std::move(ti)));
|
||||
else if (t.getArch() == llvm::Triple::hexagon)
|
||||
return std::unique_ptr<Target>(new HexagonTarget(std::move(ti)));
|
||||
return std::unique_ptr<Target>();
|
||||
}
|
|
@ -18,6 +18,8 @@
|
|||
#include "llvm/Support/ELF.h"
|
||||
|
||||
namespace lld {
|
||||
ELFTargetInfo::ELFTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {}
|
||||
|
||||
uint16_t ELFTargetInfo::getOutputType() const {
|
||||
switch (_options._outputKind) {
|
||||
case OutputKind::Executable:
|
||||
|
@ -52,6 +54,23 @@ uint16_t ELFTargetInfo::getOutputMachine() const {
|
|||
}
|
||||
}
|
||||
|
||||
ErrorOr<Reader &> ELFTargetInfo::getReader(const LinkerInput &input) const {
|
||||
if (!_reader)
|
||||
_reader = createReaderELF(*this, std::bind(&ELFTargetInfo::getReader, this,
|
||||
std::placeholders::_1));
|
||||
return *_reader;
|
||||
}
|
||||
|
||||
ErrorOr<Writer &> ELFTargetInfo::getWriter() const {
|
||||
if (!_writer) {
|
||||
if (_options._outputYAML)
|
||||
_writer = createWriterYAML(*this);
|
||||
else
|
||||
_writer = createWriterELF(*this);
|
||||
}
|
||||
return *_writer;
|
||||
}
|
||||
|
||||
std::unique_ptr<ELFTargetInfo> ELFTargetInfo::create(const LinkerOptions &lo) {
|
||||
switch (llvm::Triple(llvm::Triple::normalize(lo._target)).getArch()) {
|
||||
case llvm::Triple::x86:
|
||||
|
|
|
@ -195,6 +195,15 @@ public:
|
|||
}
|
||||
return llvm::make_error_code(llvm::errc::invalid_argument);
|
||||
}
|
||||
|
||||
virtual ErrorOr<Reader &> getReader(const LinkerInput &input) const {
|
||||
llvm_unreachable("Unimplemented!");
|
||||
}
|
||||
|
||||
virtual ErrorOr<Writer &> getWriter() const {
|
||||
llvm_unreachable("Unimplemented!");
|
||||
}
|
||||
|
||||
private:
|
||||
bool _doStubs;
|
||||
bool _doGOT;
|
||||
|
|
Loading…
Reference in New Issue