1 //===- Core/Atom.h - A node in linking graph --------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLD_CORE_ATOM_H 10 #define LLD_CORE_ATOM_H 11 12 #include "lld/Common/LLVM.h" 13 #include "llvm/ADT/StringRef.h" 14 15 namespace lld { 16 17 class File; 18 19 template<typename T> 20 class OwningAtomPtr; 21 22 /// 23 /// The linker has a Graph Theory model of linking. An object file is seen 24 /// as a set of Atoms with References to other Atoms. Each Atom is a node 25 /// and each Reference is an edge. An Atom can be a DefinedAtom which has 26 /// content or a UndefinedAtom which is a placeholder and represents an 27 /// undefined symbol (extern declaration). 28 /// 29 class Atom { 30 template<typename T> friend class OwningAtomPtr; 31 32 public: 33 /// Whether this atom is defined or a proxy for an undefined symbol 34 enum Definition { 35 definitionRegular, ///< Normal C/C++ function or global variable. 36 definitionAbsolute, ///< Asm-only (foo = 10). Not tied to any content. 37 definitionUndefined, ///< Only in .o files to model reference to undef. 38 definitionSharedLibrary ///< Only in shared libraries to model export. 39 }; 40 41 /// The scope in which this atom is accessible to other atoms. 42 enum Scope { 43 scopeTranslationUnit, ///< Accessible only to atoms in the same translation 44 /// unit (e.g. a C static). 45 scopeLinkageUnit, ///< Accessible to atoms being linked but not visible 46 /// to runtime loader (e.g. visibility=hidden). 47 scopeGlobal ///< Accessible to all atoms and visible to runtime 48 /// loader (e.g. visibility=default). 49 }; 50 51 /// file - returns the File that produced/owns this Atom 52 virtual const File& file() const = 0; 53 54 /// name - The name of the atom. For a function atom, it is the (mangled) 55 /// name of the function. 56 virtual StringRef name() const = 0; 57 58 /// definition - Whether this atom is a definition or represents an undefined 59 /// symbol. definition()60 Definition definition() const { return _definition; } 61 classof(const Atom * a)62 static bool classof(const Atom *a) { return true; } 63 64 protected: 65 /// Atom is an abstract base class. Only subclasses can access constructor. Atom(Definition def)66 explicit Atom(Definition def) : _definition(def) {} 67 68 /// The memory for Atom objects is always managed by the owning File 69 /// object. Therefore, no one but the owning File object should call 70 /// delete on an Atom. In fact, some File objects may bulk allocate 71 /// an array of Atoms, so they cannot be individually deleted by anyone. 72 virtual ~Atom() = default; 73 74 private: 75 Definition _definition; 76 }; 77 78 /// Class which owns an atom pointer and runs the atom destructor when the 79 /// owning pointer goes out of scope. 80 template<typename T> 81 class OwningAtomPtr { 82 private: 83 OwningAtomPtr(const OwningAtomPtr &) = delete; 84 void operator=(const OwningAtomPtr &) = delete; 85 86 public: 87 OwningAtomPtr() = default; OwningAtomPtr(T * atom)88 OwningAtomPtr(T *atom) : atom(atom) { } 89 ~OwningAtomPtr()90 ~OwningAtomPtr() { 91 if (atom) 92 runDestructor(atom); 93 } 94 runDestructor(Atom * atom)95 void runDestructor(Atom *atom) { 96 atom->~Atom(); 97 } 98 OwningAtomPtr(OwningAtomPtr && ptr)99 OwningAtomPtr(OwningAtomPtr &&ptr) : atom(ptr.atom) { 100 ptr.atom = nullptr; 101 } 102 103 void operator=(OwningAtomPtr&& ptr) { 104 if (atom) 105 runDestructor(atom); 106 atom = ptr.atom; 107 ptr.atom = nullptr; 108 } 109 get()110 T *const &get() const { 111 return atom; 112 } 113 get()114 T *&get() { 115 return atom; 116 } 117 release()118 T *release() { 119 auto *v = atom; 120 atom = nullptr; 121 return v; 122 } 123 124 private: 125 T *atom = nullptr; 126 }; 127 128 } // end namespace lld 129 130 #endif // LLD_CORE_ATOM_H 131