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 acessible 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