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