blob: ae82e905d2d0513f49ee3490810506f573f86927 [file] [log] [blame]
//===- 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/ReaderWriter/ReaderArchive.h"
#include "lld/ReaderWriter/ReaderELF.h"
#include "lld/ReaderWriter/ReaderYAML.h"
#include "lld/ReaderWriter/WriterELF.h"
#include "lld/ReaderWriter/WriterYAML.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/raw_ostream.h"
#include <set>
using namespace lld;
class X86LinuxTarget LLVM_FINAL : public Target {
public:
X86LinuxTarget(const LinkerOptions &lo) : Target(lo), _woe(lo._entrySymbol) {
_readerELF.reset(createReaderELF(_roe, _roa));
_readerYAML.reset(createReaderYAML(_roy));
_writer.reset(createWriterELF(_woe));
_writerYAML.reset(createWriterYAML(_woy));
}
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 _options._outputYAML ? *_writerYAML : *_writer;
}
private:
lld::ReaderOptionsELF _roe;
lld::ReaderOptionsArchive _roa;
struct : lld::ReaderOptionsYAML {
virtual Reference::Kind kindFromString(StringRef kindName) const {
int k;
if (kindName.getAsInteger(0, k))
k = 0;
return k;
}
} _roy;
struct WOpts : lld::WriterOptionsELF {
WOpts(StringRef entry) {
_endianness = llvm::support::little;
_is64Bit = false;
_type = llvm::ELF::ET_EXEC;
_machine = llvm::ELF::EM_386;
_entryPoint = entry;
}
} _woe;
struct WYOpts : lld::WriterOptionsYAML {
virtual StringRef kindToString(Reference::Kind k) const {
std::string str;
llvm::raw_string_ostream rso(str);
rso << (unsigned)k;
rso.flush();
return *_strings.insert(str).first;
}
mutable std::set<std::string> _strings;
} _woy;
std::unique_ptr<lld::Reader> _readerELF, _readerYAML;
std::unique_ptr<lld::Writer> _writer, _writerYAML;
};
class X86_64LinuxTarget LLVM_FINAL : public Target {
public:
X86_64LinuxTarget(const LinkerOptions &lo)
: Target(lo), _woe(lo._entrySymbol) {
_readerELF.reset(createReaderELF(_roe, _roa));
_readerYAML.reset(createReaderYAML(_roy));
_writer.reset(createWriterELF(_woe));
_writerYAML.reset(createWriterYAML(_woy));
}
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 _options._outputYAML ? *_writerYAML : *_writer;
}
private:
lld::ReaderOptionsELF _roe;
lld::ReaderOptionsArchive _roa;
struct : lld::ReaderOptionsYAML {
virtual Reference::Kind kindFromString(StringRef kindName) const {
int k;
if (kindName.getAsInteger(0, k))
k = 0;
return k;
}
} _roy;
struct WOpts : lld::WriterOptionsELF {
WOpts(StringRef entry) {
_endianness = llvm::support::little;
_is64Bit = true;
_type = llvm::ELF::ET_EXEC;
_machine = llvm::ELF::EM_X86_64;
_entryPoint = entry;
}
} _woe;
struct WYOpts : lld::WriterOptionsYAML {
virtual StringRef kindToString(Reference::Kind k) const {
std::string str;
llvm::raw_string_ostream rso(str);
rso << (unsigned)k;
rso.flush();
return *_strings.insert(str).first;
}
mutable std::set<std::string> _strings;
} _woy;
std::unique_ptr<lld::Reader> _readerELF, _readerYAML;
std::unique_ptr<lld::Writer> _writer, _writerYAML;
};
class HexagonTarget LLVM_FINAL : public Target {
public:
HexagonTarget(const LinkerOptions &lo)
: Target(lo), _woe(lo._entrySymbol) {
_readerELF.reset(createReaderELF(_roe, _roa));
_readerYAML.reset(createReaderYAML(_roy));
_writer.reset(createWriterELF(_woe));
_writerYAML.reset(createWriterYAML(_woy));
}
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 _options._outputYAML ? *_writerYAML : *_writer;
}
private:
lld::ReaderOptionsELF _roe;
lld::ReaderOptionsArchive _roa;
struct : lld::ReaderOptionsYAML {
virtual Reference::Kind kindFromString(StringRef kindName) const {
int k;
if (kindName.getAsInteger(0, k))
k = 0;
return k;
}
} _roy;
struct WOpts : lld::WriterOptionsELF {
WOpts(StringRef entry) {
_endianness = llvm::support::little;
_is64Bit = false;
_type = llvm::ELF::ET_EXEC;
_machine = llvm::ELF::EM_HEXAGON;
_entryPoint = entry;
}
} _woe;
struct WYOpts : lld::WriterOptionsYAML {
virtual StringRef kindToString(Reference::Kind k) const {
std::string str;
llvm::raw_string_ostream rso(str);
rso << (unsigned)k;
rso.flush();
return *_strings.insert(str).first;
}
mutable std::set<std::string> _strings;
} _woy;
std::unique_ptr<lld::Reader> _readerELF, _readerYAML;
std::unique_ptr<lld::Writer> _writer, _writerYAML;
};
std::unique_ptr<Target> Target::create(const LinkerOptions &lo) {
llvm::Triple t(lo._target);
if (t.getOS() == llvm::Triple::Linux && t.getArch() == llvm::Triple::x86)
return std::unique_ptr<Target>(new X86LinuxTarget(lo));
else if (t.getOS() == llvm::Triple::Linux &&
t.getArch() == llvm::Triple::x86_64)
return std::unique_ptr<Target>(new X86_64LinuxTarget(lo));
else if (t.getArch() == llvm::Triple::hexagon)
return std::unique_ptr<Target>(new HexagonTarget(lo));
return std::unique_ptr<Target>();
}