From d68d6196afc47b3fe0a0953d4d7fa08cfc90f17e Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Tue, 22 Jan 2013 02:15:30 +0000 Subject: [PATCH] Add {,ELF,MachO}TargetInfo. llvm-svn: 173117 --- lld/include/lld/{Driver => Core}/LinkerOptions.h | 70 +++++++++++++++++--- lld/include/lld/Core/TargetInfo.h | 79 +++++++++++++++++++++++ lld/include/lld/Driver/LinkerInvocation.h | 2 +- lld/include/lld/Driver/Target.h | 2 +- lld/include/lld/ReaderWriter/ELFTargetInfo.h | 30 +++++++++ lld/include/lld/ReaderWriter/MachOTargetInfo.h | 32 ++++++++++ lld/lib/Core/CMakeLists.txt | 1 + lld/lib/Core/TargetInfo.cpp | 35 ++++++++++ lld/lib/Driver/Drivers.cpp | 2 +- lld/lib/Driver/Targets.cpp | 1 + lld/lib/ReaderWriter/ELF/CMakeLists.txt | 1 + lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp | 81 ++++++++++++++++++++++++ lld/lib/ReaderWriter/MachO/CMakeLists.txt | 1 + lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp | 62 ++++++++++++++++++ 14 files changed, 387 insertions(+), 12 deletions(-) rename lld/include/lld/{Driver => Core}/LinkerOptions.h (58%) create mode 100644 lld/include/lld/Core/TargetInfo.h create mode 100644 lld/include/lld/ReaderWriter/ELFTargetInfo.h create mode 100644 lld/include/lld/ReaderWriter/MachOTargetInfo.h create mode 100644 lld/lib/Core/TargetInfo.cpp create mode 100644 lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp create mode 100644 lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp diff --git a/lld/include/lld/Driver/LinkerOptions.h b/lld/include/lld/Core/LinkerOptions.h similarity index 58% rename from lld/include/lld/Driver/LinkerOptions.h rename to lld/include/lld/Core/LinkerOptions.h index 6e49ac2..57bf322 100644 --- a/lld/include/lld/Driver/LinkerOptions.h +++ b/lld/include/lld/Core/LinkerOptions.h @@ -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 buffer, + InputKind kind = InputKind::Unknown) + : _buffer(std::move(buffer)) , _file(_buffer->getBufferIdentifier()) , _kind(kind) {} @@ -105,37 +106,88 @@ public: return _file; } + std::unique_ptr takeBuffer() { + getBuffer(); + return std::move(_buffer); + } + private: mutable std::unique_ptr _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 _input; std::vector _llvmArgs; + std::vector _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; diff --git a/lld/include/lld/Core/TargetInfo.h b/lld/include/lld/Core/TargetInfo.h new file mode 100644 index 0000000..d181d60 --- /dev/null +++ b/lld/include/lld/Core/TargetInfo.h @@ -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 + +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 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 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 diff --git a/lld/include/lld/Driver/LinkerInvocation.h b/lld/include/lld/Driver/LinkerInvocation.h index d543ebb..7a1b56a 100644 --- a/lld/include/lld/Driver/LinkerInvocation.h +++ b/lld/include/lld/Driver/LinkerInvocation.h @@ -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 { diff --git a/lld/include/lld/Driver/Target.h b/lld/include/lld/Driver/Target.h index 5b06aee..65defd6 100644 --- a/lld/include/lld/Driver/Target.h +++ b/lld/include/lld/Driver/Target.h @@ -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. diff --git a/lld/include/lld/ReaderWriter/ELFTargetInfo.h b/lld/include/lld/ReaderWriter/ELFTargetInfo.h new file mode 100644 index 0000000..be877d3 --- /dev/null +++ b/lld/include/lld/ReaderWriter/ELFTargetInfo.h @@ -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 + +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 create(const LinkerOptions &lo); +}; +} // end namespace lld + +#endif diff --git a/lld/include/lld/ReaderWriter/MachOTargetInfo.h b/lld/include/lld/ReaderWriter/MachOTargetInfo.h new file mode 100644 index 0000000..aaa06fa5 --- /dev/null +++ b/lld/include/lld/ReaderWriter/MachOTargetInfo.h @@ -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 + +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 create(const LinkerOptions &lo); +}; +} // end namespace lld + +#endif diff --git a/lld/lib/Core/CMakeLists.txt b/lld/lib/Core/CMakeLists.txt index 877da26..44becf4 100644 --- a/lld/lib/Core/CMakeLists.txt +++ b/lld/lib/Core/CMakeLists.txt @@ -7,4 +7,5 @@ add_lld_library(lldCore InputFiles.cpp Resolver.cpp SymbolTable.cpp + TargetInfo.cpp ) diff --git a/lld/lib/Core/TargetInfo.cpp b/lld/lib/Core/TargetInfo.cpp new file mode 100644 index 0000000..da834fb --- /dev/null +++ b/lld/lib/Core/TargetInfo.cpp @@ -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 diff --git a/lld/lib/Driver/Drivers.cpp b/lld/lib/Driver/Drivers.cpp index 83fb83c..2063878 100644 --- a/lld/lib/Driver/Drivers.cpp +++ b/lld/lib/Driver/Drivers.cpp @@ -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" diff --git a/lld/lib/Driver/Targets.cpp b/lld/lib/Driver/Targets.cpp index 68cb553..ae82e90 100644 --- a/lld/lib/Driver/Targets.cpp +++ b/lld/lib/Driver/Targets.cpp @@ -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" diff --git a/lld/lib/ReaderWriter/ELF/CMakeLists.txt b/lld/lib/ReaderWriter/ELF/CMakeLists.txt index f69929e..aa3e54c 100644 --- a/lld/lib/ReaderWriter/ELF/CMakeLists.txt +++ b/lld/lib/ReaderWriter/ELF/CMakeLists.txt @@ -1,4 +1,5 @@ add_lld_library(lldELF + ELFTargetInfo.cpp HexagonReference.cpp PPCReference.cpp ReaderELF.cpp diff --git a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp new file mode 100644 index 0000000..9a086f8 --- /dev/null +++ b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp @@ -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::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(new X86ELFTargetInfo(lo)); + case llvm::Triple::hexagon: + return std::unique_ptr(new HexagonELFTargetInfo(lo)); + case llvm::Triple::ppc: + return std::unique_ptr(new PPCELFTargetInfo(lo)); + default: + return std::unique_ptr(); + } +} +} // end namespace lld diff --git a/lld/lib/ReaderWriter/MachO/CMakeLists.txt b/lld/lib/ReaderWriter/MachO/CMakeLists.txt index c315ecc..db64d87 100644 --- a/lld/lib/ReaderWriter/MachO/CMakeLists.txt +++ b/lld/lib/ReaderWriter/MachO/CMakeLists.txt @@ -1,4 +1,5 @@ add_lld_library(lldMachO + MachOTargetInfo.cpp WriterMachO.cpp WriterOptionsMachO.cpp ReferenceKinds.cpp diff --git a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp new file mode 100644 index 0000000..d24680a --- /dev/null +++ b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp @@ -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::create(const LinkerOptions &lo) { + return std::unique_ptr(new GenericMachOTargetInfo(lo)); +} +} // end namespace lld -- 2.7.4