diff --git a/lld/include/lld/Core/AbsoluteAtom.h b/lld/include/lld/Core/AbsoluteAtom.h deleted file mode 100644 --- a/lld/include/lld/Core/AbsoluteAtom.h +++ /dev/null @@ -1,42 +0,0 @@ -//===- Core/AbsoluteAtom.h - An absolute Atom -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_ABSOLUTE_ATOM_H -#define LLD_CORE_ABSOLUTE_ATOM_H - -#include "lld/Core/Atom.h" - -namespace lld { - -/// An AbsoluteAtom has no content. -/// It exists to represent content at fixed addresses in memory. -class AbsoluteAtom : public Atom { -public: - - virtual uint64_t value() const = 0; - - /// scope - The visibility of this atom to other atoms. C static functions - /// have scope scopeTranslationUnit. Regular C functions have scope - /// scopeGlobal. Functions compiled with visibility=hidden have scope - /// scopeLinkageUnit so they can be see by other atoms being linked but not - /// by the OS loader. - virtual Scope scope() const = 0; - - static bool classof(const Atom *a) { - return a->definition() == definitionAbsolute; - } - - static bool classof(const AbsoluteAtom *) { return true; } - -protected: - AbsoluteAtom() : Atom(definitionAbsolute) {} -}; - -} // namespace lld - -#endif // LLD_CORE_ABSOLUTE_ATOM_H diff --git a/lld/include/lld/Core/ArchiveLibraryFile.h b/lld/include/lld/Core/ArchiveLibraryFile.h deleted file mode 100644 --- a/lld/include/lld/Core/ArchiveLibraryFile.h +++ /dev/null @@ -1,46 +0,0 @@ -//===- Core/ArchiveLibraryFile.h - Models static library ------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_ARCHIVE_LIBRARY_FILE_H -#define LLD_CORE_ARCHIVE_LIBRARY_FILE_H - -#include "lld/Core/File.h" -#include - -namespace lld { - -/// -/// The ArchiveLibraryFile subclass of File is used to represent unix -/// static library archives. These libraries provide no atoms to the -/// initial set of atoms linked. Instead, when the Resolver will query -/// ArchiveLibraryFile instances for specific symbols names using the -/// find() method. If the archive contains an object file which has a -/// DefinedAtom whose scope is not translationUnit, then that entire -/// object file File is returned. -/// -class ArchiveLibraryFile : public File { -public: - static bool classof(const File *f) { - return f->kind() == kindArchiveLibrary; - } - - /// Check if any member of the archive contains an Atom with the - /// specified name and return the File object for that member, or nullptr. - virtual File *find(StringRef name) = 0; - - virtual std::error_code - parseAllMembers(std::vector> &result) = 0; - -protected: - /// only subclasses of ArchiveLibraryFile can be instantiated - ArchiveLibraryFile(StringRef path) : File(path, kindArchiveLibrary) {} -}; - -} // namespace lld - -#endif // LLD_CORE_ARCHIVE_LIBRARY_FILE_H diff --git a/lld/include/lld/Core/Atom.h b/lld/include/lld/Core/Atom.h deleted file mode 100644 --- a/lld/include/lld/Core/Atom.h +++ /dev/null @@ -1,130 +0,0 @@ -//===- Core/Atom.h - A node in linking graph --------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_ATOM_H -#define LLD_CORE_ATOM_H - -#include "lld/Common/LLVM.h" -#include "llvm/ADT/StringRef.h" - -namespace lld { - -class File; - -template -class OwningAtomPtr; - -/// -/// The linker has a Graph Theory model of linking. An object file is seen -/// as a set of Atoms with References to other Atoms. Each Atom is a node -/// and each Reference is an edge. An Atom can be a DefinedAtom which has -/// content or a UndefinedAtom which is a placeholder and represents an -/// undefined symbol (extern declaration). -/// -class Atom { - template friend class OwningAtomPtr; - -public: - /// Whether this atom is defined or a proxy for an undefined symbol - enum Definition { - definitionRegular, ///< Normal C/C++ function or global variable. - definitionAbsolute, ///< Asm-only (foo = 10). Not tied to any content. - definitionUndefined, ///< Only in .o files to model reference to undef. - definitionSharedLibrary ///< Only in shared libraries to model export. - }; - - /// The scope in which this atom is accessible to other atoms. - enum Scope { - scopeTranslationUnit, ///< Accessible only to atoms in the same translation - /// unit (e.g. a C static). - scopeLinkageUnit, ///< Accessible to atoms being linked but not visible - /// to runtime loader (e.g. visibility=hidden). - scopeGlobal ///< Accessible to all atoms and visible to runtime - /// loader (e.g. visibility=default). - }; - - /// file - returns the File that produced/owns this Atom - virtual const File& file() const = 0; - - /// name - The name of the atom. For a function atom, it is the (mangled) - /// name of the function. - virtual StringRef name() const = 0; - - /// definition - Whether this atom is a definition or represents an undefined - /// symbol. - Definition definition() const { return _definition; } - - static bool classof(const Atom *a) { return true; } - -protected: - /// Atom is an abstract base class. Only subclasses can access constructor. - explicit Atom(Definition def) : _definition(def) {} - - /// The memory for Atom objects is always managed by the owning File - /// object. Therefore, no one but the owning File object should call - /// delete on an Atom. In fact, some File objects may bulk allocate - /// an array of Atoms, so they cannot be individually deleted by anyone. - virtual ~Atom() = default; - -private: - Definition _definition; -}; - -/// Class which owns an atom pointer and runs the atom destructor when the -/// owning pointer goes out of scope. -template -class OwningAtomPtr { -private: - OwningAtomPtr(const OwningAtomPtr &) = delete; - void operator=(const OwningAtomPtr &) = delete; - -public: - OwningAtomPtr() = default; - OwningAtomPtr(T *atom) : atom(atom) { } - - ~OwningAtomPtr() { - if (atom) - runDestructor(atom); - } - - void runDestructor(Atom *atom) { - atom->~Atom(); - } - - OwningAtomPtr(OwningAtomPtr &&ptr) : atom(ptr.atom) { - ptr.atom = nullptr; - } - - void operator=(OwningAtomPtr&& ptr) { - if (atom) - runDestructor(atom); - atom = ptr.atom; - ptr.atom = nullptr; - } - - T *const &get() const { - return atom; - } - - T *&get() { - return atom; - } - - T *release() { - auto *v = atom; - atom = nullptr; - return v; - } - -private: - T *atom = nullptr; -}; - -} // end namespace lld - -#endif // LLD_CORE_ATOM_H diff --git a/lld/include/lld/Core/DefinedAtom.h b/lld/include/lld/Core/DefinedAtom.h deleted file mode 100644 --- a/lld/include/lld/Core/DefinedAtom.h +++ /dev/null @@ -1,373 +0,0 @@ -//===- Core/DefinedAtom.h - An Atom with content --------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_DEFINED_ATOM_H -#define LLD_CORE_DEFINED_ATOM_H - -#include "lld/Common/LLVM.h" -#include "lld/Core/Atom.h" -#include "lld/Core/Reference.h" -#include "llvm/Support/ErrorHandling.h" - -namespace lld { -class File; - -/// The fundamental unit of linking. -/// -/// A C function or global variable is an atom. An atom has content and -/// attributes. The content of a function atom is the instructions that -/// implement the function. The content of a global variable atom is its -/// initial bytes. -/// -/// Here are some example attribute sets for common atoms. If a particular -/// attribute is not listed, the default values are: definition=regular, -/// sectionChoice=basedOnContent, scope=translationUnit, merge=no, -/// deadStrip=normal, interposable=no -/// -/// C function: void foo() {}
-/// name=foo, type=code, perm=r_x, scope=global -/// -/// C static function: staic void func() {}
-/// name=func, type=code, perm=r_x -/// -/// C global variable: int count = 1;
-/// name=count, type=data, perm=rw_, scope=global -/// -/// C tentative definition: int bar;
-/// name=bar, type=zerofill, perm=rw_, scope=global, -/// merge=asTentative, interposable=yesAndRuntimeWeak -/// -/// Uninitialized C static variable: static int stuff;
-/// name=stuff, type=zerofill, perm=rw_ -/// -/// Weak C function: __attribute__((weak)) void foo() {}
-/// name=foo, type=code, perm=r_x, scope=global, merge=asWeak -/// -/// Hidden C function: __attribute__((visibility("hidden"))) void foo() {}
-/// name=foo, type=code, perm=r_x, scope=linkageUnit -/// -/// No-dead-strip function: __attribute__((used)) void foo() {}
-/// name=foo, type=code, perm=r_x, scope=global, deadStrip=never -/// -/// Non-inlined C++ inline method: inline void Foo::doit() {}
-/// name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global, -/// mergeDupes=asWeak -/// -/// Non-inlined C++ inline method whose address is taken: -/// inline void Foo::doit() {}
-/// name=_ZN3Foo4doitEv, type=code, perm=r_x, scope=global, -/// mergeDupes=asAddressedWeak -/// -/// literal c-string: "hello"
-/// name="" type=cstring, perm=r__, scope=linkageUnit -/// -/// literal double: 1.234
-/// name="" type=literal8, perm=r__, scope=linkageUnit -/// -/// constant: { 1,2,3 }
-/// name="" type=constant, perm=r__, scope=linkageUnit -/// -/// Pointer to initializer function:
-/// name="" type=initializer, perm=rw_l, -/// sectionChoice=customRequired -/// -/// C function place in custom section: __attribute__((section("__foo"))) -/// void foo() {}
-/// name=foo, type=code, perm=r_x, scope=global, -/// sectionChoice=customRequired, customSectionName=__foo -/// -class DefinedAtom : public Atom { -public: - enum Interposable { - interposeNo, // linker can directly bind uses of this atom - interposeYes, // linker must indirect (through GOT) uses - interposeYesAndRuntimeWeak // must indirect and mark symbol weak in final - // linked image - }; - - enum Merge { - mergeNo, // Another atom with same name is error - mergeAsTentative, // Is ANSI C tentative definition, can be coalesced - mergeAsWeak, // Is C++ inline definition that was not inlined, - // but address was not taken, so atom can be hidden - // by linker - mergeAsWeakAndAddressUsed, // Is C++ definition inline definition whose - // address was taken. - mergeSameNameAndSize, // Another atom with different size is error - mergeByLargestSection, // Choose an atom whose section is the largest. - mergeByContent, // Merge with other constants with same content. - }; - - enum ContentType { - typeUnknown, // for use with definitionUndefined - typeMachHeader, // atom representing mach_header [Darwin] - typeCode, // executable code - typeResolver, // function which returns address of target - typeBranchIsland, // linker created for large binaries - typeBranchShim, // linker created to switch thumb mode - typeStub, // linker created for calling external function - typeStubHelper, // linker created for initial stub binding - typeConstant, // a read-only constant - typeCString, // a zero terminated UTF8 C string - typeUTF16String, // a zero terminated UTF16 string - typeCFI, // a FDE or CIE from dwarf unwind info - typeLSDA, // extra unwinding info - typeLiteral4, // a four-btye read-only constant - typeLiteral8, // an eight-btye read-only constant - typeLiteral16, // a sixteen-btye read-only constant - typeData, // read-write data - typeDataFast, // allow data to be quickly accessed - typeZeroFill, // zero-fill data - typeZeroFillFast, // allow zero-fill data to be quicky accessed - typeConstData, // read-only data after dynamic linker is done - typeObjC1Class, // ObjC1 class [Darwin] - typeLazyPointer, // pointer through which a stub jumps - typeLazyDylibPointer, // pointer through which a stub jumps [Darwin] - typeNonLazyPointer, // pointer to external symbol - typeCFString, // NS/CFString object [Darwin] - typeGOT, // pointer to external symbol - typeInitializerPtr, // pointer to initializer function - typeTerminatorPtr, // pointer to terminator function - typeCStringPtr, // pointer to UTF8 C string [Darwin] - typeObjCClassPtr, // pointer to ObjC class [Darwin] - typeObjC2CategoryList, // pointers to ObjC category [Darwin] - typeObjCImageInfo, // pointer to ObjC class [Darwin] - typeObjCMethodList, // pointer to ObjC method list [Darwin] - typeDTraceDOF, // runtime data for Dtrace [Darwin] - typeInterposingTuples, // tuples of interposing info for dyld [Darwin] - typeTempLTO, // temporary atom for bitcode reader - typeCompactUnwindInfo, // runtime data for unwinder [Darwin] - typeProcessedUnwindInfo,// compressed compact unwind info [Darwin] - typeThunkTLV, // thunk used to access a TLV [Darwin] - typeTLVInitialData, // initial data for a TLV [Darwin] - typeTLVInitialZeroFill, // TLV initial zero fill data [Darwin] - typeTLVInitializerPtr, // pointer to thread local initializer [Darwin] - typeDSOHandle, // atom representing DSO handle [Darwin] - typeSectCreate, // Created via the -sectcreate option [Darwin] - }; - - // Permission bits for atoms and segments. The order of these values are - // important, because the layout pass may sort atoms by permission if other - // attributes are the same. - enum ContentPermissions { - perm___ = 0, // mapped as unaccessible - permR__ = 8, // mapped read-only - permRW_ = 8 + 2, // mapped readable and writable - permRW_L = 8 + 2 + 1, // initially mapped r/w, then made read-only - // loader writable - permR_X = 8 + 4, // mapped readable and executable - permRWX = 8 + 2 + 4, // mapped readable and writable and executable - permUnknown = 16 // unknown or invalid permissions - }; - - enum SectionChoice { - sectionBasedOnContent, // linker infers final section based on content - sectionCustomPreferred, // linker may place in specific section - sectionCustomRequired // linker must place in specific section - }; - - enum DeadStripKind { - deadStripNormal, // linker may dead strip this atom - deadStripNever, // linker must never dead strip this atom - deadStripAlways // linker must remove this atom if unused - }; - - enum DynamicExport { - /// The linker may or may not export this atom dynamically depending - /// on the output type and other context of the link. - dynamicExportNormal, - /// The linker will always export this atom dynamically. - dynamicExportAlways, - }; - - // Attributes describe a code model used by the atom. - enum CodeModel { - codeNA, // no specific code model - // MIPS code models - codeMipsPIC, // PIC function in a PIC / non-PIC mixed file - codeMipsMicro, // microMIPS instruction encoding - codeMipsMicroPIC, // microMIPS instruction encoding + PIC - codeMips16, // MIPS-16 instruction encoding - // ARM code models - codeARMThumb, // ARM Thumb instruction set - codeARM_a, // $a-like mapping symbol (for ARM code) - codeARM_d, // $d-like mapping symbol (for data) - codeARM_t, // $t-like mapping symbol (for Thumb code) - }; - - struct Alignment { - Alignment(int v, int m = 0) : value(v), modulus(m) {} - - uint16_t value; - uint16_t modulus; - - bool operator==(const Alignment &rhs) const { - return (value == rhs.value) && (modulus == rhs.modulus); - } - }; - - /// returns a value for the order of this Atom within its file. - /// - /// This is used by the linker to order the layout of Atoms so that the - /// resulting image is stable and reproducible. - virtual uint64_t ordinal() const = 0; - - /// the number of bytes of space this atom's content will occupy in the - /// final linked image. - /// - /// For a function atom, it is the number of bytes of code in the function. - virtual uint64_t size() const = 0; - - /// The size of the section from which the atom is instantiated. - /// - /// Merge::mergeByLargestSection is defined in terms of section size - /// and not in terms of atom size, so we need this function separate - /// from size(). - virtual uint64_t sectionSize() const { return 0; } - - /// The visibility of this atom to other atoms. - /// - /// C static functions have scope scopeTranslationUnit. Regular C functions - /// have scope scopeGlobal. Functions compiled with visibility=hidden have - /// scope scopeLinkageUnit so they can be see by other atoms being linked but - /// not by the OS loader. - virtual Scope scope() const = 0; - - /// Whether the linker should use direct or indirect access to this - /// atom. - virtual Interposable interposable() const = 0; - - /// how the linker should handle if multiple atoms have the same name. - virtual Merge merge() const = 0; - - /// The type of this atom, such as code or data. - virtual ContentType contentType() const = 0; - - /// The alignment constraints on how this atom must be laid out in the - /// final linked image (e.g. 16-byte aligned). - virtual Alignment alignment() const = 0; - - /// Whether this atom must be in a specially named section in the final - /// linked image, or if the linker can infer the section based on the - /// contentType(). - virtual SectionChoice sectionChoice() const = 0; - - /// If sectionChoice() != sectionBasedOnContent, then this return the - /// name of the section the atom should be placed into. - virtual StringRef customSectionName() const = 0; - - /// constraints on whether the linker may dead strip away this atom. - virtual DeadStripKind deadStrip() const = 0; - - /// Under which conditions should this atom be dynamically exported. - virtual DynamicExport dynamicExport() const { - return dynamicExportNormal; - } - - /// Code model used by the atom. - virtual CodeModel codeModel() const { return codeNA; } - - /// Returns the OS memory protections required for this atom's content - /// at runtime. - /// - /// A function atom is R_X, a global variable is RW_, and a read-only constant - /// is R__. - virtual ContentPermissions permissions() const; - - /// returns a reference to the raw (unrelocated) bytes of this Atom's - /// content. - virtual ArrayRef rawContent() const = 0; - - /// This class abstracts iterating over the sequence of References - /// in an Atom. Concrete instances of DefinedAtom must implement - /// the derefIterator() and incrementIterator() methods. - class reference_iterator { - public: - reference_iterator(const DefinedAtom &a, const void *it) - : _atom(a), _it(it) { } - - const Reference *operator*() const { - return _atom.derefIterator(_it); - } - - const Reference *operator->() const { - return _atom.derefIterator(_it); - } - - bool operator==(const reference_iterator &other) const { - return _it == other._it; - } - - bool operator!=(const reference_iterator &other) const { - return !(*this == other); - } - - reference_iterator &operator++() { - _atom.incrementIterator(_it); - return *this; - } - private: - const DefinedAtom &_atom; - const void *_it; - }; - - /// Returns an iterator to the beginning of this Atom's References. - virtual reference_iterator begin() const = 0; - - /// Returns an iterator to the end of this Atom's References. - virtual reference_iterator end() const = 0; - - /// Adds a reference to this atom. - virtual void addReference(Reference::KindNamespace ns, - Reference::KindArch arch, - Reference::KindValue kindValue, uint64_t off, - const Atom *target, Reference::Addend a) { - llvm_unreachable("Subclass does not permit adding references"); - } - - static bool classof(const Atom *a) { - return a->definition() == definitionRegular; - } - - /// Utility for deriving permissions from content type - static ContentPermissions permissions(ContentType type); - - /// Utility function to check if the atom occupies file space - bool occupiesDiskSpace() const { - ContentType atomContentType = contentType(); - return !(atomContentType == DefinedAtom::typeZeroFill || - atomContentType == DefinedAtom::typeZeroFillFast || - atomContentType == DefinedAtom::typeTLVInitialZeroFill); - } - - /// Utility function to check if relocations in this atom to other defined - /// atoms can be implicitly generated, and so we don't need to explicitly - /// emit those relocations. - bool relocsToDefinedCanBeImplicit() const { - ContentType atomContentType = contentType(); - return atomContentType == typeCFI; - } - -protected: - // DefinedAtom is an abstract base class. Only subclasses can access - // constructor. - DefinedAtom() : Atom(definitionRegular) { } - - ~DefinedAtom() override = default; - - /// Returns a pointer to the Reference object that the abstract - /// iterator "points" to. - virtual const Reference *derefIterator(const void *iter) const = 0; - - /// Adjusts the abstract iterator to "point" to the next Reference - /// object for this Atom. - virtual void incrementIterator(const void *&iter) const = 0; -}; -} // end namespace lld - -#endif diff --git a/lld/include/lld/Core/Error.h b/lld/include/lld/Core/Error.h deleted file mode 100644 --- a/lld/include/lld/Core/Error.h +++ /dev/null @@ -1,67 +0,0 @@ -//===- Error.h - system_error extensions for lld ----------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This declares a new error_category for the lld library. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_ERROR_H -#define LLD_CORE_ERROR_H - -#include "lld/Common/LLVM.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/Error.h" -#include - -namespace lld { - -const std::error_category &YamlReaderCategory(); - -enum class YamlReaderError { - unknown_keyword, - illegal_value -}; - -inline std::error_code make_error_code(YamlReaderError e) { - return std::error_code(static_cast(e), YamlReaderCategory()); -} - -/// Creates an error_code object that has associated with it an arbitrary -/// error message. The value() of the error_code will always be non-zero -/// but its value is meaningless. The message() will be (a copy of) the -/// supplied error string. -/// Note: Once ErrorOr<> is updated to work with errors other than error_code, -/// this can be updated to return some other kind of error. -std::error_code make_dynamic_error_code(StringRef msg); - -/// Generic error. -/// -/// For errors that don't require their own specific sub-error (most errors) -/// this class can be used to describe the error via a string message. -class GenericError : public llvm::ErrorInfo { -public: - static char ID; - GenericError(Twine Msg); - const std::string &getMessage() const { return Msg; } - void log(llvm::raw_ostream &OS) const override; - - std::error_code convertToErrorCode() const override { - return make_dynamic_error_code(getMessage()); - } - -private: - std::string Msg; -}; - -} // end namespace lld - -namespace std { -template <> struct is_error_code_enum : std::true_type {}; -} - -#endif diff --git a/lld/include/lld/Core/File.h b/lld/include/lld/Core/File.h deleted file mode 100644 --- a/lld/include/lld/Core/File.h +++ /dev/null @@ -1,276 +0,0 @@ -//===- Core/File.h - A Container of Atoms ---------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_FILE_H -#define LLD_CORE_FILE_H - -#include "lld/Core/AbsoluteAtom.h" -#include "lld/Core/DefinedAtom.h" -#include "lld/Core/SharedLibraryAtom.h" -#include "lld/Core/UndefinedAtom.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include -#include - -namespace lld { - -class LinkingContext; - -/// Every Atom is owned by some File. A common scenario is for a single -/// object file (.o) to be parsed by some reader and produce a single -/// File object that represents the content of that object file. -/// -/// To iterate through the Atoms in a File there are four methods that -/// return collections. For instance to iterate through all the DefinedAtoms -/// in a File object use: -/// for (const DefinedAtoms *atom : file->defined()) { -/// } -/// -/// The Atom objects in a File are owned by the File object. The Atom objects -/// are destroyed when the File object is destroyed. -class File { -public: - virtual ~File(); - - /// Kinds of files that are supported. - enum Kind { - kindErrorObject, ///< a error object file (.o) - kindNormalizedObject, ///< a normalized file (.o) - kindMachObject, ///< a MachO object file (.o) - kindCEntryObject, ///< a file for CEntries - kindHeaderObject, ///< a file for file headers - kindEntryObject, ///< a file for the entry - kindUndefinedSymsObject, ///< a file for undefined symbols - kindStubHelperObject, ///< a file for stub helpers - kindResolverMergedObject, ///< the resolver merged file. - kindSectCreateObject, ///< a sect create object file (.o) - kindSharedLibrary, ///< shared library (.so) - kindArchiveLibrary ///< archive (.a) - }; - - /// Returns file kind. Need for dyn_cast<> on File objects. - Kind kind() const { - return _kind; - } - - /// This returns the path to the file which was used to create this object - /// (e.g. "/tmp/foo.o"). If the file is a member of an archive file, the - /// returned string includes the archive file name. - StringRef path() const { - if (_archivePath.empty()) - return _path; - if (_archiveMemberPath.empty()) - _archiveMemberPath = (_archivePath + "(" + _path + ")").str(); - return _archiveMemberPath; - } - - /// Returns the path of the archive file name if this file is instantiated - /// from an archive file. Otherwise returns the empty string. - StringRef archivePath() const { return _archivePath; } - void setArchivePath(StringRef path) { _archivePath = std::string(path); } - - /// Returns the path name of this file. It doesn't include archive file name. - StringRef memberPath() const { return _path; } - - /// Returns the command line order of the file. - uint64_t ordinal() const { - assert(_ordinal != UINT64_MAX); - return _ordinal; - } - - /// Returns true/false depending on whether an ordinal has been set. - bool hasOrdinal() const { return (_ordinal != UINT64_MAX); } - - /// Sets the command line order of the file. - void setOrdinal(uint64_t ordinal) const { _ordinal = ordinal; } - - /// Returns the ordinal for the next atom to be defined in this file. - uint64_t getNextAtomOrdinalAndIncrement() const { - return _nextAtomOrdinal++; - } - - /// For allocating any objects owned by this File. - llvm::BumpPtrAllocator &allocator() const { - return _allocator; - } - - /// The type of atom mutable container. - template using AtomVector = std::vector>; - - /// The range type for the atoms. - template class AtomRange { - public: - AtomRange(AtomVector &v) : _v(v) {} - AtomRange(const AtomVector &v) : _v(const_cast &>(v)) {} - - using ConstDerefFn = const T* (*)(const OwningAtomPtr&); - using DerefFn = T* (*)(OwningAtomPtr&); - - typedef llvm::mapped_iterator::const_iterator, - ConstDerefFn> ConstItTy; - typedef llvm::mapped_iterator::iterator, - DerefFn> ItTy; - - static const T* DerefConst(const OwningAtomPtr &p) { - return p.get(); - } - - static T* Deref(OwningAtomPtr &p) { - return p.get(); - } - - ConstItTy begin() const { - return ConstItTy(_v.begin(), ConstDerefFn(DerefConst)); - } - ConstItTy end() const { - return ConstItTy(_v.end(), ConstDerefFn(DerefConst)); - } - - ItTy begin() { - return ItTy(_v.begin(), DerefFn(Deref)); - } - ItTy end() { - return ItTy(_v.end(), DerefFn(Deref)); - } - - llvm::iterator_range::iterator> owning_ptrs() { - return llvm::make_range(_v.begin(), _v.end()); - } - - llvm::iterator_range::iterator> owning_ptrs() const { - return llvm::make_range(_v.begin(), _v.end()); - } - - bool empty() const { - return _v.empty(); - } - - size_t size() const { - return _v.size(); - } - - const OwningAtomPtr &operator[](size_t idx) const { - return _v[idx]; - } - - OwningAtomPtr &operator[](size_t idx) { - return _v[idx]; - } - - private: - AtomVector &_v; - }; - - /// Must be implemented to return the AtomVector object for - /// all DefinedAtoms in this File. - virtual const AtomRange defined() const = 0; - - /// Must be implemented to return the AtomVector object for - /// all UndefinedAtomw in this File. - virtual const AtomRange undefined() const = 0; - - /// Must be implemented to return the AtomVector object for - /// all SharedLibraryAtoms in this File. - virtual const AtomRange sharedLibrary() const = 0; - - /// Must be implemented to return the AtomVector object for - /// all AbsoluteAtoms in this File. - virtual const AtomRange absolute() const = 0; - - /// Drop all of the atoms owned by this file. This will result in all of - /// the atoms running their destructors. - /// This is required because atoms may be allocated on a BumpPtrAllocator - /// of a different file. We need to destruct all atoms before any files. - virtual void clearAtoms() = 0; - - /// If a file is parsed using a different method than doParse(), - /// one must use this method to set the last error status, so that - /// doParse will not be called twice. Only YAML reader uses this - /// (because YAML reader does not read blobs but structured data). - void setLastError(std::error_code err) { _lastError = err; } - - std::error_code parse(); - - // Usually each file owns a std::unique_ptr. - // However, there's one special case. If a file is an archive file, - // the archive file and its children all shares the same memory buffer. - // This method is used by the ArchiveFile to give its children - // co-ownership of the buffer. - void setSharedMemoryBuffer(std::shared_ptr mb) { - _sharedMemoryBuffer = mb; - } - -protected: - /// only subclasses of File can be instantiated - File(StringRef p, Kind kind) - : _path(p), _kind(kind), _ordinal(UINT64_MAX), - _nextAtomOrdinal(0) {} - - /// Subclasses should override this method to parse the - /// memory buffer passed to this file's constructor. - virtual std::error_code doParse() { return std::error_code(); } - - static AtomVector _noDefinedAtoms; - static AtomVector _noUndefinedAtoms; - static AtomVector _noSharedLibraryAtoms; - static AtomVector _noAbsoluteAtoms; - mutable llvm::BumpPtrAllocator _allocator; - -private: - StringRef _path; - std::string _archivePath; - mutable std::string _archiveMemberPath; - Kind _kind; - mutable uint64_t _ordinal; - mutable uint64_t _nextAtomOrdinal; - std::shared_ptr _sharedMemoryBuffer; - llvm::Optional _lastError; - std::mutex _parseMutex; -}; - -/// An ErrorFile represents a file that doesn't exist. -/// If you try to parse a file which doesn't exist, an instance of this -/// class will be returned. That's parse method always returns an error. -/// This is useful to delay erroring on non-existent files, so that we -/// can do unit testing a driver using non-existing file paths. -class ErrorFile : public File { -public: - ErrorFile(StringRef path, std::error_code ec) - : File(path, kindErrorObject), _ec(ec) {} - - std::error_code doParse() override { return _ec; } - - const AtomRange defined() const override { - llvm_unreachable("internal error"); - } - const AtomRange undefined() const override { - llvm_unreachable("internal error"); - } - const AtomRange sharedLibrary() const override { - llvm_unreachable("internal error"); - } - const AtomRange absolute() const override { - llvm_unreachable("internal error"); - } - - void clearAtoms() override { - } - -private: - std::error_code _ec; -}; - -} // end namespace lld - -#endif diff --git a/lld/include/lld/Core/Instrumentation.h b/lld/include/lld/Core/Instrumentation.h deleted file mode 100644 --- a/lld/include/lld/Core/Instrumentation.h +++ /dev/null @@ -1,131 +0,0 @@ -//===- include/Core/Instrumentation.h - Instrumentation API ---------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// Provide an Instrumentation API that optionally uses VTune interfaces. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_INSTRUMENTATION_H -#define LLD_CORE_INSTRUMENTATION_H - -#include "llvm/Support/Compiler.h" -#include - -#ifdef LLD_HAS_VTUNE -# include -#endif - -namespace lld { -#ifdef LLD_HAS_VTUNE -/// A unique global scope for instrumentation data. -/// -/// Domains last for the lifetime of the application and cannot be destroyed. -/// Multiple Domains created with the same name represent the same domain. -class Domain { - __itt_domain *_domain; - -public: - explicit Domain(const char *name) : _domain(__itt_domain_createA(name)) {} - - operator __itt_domain *() const { return _domain; } - __itt_domain *operator->() const { return _domain; } -}; - -/// A global reference to a string constant. -/// -/// These are uniqued by the ITT runtime and cannot be deleted. They are not -/// specific to a domain. -/// -/// Prefer reusing a single StringHandle over passing a ntbs when the same -/// string will be used often. -class StringHandle { - __itt_string_handle *_handle; - -public: - StringHandle(const char *name) : _handle(__itt_string_handle_createA(name)) {} - - operator __itt_string_handle *() const { return _handle; } -}; - -/// A task on a single thread. Nests within other tasks. -/// -/// Each thread has its own task stack and tasks nest recursively on that stack. -/// A task cannot transfer threads. -/// -/// SBRM is used to ensure task starts and ends are balanced. The lifetime of -/// a task is either the lifetime of this object, or until end is called. -class ScopedTask { - __itt_domain *_domain; - - ScopedTask(const ScopedTask &) = delete; - ScopedTask &operator=(const ScopedTask &) = delete; - -public: - /// Create a task in Domain \p d named \p s. - ScopedTask(const Domain &d, const StringHandle &s) : _domain(d) { - __itt_task_begin(d, __itt_null, __itt_null, s); - } - - ScopedTask(ScopedTask &&other) { - *this = std::move(other); - } - - ScopedTask &operator=(ScopedTask &&other) { - _domain = other._domain; - other._domain = nullptr; - return *this; - } - - /// Prematurely end this task. - void end() { - if (_domain) - __itt_task_end(_domain); - _domain = nullptr; - } - - ~ScopedTask() { end(); } -}; - -/// A specific point in time. Allows metadata to be associated. -class Marker { -public: - Marker(const Domain &d, const StringHandle &s) { - __itt_marker(d, __itt_null, s, __itt_scope_global); - } -}; -#else -class Domain { -public: - Domain(const char *name) {} -}; - -class StringHandle { -public: - StringHandle(const char *name) {} -}; - -class ScopedTask { -public: - ScopedTask(const Domain &d, const StringHandle &s) {} - void end() {} -}; - -class Marker { -public: - Marker(const Domain &d, const StringHandle &s) {} -}; -#endif - -inline const Domain &getDefaultDomain() { - static Domain domain("org.llvm.lld"); - return domain; -} -} // end namespace lld. - -#endif diff --git a/lld/include/lld/Core/LinkingContext.h b/lld/include/lld/Core/LinkingContext.h deleted file mode 100644 --- a/lld/include/lld/Core/LinkingContext.h +++ /dev/null @@ -1,257 +0,0 @@ -//===- lld/Core/LinkingContext.h - Linker Target Info Interface -*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_LINKING_CONTEXT_H -#define LLD_CORE_LINKING_CONTEXT_H - -#include "lld/Common/CommonLinkerContext.h" -#include "lld/Core/Node.h" -#include "lld/Core/Reader.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Error.h" -#include -#include -#include -#include -#include - -namespace lld { - -class PassManager; -class File; -class Writer; -class Node; -class SharedLibraryFile; - -/// The LinkingContext class encapsulates "what and how" to link. -/// -/// The base class LinkingContext contains the options needed by core linking. -/// Subclasses of LinkingContext have additional options needed by specific -/// Writers. -class LinkingContext : public CommonLinkerContext { -public: - virtual ~LinkingContext(); - - /// \name Methods needed by core linking - /// @{ - - /// Name of symbol linker should use as "entry point" to program, - /// usually "main" or "start". - virtual StringRef entrySymbolName() const { return _entrySymbolName; } - - /// Whether core linking should remove Atoms not reachable by following - /// References from the entry point Atom or from all global scope Atoms - /// if globalsAreDeadStripRoots() is true. - bool deadStrip() const { return _deadStrip; } - - /// Only used if deadStrip() returns true. Means all global scope Atoms - /// should be marked live (along with all Atoms they reference). Usually - /// this method returns false for main executables, but true for dynamic - /// shared libraries. - bool globalsAreDeadStripRoots() const { return _globalsAreDeadStripRoots; } - - /// Only used if deadStrip() returns true. This method returns the names - /// of DefinedAtoms that should be marked live (along with all Atoms they - /// reference). Only Atoms with scope scopeLinkageUnit or scopeGlobal can - /// be kept live using this method. - ArrayRef deadStripRoots() const { - return _deadStripRoots; - } - - /// Add the given symbol name to the dead strip root set. Only used if - /// deadStrip() returns true. - void addDeadStripRoot(StringRef symbolName) { - assert(!symbolName.empty() && "Empty symbol cannot be a dead strip root"); - _deadStripRoots.push_back(symbolName); - } - - /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a - /// SharedLibraryAtom for the link to be successful. This method controls - /// whether core linking prints out a list of remaining UndefinedAtoms. - /// - /// \todo This should be a method core linking calls with a list of the - /// UndefinedAtoms so that different drivers can format the error message - /// as needed. - bool printRemainingUndefines() const { return _printRemainingUndefines; } - - /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a - /// SharedLibraryAtom for the link to be successful. This method controls - /// whether core linking considers remaining undefines to be an error. - bool allowRemainingUndefines() const { return _allowRemainingUndefines; } - - /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a - /// SharedLibraryAtom for the link to be successful. This method controls - /// whether core linking considers remaining undefines from the shared library - /// to be an error. - bool allowShlibUndefines() const { return _allowShlibUndefines; } - - /// If true, core linking will write the path to each input file to stdout - /// (i.e. llvm::outs()) as it is used. This is used to implement the -t - /// linker option. - /// - /// \todo This should be a method core linking calls so that drivers can - /// format the line as needed. - bool logInputFiles() const { return _logInputFiles; } - - /// Parts of LLVM use global variables which are bound to command line - /// options (see llvm::cl::Options). This method returns "command line" - /// options which are used to configure LLVM's command line settings. - /// For instance the -debug-only XXX option can be used to dynamically - /// trace different parts of LLVM and lld. - ArrayRef llvmOptions() const { return _llvmOptions; } - - /// \name Methods used by Drivers to configure TargetInfo - /// @{ - void setOutputPath(StringRef str) { _outputPath = str; } - - // Set the entry symbol name. You may also need to call addDeadStripRoot() for - // the symbol if your platform supports dead-stripping, so that the symbol - // will not be removed from the output. - void setEntrySymbolName(StringRef name) { - _entrySymbolName = name; - } - - void setDeadStripping(bool enable) { _deadStrip = enable; } - void setGlobalsAreDeadStripRoots(bool v) { _globalsAreDeadStripRoots = v; } - - void setPrintRemainingUndefines(bool print) { - _printRemainingUndefines = print; - } - - void setAllowRemainingUndefines(bool allow) { - _allowRemainingUndefines = allow; - } - - void setAllowShlibUndefines(bool allow) { _allowShlibUndefines = allow; } - void setLogInputFiles(bool log) { _logInputFiles = log; } - - void appendLLVMOption(const char *opt) { _llvmOptions.push_back(opt); } - - std::vector> &getNodes() { return _nodes; } - const std::vector> &getNodes() const { return _nodes; } - - /// This method adds undefined symbols specified by the -u option to the to - /// the list of undefined symbols known to the linker. This option essentially - /// forces an undefined symbol to be created. You may also need to call - /// addDeadStripRoot() for the symbol if your platform supports dead - /// stripping, so that the symbol will not be removed from the output. - void addInitialUndefinedSymbol(StringRef symbolName) { - _initialUndefinedSymbols.push_back(symbolName); - } - - /// Iterators for symbols that appear on the command line. - typedef std::vector StringRefVector; - typedef StringRefVector::iterator StringRefVectorIter; - typedef StringRefVector::const_iterator StringRefVectorConstIter; - - /// Create linker internal files containing atoms for the linker to include - /// during link. Flavors can override this function in their LinkingContext - /// to add more internal files. These internal files are positioned before - /// the actual input files. - virtual void createInternalFiles(std::vector> &) const; - - /// Return the list of undefined symbols that are specified in the - /// linker command line, using the -u option. - ArrayRef initialUndefinedSymbols() const { - return _initialUndefinedSymbols; - } - - /// After all set* methods are called, the Driver calls this method - /// to validate that there are no missing options or invalid combinations - /// of options. If there is a problem, a description of the problem - /// is written to the global error handler. - /// - /// \returns true if there is an error with the current settings. - bool validate(); - - /// Formats symbol name for use in error messages. - virtual std::string demangle(StringRef symbolName) const = 0; - - /// @} - /// \name Methods used by Driver::link() - /// @{ - - /// Returns the file system path to which the linked output should be written. - /// - /// \todo To support in-memory linking, we need an abstraction that allows - /// the linker to write to an in-memory buffer. - StringRef outputPath() const { return _outputPath; } - - /// Accessor for Register object embedded in LinkingContext. - const Registry ®istry() const { return _registry; } - Registry ®istry() { return _registry; } - - /// This method is called by core linking to give the Writer a chance - /// to add file format specific "files" to set of files to be linked. This is - /// how file format specific atoms can be added to the link. - virtual void createImplicitFiles(std::vector> &) = 0; - - /// This method is called by core linking to build the list of Passes to be - /// run on the merged/linked graph of all input files. - virtual void addPasses(PassManager &pm) = 0; - - /// Calls through to the writeFile() method on the specified Writer. - /// - /// \param linkedFile This is the merged/linked graph of all input file Atoms. - virtual llvm::Error writeFile(const File &linkedFile) const; - - /// Return the next ordinal and Increment it. - virtual uint64_t getNextOrdinalAndIncrement() const { return _nextOrdinal++; } - - // This function is called just before the Resolver kicks in. - // Derived classes may use it to change the list of input files. - virtual void finalizeInputFiles() = 0; - - /// Callback invoked for each file the Resolver decides we are going to load. - /// This can be used to update context state based on the file, and emit - /// errors for any differences between the context state and a loaded file. - /// For example, we can error if we try to load a file which is a different - /// arch from that being linked. - virtual llvm::Error handleLoadedFile(File &file) = 0; - - /// @} -protected: - LinkingContext(); // Must be subclassed - - /// Abstract method to lazily instantiate the Writer. - virtual Writer &writer() const = 0; - - /// Method to create an internal file for the entry symbol - virtual std::unique_ptr createEntrySymbolFile() const; - std::unique_ptr createEntrySymbolFile(StringRef filename) const; - - /// Method to create an internal file for an undefined symbol - virtual std::unique_ptr createUndefinedSymbolFile() const; - std::unique_ptr createUndefinedSymbolFile(StringRef filename) const; - - StringRef _outputPath; - StringRef _entrySymbolName; - bool _deadStrip = false; - bool _globalsAreDeadStripRoots = false; - bool _printRemainingUndefines = true; - bool _allowRemainingUndefines = false; - bool _logInputFiles = false; - bool _allowShlibUndefines = false; - std::vector _deadStripRoots; - std::vector _llvmOptions; - StringRefVector _initialUndefinedSymbols; - std::vector> _nodes; - mutable llvm::BumpPtrAllocator _allocator; - mutable uint64_t _nextOrdinal = 0; - Registry _registry; - -private: - /// Validate the subclass bits. Only called by validate. - virtual bool validateImpl() = 0; -}; - -} // end namespace lld - -#endif // LLD_CORE_LINKING_CONTEXT_H diff --git a/lld/include/lld/Core/Node.h b/lld/include/lld/Core/Node.h deleted file mode 100644 --- a/lld/include/lld/Core/Node.h +++ /dev/null @@ -1,74 +0,0 @@ -//===- lld/Core/Node.h - Input file class -----------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// -/// The classes in this file represents inputs to the linker. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_NODE_H -#define LLD_CORE_NODE_H - -#include "lld/Core/File.h" -#include -#include - -namespace lld { - -// A Node represents a FileNode or other type of Node. In the latter case, -// the node contains meta information about the input file list. -// Currently only GroupEnd node is defined as a meta node. -class Node { -public: - enum class Kind { File, GroupEnd }; - - explicit Node(Kind type) : _kind(type) {} - virtual ~Node() = default; - - virtual Kind kind() const { return _kind; } - -private: - Kind _kind; -}; - -// This is a marker for --end-group. getSize() returns the number of -// files between the corresponding --start-group and this marker. -class GroupEnd : public Node { -public: - explicit GroupEnd(int size) : Node(Kind::GroupEnd), _size(size) {} - - int getSize() const { return _size; } - - static bool classof(const Node *a) { - return a->kind() == Kind::GroupEnd; - } - -private: - int _size; -}; - -// A container of File. -class FileNode : public Node { -public: - explicit FileNode(std::unique_ptr f) - : Node(Node::Kind::File), _file(std::move(f)) {} - - static bool classof(const Node *a) { - return a->kind() == Node::Kind::File; - } - - File *getFile() { return _file.get(); } - -protected: - std::unique_ptr _file; -}; - -} // end namespace lld - -#endif // LLD_CORE_NODE_H diff --git a/lld/include/lld/Core/Pass.h b/lld/include/lld/Core/Pass.h deleted file mode 100644 --- a/lld/include/lld/Core/Pass.h +++ /dev/null @@ -1,42 +0,0 @@ -//===------ Core/Pass.h - Base class for linker passes ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_PASS_H -#define LLD_CORE_PASS_H - -#include "llvm/Support/Error.h" - -namespace lld { - -class SimpleFile; - -/// Once the core linking is done (which resolves references, coalesces atoms -/// and produces a complete Atom graph), the linker runs a series of passes -/// on the Atom graph. The graph is modeled as a File, which means the pass -/// has access to all the atoms and to File level attributes. Each pass does -/// a particular transformation to the Atom graph or to the File attributes. -/// -/// This is the abstract base class for all passes. A Pass does its -/// actual work in it perform() method. It can iterator over Atoms in the -/// graph using the *begin()/*end() atom iterator of the File. It can add -/// new Atoms to the graph using the File's addAtom() method. -class Pass { -public: - virtual ~Pass() = default; - - /// Do the actual work of the Pass. - virtual llvm::Error perform(SimpleFile &mergedFile) = 0; - -protected: - // Only subclassess can be instantiated. - Pass() = default; -}; - -} // end namespace lld - -#endif // LLD_CORE_PASS_H diff --git a/lld/include/lld/Core/PassManager.h b/lld/include/lld/Core/PassManager.h deleted file mode 100644 --- a/lld/include/lld/Core/PassManager.h +++ /dev/null @@ -1,47 +0,0 @@ -//===- lld/Core/PassManager.h - Manage linker passes ----------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_PASS_MANAGER_H -#define LLD_CORE_PASS_MANAGER_H - -#include "lld/Common/LLVM.h" -#include "lld/Core/Pass.h" -#include "llvm/Support/Error.h" -#include -#include - -namespace lld { -class SimpleFile; -class Pass; - -/// Owns and runs a collection of passes. -/// -/// This class is currently just a container for passes and a way to run them. -/// -/// In the future this should handle timing pass runs, running parallel passes, -/// and validate/satisfy pass dependencies. -class PassManager { -public: - void add(std::unique_ptr pass) { - _passes.push_back(std::move(pass)); - } - - llvm::Error runOnFile(SimpleFile &file) { - for (std::unique_ptr &pass : _passes) - if (llvm::Error EC = pass->perform(file)) - return EC; - return llvm::Error::success(); - } - -private: - /// Passes in the order they should run. - std::vector> _passes; -}; -} // end namespace lld - -#endif diff --git a/lld/include/lld/Core/Reader.h b/lld/include/lld/Core/Reader.h deleted file mode 100644 --- a/lld/include/lld/Core/Reader.h +++ /dev/null @@ -1,154 +0,0 @@ -//===- lld/Core/Reader.h - Abstract File Format Reading Interface ---------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_READER_H -#define LLD_CORE_READER_H - -#include "lld/Common/LLVM.h" -#include "lld/Core/Reference.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/BinaryFormat/Magic.h" -#include "llvm/Support/ErrorOr.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/MemoryBuffer.h" -#include -#include - -namespace llvm { -namespace yaml { -class IO; -} // end namespace yaml -} // end namespace llvm - -namespace lld { - -class File; -class LinkingContext; -class MachOLinkingContext; - -/// An abstract class for reading object files, library files, and -/// executable files. -/// -/// Each file format (e.g. mach-o, etc) has a concrete subclass of Reader. -class Reader { -public: - virtual ~Reader() = default; - - /// Sniffs the file to determine if this Reader can parse it. - /// The method is called with: - /// 1) the file_magic enumeration returned by identify_magic() - /// 2) the whole file content buffer if the above is not enough. - virtual bool canParse(llvm::file_magic magic, MemoryBufferRef mb) const = 0; - - /// Parse a supplied buffer (already filled with the contents of a - /// file) and create a File object. - /// The resulting File object takes ownership of the MemoryBuffer. - virtual ErrorOr> - loadFile(std::unique_ptr mb, const class Registry &) const = 0; -}; - -/// An abstract class for handling alternate yaml representations -/// of object files. -/// -/// The YAML syntax allows "tags" which are used to specify the type of -/// the YAML node. In lld, top level YAML documents can be in many YAML -/// representations (e.g mach-o encoded as yaml, etc). A tag is used to -/// specify which representation is used in the following YAML document. -/// To work, there must be a YamlIOTaggedDocumentHandler registered that -/// handles each tag type. -class YamlIOTaggedDocumentHandler { -public: - virtual ~YamlIOTaggedDocumentHandler(); - - /// This method is called on each registered YamlIOTaggedDocumentHandler - /// until one returns true. If the subclass handles tag type !xyz, then - /// this method should call io.mapTag("!xzy") to see if that is the current - /// document type, and if so, process the rest of the document using - /// YAML I/O, then convert the result into an lld::File* and return it. - virtual bool handledDocTag(llvm::yaml::IO &io, const lld::File *&f) const = 0; -}; - -/// A registry to hold the list of currently registered Readers and -/// tables which map Reference kind values to strings. -/// The linker does not directly invoke Readers. Instead, it registers -/// Readers based on it configuration and command line options, then calls -/// the Registry object to parse files. -class Registry { -public: - Registry(); - - /// Walk the list of registered Readers and find one that can parse the - /// supplied file and parse it. - ErrorOr> - loadFile(std::unique_ptr mb) const; - - /// Walk the list of registered kind tables to convert a Reference Kind - /// name to a value. - bool referenceKindFromString(StringRef inputStr, Reference::KindNamespace &ns, - Reference::KindArch &a, - Reference::KindValue &value) const; - - /// Walk the list of registered kind tables to convert a Reference Kind - /// value to a string. - bool referenceKindToString(Reference::KindNamespace ns, Reference::KindArch a, - Reference::KindValue value, StringRef &) const; - - /// Walk the list of registered tag handlers and have the one that handles - /// the current document type process the yaml into an lld::File*. - bool handleTaggedDoc(llvm::yaml::IO &io, const lld::File *&file) const; - - // These methods are called to dynamically add support for various file - // formats. The methods are also implemented in the appropriate lib*.a - // library, so that the code for handling a format is only linked in, if this - // method is used. Any options that a Reader might need must be passed - // as parameters to the addSupport*() method. - void addSupportArchives(bool logLoading); - void addSupportYamlFiles(); - void addSupportMachOObjects(MachOLinkingContext &); - - /// To convert between kind values and names, the registry walks the list - /// of registered kind tables. Each table is a zero terminated array of - /// KindStrings elements. - struct KindStrings { - Reference::KindValue value; - StringRef name; - }; - - /// A Reference Kind value is a tuple of . All - /// entries in a conversion table have the same . The - /// array then contains the value/name pairs. - void addKindTable(Reference::KindNamespace ns, Reference::KindArch arch, - const KindStrings array[]); - -private: - struct KindEntry { - Reference::KindNamespace ns; - Reference::KindArch arch; - const KindStrings *array; - }; - - void add(std::unique_ptr); - void add(std::unique_ptr); - - std::vector> _readers; - std::vector> _yamlHandlers; - std::vector _kindEntries; -}; - -// Utilities for building a KindString table. For instance: -// static const Registry::KindStrings table[] = { -// LLD_KIND_STRING_ENTRY(R_VAX_ADDR16), -// LLD_KIND_STRING_ENTRY(R_VAX_DATA16), -// LLD_KIND_STRING_END -// }; -#define LLD_KIND_STRING_ENTRY(name) { name, #name } -#define LLD_KIND_STRING_END { 0, "" } - -} // end namespace lld - -#endif // LLD_CORE_READER_H diff --git a/lld/include/lld/Core/Reference.h b/lld/include/lld/Core/Reference.h deleted file mode 100644 --- a/lld/include/lld/Core/Reference.h +++ /dev/null @@ -1,117 +0,0 @@ -//===- Core/References.h - A Reference to Another Atom ----------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_REFERENCES_H -#define LLD_CORE_REFERENCES_H - -#include - -namespace lld { - -class Atom; - -/// -/// The linker has a Graph Theory model of linking. An object file is seen -/// as a set of Atoms with References to other Atoms. Each Atom is a node -/// and each Reference is an edge. -/// -/// For example if a function contains a call site to "malloc" 40 bytes into -/// the Atom, then the function Atom will have a Reference of: offsetInAtom=40, -/// kind=callsite, target=malloc, addend=0. -/// -/// Besides supporting traditional "relocations", references are also used -/// forcing layout (one atom must follow another), marking data-in-code -/// (jump tables or ARM constants), etc. -/// -/// The "kind" of a reference is a tuple of . This -/// enable us to re-use existing relocation types definded for various -/// file formats and architectures. -/// -/// References and atoms form a directed graph. The dead-stripping pass -/// traverses them starting from dead-strip root atoms to garbage collect -/// unreachable ones. -/// -/// References of any kind are considered as directed edges. In addition to -/// that, references of some kind is considered as bidirected edges. -class Reference { -public: - /// Which universe defines the kindValue(). - enum class KindNamespace { - all = 0, - testing = 1, - }; - - KindNamespace kindNamespace() const { return (KindNamespace)_kindNamespace; } - void setKindNamespace(KindNamespace ns) { _kindNamespace = (uint8_t)ns; } - - // Which architecture the kind value is for. - enum class KindArch { all, AArch64, ARM, x86, x86_64}; - - KindArch kindArch() const { return (KindArch)_kindArch; } - void setKindArch(KindArch a) { _kindArch = (uint8_t)a; } - - typedef uint16_t KindValue; - - KindValue kindValue() const { return _kindValue; } - - /// setKindValue() is needed because during linking, some optimizations may - /// change the codegen and hence the reference kind. - void setKindValue(KindValue value) { - _kindValue = value; - } - - /// KindValues used with KindNamespace::all and KindArch::all. - enum { - // kindLayoutAfter is treated as a bidirected edge by the dead-stripping - // pass. - kindLayoutAfter = 1, - kindAssociate, - }; - - // A value to be added to the value of a target - typedef int64_t Addend; - - /// If the reference is a fixup in the Atom, then this returns the - /// byte offset into the Atom's content to do the fix up. - virtual uint64_t offsetInAtom() const = 0; - - /// Returns the atom this reference refers to. - virtual const Atom *target() const = 0; - - /// During linking, the linker may merge graphs which coalesces some nodes - /// (i.e. Atoms). To switch the target of a reference, this method is called. - virtual void setTarget(const Atom *) = 0; - - /// Some relocations require a symbol and a value (e.g. foo + 4). - virtual Addend addend() const = 0; - - /// During linking, some optimizations may change addend value. - virtual void setAddend(Addend) = 0; - - /// Returns target specific attributes of the reference. - virtual uint32_t tag() const { return 0; } - -protected: - /// Reference is an abstract base class. Only subclasses can use constructor. - Reference(KindNamespace ns, KindArch a, KindValue value) - : _kindValue(value), _kindNamespace((uint8_t)ns), _kindArch((uint8_t)a) {} - - /// The memory for Reference objects is always managed by the owning File - /// object. Therefore, no one but the owning File object should call - /// delete on a Reference. In fact, some File objects may bulk allocate - /// an array of References, so they cannot be individually deleted by anyone. - virtual ~Reference() = default; - - KindValue _kindValue; - uint8_t _kindNamespace; - uint8_t _kindArch; -}; - -} // end namespace lld - -#endif // LLD_CORE_REFERENCES_H diff --git a/lld/include/lld/Core/Resolver.h b/lld/include/lld/Core/Resolver.h deleted file mode 100644 --- a/lld/include/lld/Core/Resolver.h +++ /dev/null @@ -1,105 +0,0 @@ -//===- Core/Resolver.h - Resolves Atom References -------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_RESOLVER_H -#define LLD_CORE_RESOLVER_H - -#include "lld/Core/ArchiveLibraryFile.h" -#include "lld/Core/File.h" -#include "lld/Core/SharedLibraryFile.h" -#include "lld/Core/Simple.h" -#include "lld/Core/SymbolTable.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/Support/ErrorOr.h" -#include -#include -#include -#include - -namespace lld { - -class Atom; -class LinkingContext; - -/// The Resolver is responsible for merging all input object files -/// and producing a merged graph. -class Resolver { -public: - Resolver(LinkingContext &ctx) : _ctx(ctx), _result(new MergedFile()) {} - - // InputFiles::Handler methods - void doDefinedAtom(OwningAtomPtr atom); - bool doUndefinedAtom(OwningAtomPtr atom); - void doSharedLibraryAtom(OwningAtomPtr atom); - void doAbsoluteAtom(OwningAtomPtr atom); - - // Handle files, this adds atoms from the current file thats - // being processed by the resolver - llvm::Expected handleFile(File &); - - // Handle an archive library file. - llvm::Expected handleArchiveFile(File &); - - // Handle a shared library file. - llvm::Error handleSharedLibrary(File &); - - /// do work of merging and resolving and return list - bool resolve(); - - std::unique_ptr resultFile() { return std::move(_result); } - -private: - typedef std::function(StringRef)> UndefCallback; - - bool undefinesAdded(int begin, int end); - File *getFile(int &index); - - /// The main function that iterates over the files to resolve - bool resolveUndefines(); - void updateReferences(); - void deadStripOptimize(); - bool checkUndefines(); - void removeCoalescedAwayAtoms(); - llvm::Expected forEachUndefines(File &file, UndefCallback callback); - - void markLive(const Atom *atom); - - class MergedFile : public SimpleFile { - public: - MergedFile() : SimpleFile("", kindResolverMergedObject) {} - void addAtoms(llvm::MutableArrayRef> atoms); - }; - - LinkingContext &_ctx; - SymbolTable _symbolTable; - std::vector> _atoms; - std::set _deadStripRoots; - llvm::DenseSet _liveAtoms; - llvm::DenseSet _deadAtoms; - std::unique_ptr _result; - std::unordered_multimap _reverseRef; - - // --start-group and --end-group - std::vector _files; - std::map _newUndefinesAdded; - - // List of undefined symbols. - std::vector _undefines; - - // Start position in _undefines for each archive/shared library file. - // Symbols from index 0 to the start position are already searched before. - // Searching them again would never succeed. When we look for undefined - // symbols from an archive/shared library file, start from its start - // position to save time. - std::map _undefineIndex; -}; - -} // namespace lld - -#endif // LLD_CORE_RESOLVER_H diff --git a/lld/include/lld/Core/SharedLibraryAtom.h b/lld/include/lld/Core/SharedLibraryAtom.h deleted file mode 100644 --- a/lld/include/lld/Core/SharedLibraryAtom.h +++ /dev/null @@ -1,52 +0,0 @@ -//===- Core/SharedLibraryAtom.h - A Shared Library Atom -------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_SHARED_LIBRARY_ATOM_H -#define LLD_CORE_SHARED_LIBRARY_ATOM_H - -#include "lld/Core/Atom.h" - -namespace lld { - -/// A SharedLibraryAtom has no content. -/// It exists to represent a symbol which will be bound at runtime. -class SharedLibraryAtom : public Atom { -public: - enum class Type : uint32_t { - Unknown, - Code, - Data, - }; - - /// Returns shared library name used to load it at runtime. - /// On Darwin it is the LC_DYLIB_LOAD dylib name. - virtual StringRef loadName() const = 0; - - /// Returns if shared library symbol can be missing at runtime and if - /// so the loader should silently resolve address of symbol to be nullptr. - virtual bool canBeNullAtRuntime() const = 0; - - virtual Type type() const = 0; - - virtual uint64_t size() const = 0; - - static bool classof(const Atom *a) { - return a->definition() == definitionSharedLibrary; - } - - static inline bool classof(const SharedLibraryAtom *) { return true; } - -protected: - SharedLibraryAtom() : Atom(definitionSharedLibrary) {} - - ~SharedLibraryAtom() override = default; -}; - -} // namespace lld - -#endif // LLD_CORE_SHARED_LIBRARY_ATOM_H diff --git a/lld/include/lld/Core/SharedLibraryFile.h b/lld/include/lld/Core/SharedLibraryFile.h deleted file mode 100644 --- a/lld/include/lld/Core/SharedLibraryFile.h +++ /dev/null @@ -1,69 +0,0 @@ -//===- Core/SharedLibraryFile.h - Models shared libraries as Atoms --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_SHARED_LIBRARY_FILE_H -#define LLD_CORE_SHARED_LIBRARY_FILE_H - -#include "lld/Core/File.h" - -namespace lld { - -/// -/// The SharedLibraryFile subclass of File is used to represent dynamic -/// shared libraries being linked against. -/// -class SharedLibraryFile : public File { -public: - static bool classof(const File *f) { - return f->kind() == kindSharedLibrary; - } - - /// Check if the shared library exports a symbol with the specified name. - /// If so, return a SharedLibraryAtom which represents that exported - /// symbol. Otherwise return nullptr. - virtual OwningAtomPtr exports(StringRef name) const = 0; - - // Returns the install name. - virtual StringRef getDSOName() const = 0; - - const AtomRange defined() const override { - return _definedAtoms; - } - - const AtomRange undefined() const override { - return _undefinedAtoms; - } - - const AtomRange sharedLibrary() const override { - return _sharedLibraryAtoms; - } - - const AtomRange absolute() const override { - return _absoluteAtoms; - } - - void clearAtoms() override { - _definedAtoms.clear(); - _undefinedAtoms.clear(); - _sharedLibraryAtoms.clear(); - _absoluteAtoms.clear(); - } - -protected: - /// only subclasses of SharedLibraryFile can be instantiated - explicit SharedLibraryFile(StringRef path) : File(path, kindSharedLibrary) {} - - AtomVector _definedAtoms; - AtomVector _undefinedAtoms; - AtomVector _sharedLibraryAtoms; - AtomVector _absoluteAtoms; -}; - -} // namespace lld - -#endif // LLD_CORE_SHARED_LIBRARY_FILE_H diff --git a/lld/include/lld/Core/Simple.h b/lld/include/lld/Core/Simple.h deleted file mode 100644 --- a/lld/include/lld/Core/Simple.h +++ /dev/null @@ -1,270 +0,0 @@ -//===- lld/Core/Simple.h - Simple implementations of Atom and File --------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -/// -/// \file -/// Provide simple implementations for Atoms and File. -/// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_SIMPLE_H -#define LLD_CORE_SIMPLE_H - -#include "lld/Core/AbsoluteAtom.h" -#include "lld/Core/Atom.h" -#include "lld/Core/DefinedAtom.h" -#include "lld/Core/File.h" -#include "lld/Core/Reference.h" -#include "lld/Core/SharedLibraryAtom.h" -#include "lld/Core/UndefinedAtom.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/Support/Allocator.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/ErrorHandling.h" -#include -#include -#include -#include - -namespace lld { - -class SimpleFile : public File { -public: - SimpleFile(StringRef path, File::Kind kind) - : File(path, kind) {} - - ~SimpleFile() override { - _defined.clear(); - _undefined.clear(); - _shared.clear(); - _absolute.clear(); - } - - void addAtom(DefinedAtom &a) { - _defined.push_back(OwningAtomPtr(&a)); - } - void addAtom(UndefinedAtom &a) { - _undefined.push_back(OwningAtomPtr(&a)); - } - void addAtom(SharedLibraryAtom &a) { - _shared.push_back(OwningAtomPtr(&a)); - } - void addAtom(AbsoluteAtom &a) { - _absolute.push_back(OwningAtomPtr(&a)); - } - - void addAtom(const Atom &atom) { - if (auto *p = dyn_cast(&atom)) { - addAtom(const_cast(*p)); - } else if (auto *p = dyn_cast(&atom)) { - addAtom(const_cast(*p)); - } else if (auto *p = dyn_cast(&atom)) { - addAtom(const_cast(*p)); - } else if (auto *p = dyn_cast(&atom)) { - addAtom(const_cast(*p)); - } else { - llvm_unreachable("atom has unknown definition kind"); - } - } - - void removeDefinedAtomsIf(std::function pred) { - auto &atoms = _defined; - auto newEnd = std::remove_if(atoms.begin(), atoms.end(), - [&pred](OwningAtomPtr &p) { - return pred(p.get()); - }); - atoms.erase(newEnd, atoms.end()); - } - - const AtomRange defined() const override { return _defined; } - - const AtomRange undefined() const override { - return _undefined; - } - - const AtomRange sharedLibrary() const override { - return _shared; - } - - const AtomRange absolute() const override { - return _absolute; - } - - void clearAtoms() override { - _defined.clear(); - _undefined.clear(); - _shared.clear(); - _absolute.clear(); - } - -private: - AtomVector _defined; - AtomVector _undefined; - AtomVector _shared; - AtomVector _absolute; -}; - -class SimpleReference : public Reference, - public llvm::ilist_node { -public: - SimpleReference(Reference::KindNamespace ns, Reference::KindArch arch, - Reference::KindValue value, uint64_t off, const Atom *t, - Reference::Addend a) - : Reference(ns, arch, value), _target(t), _offsetInAtom(off), _addend(a) { - } - SimpleReference() - : Reference(Reference::KindNamespace::all, Reference::KindArch::all, 0), - _target(nullptr), _offsetInAtom(0), _addend(0) {} - - uint64_t offsetInAtom() const override { return _offsetInAtom; } - - const Atom *target() const override { - assert(_target); - return _target; - } - - Addend addend() const override { return _addend; } - void setAddend(Addend a) override { _addend = a; } - void setTarget(const Atom *newAtom) override { _target = newAtom; } - -private: - const Atom *_target; - uint64_t _offsetInAtom; - Addend _addend; -}; - -class SimpleDefinedAtom : public DefinedAtom { -public: - explicit SimpleDefinedAtom(const File &f) - : _file(f), _ordinal(f.getNextAtomOrdinalAndIncrement()) {} - - ~SimpleDefinedAtom() override { - _references.clearAndLeakNodesUnsafely(); - } - - const File &file() const override { return _file; } - - StringRef name() const override { return StringRef(); } - - uint64_t ordinal() const override { return _ordinal; } - - Scope scope() const override { return DefinedAtom::scopeLinkageUnit; } - - Interposable interposable() const override { - return DefinedAtom::interposeNo; - } - - Merge merge() const override { return DefinedAtom::mergeNo; } - - Alignment alignment() const override { return 1; } - - SectionChoice sectionChoice() const override { - return DefinedAtom::sectionBasedOnContent; - } - - StringRef customSectionName() const override { return StringRef(); } - DeadStripKind deadStrip() const override { - return DefinedAtom::deadStripNormal; - } - - DefinedAtom::reference_iterator begin() const override { - const void *it = - reinterpret_cast(_references.begin().getNodePtr()); - return reference_iterator(*this, it); - } - - DefinedAtom::reference_iterator end() const override { - const void *it = - reinterpret_cast(_references.end().getNodePtr()); - return reference_iterator(*this, it); - } - - const Reference *derefIterator(const void *it) const override { - return &*RefList::const_iterator( - *reinterpret_cast *>(it)); - } - - void incrementIterator(const void *&it) const override { - RefList::const_iterator ref( - *reinterpret_cast *>(it)); - it = reinterpret_cast(std::next(ref).getNodePtr()); - } - - void addReference(Reference::KindNamespace ns, - Reference::KindArch arch, - Reference::KindValue kindValue, uint64_t off, - const Atom *target, Reference::Addend a) override { - assert(target && "trying to create reference to nothing"); - auto node = new (_file.allocator()) - SimpleReference(ns, arch, kindValue, off, target, a); - _references.push_back(node); - } - - /// Sort references in a canonical order (by offset, then by kind). - void sortReferences() const { - // Cannot sort a linked list, so move elements into a temporary vector, - // sort the vector, then reconstruct the list. - llvm::SmallVector elements; - for (SimpleReference &node : _references) { - elements.push_back(&node); - } - std::sort(elements.begin(), elements.end(), - [] (const SimpleReference *lhs, const SimpleReference *rhs) -> bool { - uint64_t lhsOffset = lhs->offsetInAtom(); - uint64_t rhsOffset = rhs->offsetInAtom(); - if (rhsOffset != lhsOffset) - return (lhsOffset < rhsOffset); - if (rhs->kindNamespace() != lhs->kindNamespace()) - return (lhs->kindNamespace() < rhs->kindNamespace()); - if (rhs->kindArch() != lhs->kindArch()) - return (lhs->kindArch() < rhs->kindArch()); - return (lhs->kindValue() < rhs->kindValue()); - }); - _references.clearAndLeakNodesUnsafely(); - for (SimpleReference *node : elements) { - _references.push_back(node); - } - } - - void setOrdinal(uint64_t ord) { _ordinal = ord; } - -private: - typedef llvm::ilist RefList; - - const File &_file; - uint64_t _ordinal; - mutable RefList _references; -}; - -class SimpleUndefinedAtom : public UndefinedAtom { -public: - SimpleUndefinedAtom(const File &f, StringRef name) : _file(f), _name(name) { - assert(!name.empty() && "UndefinedAtoms must have a name"); - } - - ~SimpleUndefinedAtom() override = default; - - /// file - returns the File that produced/owns this Atom - const File &file() const override { return _file; } - - /// name - The name of the atom. For a function atom, it is the (mangled) - /// name of the function. - StringRef name() const override { return _name; } - - CanBeNull canBeNull() const override { return UndefinedAtom::canBeNullNever; } - -private: - const File &_file; - StringRef _name; -}; - -} // end namespace lld - -#endif // LLD_CORE_SIMPLE_H diff --git a/lld/include/lld/Core/SymbolTable.h b/lld/include/lld/Core/SymbolTable.h deleted file mode 100644 --- a/lld/include/lld/Core/SymbolTable.h +++ /dev/null @@ -1,95 +0,0 @@ -//===- Core/SymbolTable.h - Main Symbol Table -----------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_SYMBOL_TABLE_H -#define LLD_CORE_SYMBOL_TABLE_H - -#include "lld/Common/LLVM.h" -#include "llvm/ADT/DenseSet.h" -#include "llvm/Support/DJB.h" -#include -#include -#include - -namespace lld { - -class AbsoluteAtom; -class Atom; -class DefinedAtom; -class LinkingContext; -class ResolverOptions; -class SharedLibraryAtom; -class UndefinedAtom; - -/// The SymbolTable class is responsible for coalescing atoms. -/// -/// All atoms coalescable by-name or by-content should be added. -/// The method replacement() can be used to find the replacement atom -/// if an atom has been coalesced away. -class SymbolTable { -public: - /// add atom to symbol table - bool add(const DefinedAtom &); - - /// add atom to symbol table - bool add(const UndefinedAtom &); - - /// add atom to symbol table - bool add(const SharedLibraryAtom &); - - /// add atom to symbol table - bool add(const AbsoluteAtom &); - - /// returns atom in symbol table for specified name (or nullptr) - const Atom *findByName(StringRef sym); - - /// returns vector of remaining UndefinedAtoms - std::vector undefines(); - - /// if atom has been coalesced away, return replacement, else return atom - const Atom *replacement(const Atom *); - - /// if atom has been coalesced away, return true - bool isCoalescedAway(const Atom *); - -private: - typedef llvm::DenseMap AtomToAtom; - - struct StringRefMappingInfo { - static StringRef getEmptyKey() { return StringRef(); } - static StringRef getTombstoneKey() { return StringRef(" ", 1); } - static unsigned getHashValue(StringRef const val) { - return llvm::djbHash(val, 0); - } - static bool isEqual(StringRef const lhs, StringRef const rhs) { - return lhs.equals(rhs); - } - }; - typedef llvm::DenseMap NameToAtom; - - struct AtomMappingInfo { - static const DefinedAtom * getEmptyKey() { return nullptr; } - static const DefinedAtom * getTombstoneKey() { return (DefinedAtom*)(-1); } - static unsigned getHashValue(const DefinedAtom * const Val); - static bool isEqual(const DefinedAtom * const LHS, - const DefinedAtom * const RHS); - }; - typedef llvm::DenseSet AtomContentSet; - - bool addByName(const Atom &); - bool addByContent(const DefinedAtom &); - - AtomToAtom _replacedAtoms; - NameToAtom _nameTable; - AtomContentSet _contentTable; -}; - -} // namespace lld - -#endif // LLD_CORE_SYMBOL_TABLE_H diff --git a/lld/include/lld/Core/UndefinedAtom.h b/lld/include/lld/Core/UndefinedAtom.h deleted file mode 100644 --- a/lld/include/lld/Core/UndefinedAtom.h +++ /dev/null @@ -1,67 +0,0 @@ -//===- Core/UndefinedAtom.h - An Undefined Atom ---------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_UNDEFINED_ATOM_H -#define LLD_CORE_UNDEFINED_ATOM_H - -#include "lld/Core/Atom.h" - -namespace lld { - -/// An UndefinedAtom has no content. -/// It exists as a placeholder for a future atom. -class UndefinedAtom : public Atom { -public: - /// Whether this undefined symbol needs to be resolved, - /// or whether it can just evaluate to nullptr. - /// This concept is often called "weak", but that term - /// is overloaded to mean other things too. - enum CanBeNull { - /// Normal symbols must be resolved at build time - canBeNullNever, - - /// This symbol can be missing at runtime and will evaluate to nullptr. - /// That is, the static linker still must find a definition (usually - /// is some shared library), but at runtime, the dynamic loader - /// will allow the symbol to be missing and resolved to nullptr. - /// - /// On Darwin this is generated using a function prototype with - /// __attribute__((weak_import)). - /// On linux this is generated using a function prototype with - /// __attribute__((weak)). - /// On Windows this feature is not supported. - canBeNullAtRuntime, - - /// This symbol can be missing at build time. - /// That is, the static linker will not error if a definition for - /// this symbol is not found at build time. Instead, the linker - /// will build an executable that lets the dynamic loader find the - /// symbol at runtime. - /// This feature is not supported on Darwin nor Windows. - /// On linux this is generated using a function prototype with - /// __attribute__((weak)). - canBeNullAtBuildtime - }; - - virtual CanBeNull canBeNull() const = 0; - - static bool classof(const Atom *a) { - return a->definition() == definitionUndefined; - } - - static bool classof(const UndefinedAtom *) { return true; } - -protected: - UndefinedAtom() : Atom(definitionUndefined) {} - - ~UndefinedAtom() override = default; -}; - -} // namespace lld - -#endif // LLD_CORE_UNDEFINED_ATOM_H diff --git a/lld/include/lld/Core/Writer.h b/lld/include/lld/Core/Writer.h deleted file mode 100644 --- a/lld/include/lld/Core/Writer.h +++ /dev/null @@ -1,46 +0,0 @@ -//===- lld/Core/Writer.h - Abstract File Format Interface -----------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_CORE_WRITER_H -#define LLD_CORE_WRITER_H - -#include "lld/Common/LLVM.h" -#include "llvm/Support/Error.h" -#include -#include - -namespace lld { -class File; -class LinkingContext; -class MachOLinkingContext; - -/// The Writer is an abstract class for writing object files, shared -/// library files, and executable files. Each file format (e.g. mach-o, etc) -/// has a concrete subclass of Writer. -class Writer { -public: - virtual ~Writer(); - - /// Write a file from the supplied File object - virtual llvm::Error writeFile(const File &linkedFile, StringRef path) = 0; - - /// This method is called by Core Linking to give the Writer a chance - /// to add file format specific "files" to set of files to be linked. This is - /// how file format specific atoms can be added to the link. - virtual void createImplicitFiles(std::vector> &) {} - -protected: - // only concrete subclasses can be instantiated - Writer(); -}; - -std::unique_ptr createWriterMachO(const MachOLinkingContext &); -std::unique_ptr createWriterYAML(const LinkingContext &); -} // end namespace lld - -#endif