//===- 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