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
#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;
}
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;
}
private:
mutable std::unique_ptr<llvm::MemoryBuffer> _buffer;
std::string _file;
- mutable InputKind _kind;
};
enum OutputKind {
}
namespace lld {
+class LinkerInput;
struct LinkerOptions;
class PassManager;
+class Reader;
+class Writer;
class TargetInfo {
protected:
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;
+++ /dev/null
-//===- 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
#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"
class ELFTargetInfo : public TargetInfo {
protected:
- ELFTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {}
+ ELFTargetInfo(const LinkerOptions &lo);
public:
uint16_t getOutputType() const;
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>
protected:
std::unique_ptr<TargetHandlerBase> _targetHandler;
+ mutable std::unique_ptr<Reader> _reader;
+ mutable std::unique_ptr<Writer> _writer;
};
} // end namespace lld
#include "lld/Core/TargetInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+
#include <memory>
namespace lld {
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
Driver.cpp
Drivers.cpp
LinkerInvocation.cpp
- Target.cpp
- Targets.cpp
)
add_dependencies(lldDriver DriverOptionsTableGen)
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);
#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"
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()) {
}
// 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;
// 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";
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) {
+++ /dev/null
-//===- 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() {}
+++ /dev/null
-//===- 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>();
-}
#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:
}
}
+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:
}
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;