]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / ExecutionEngine / Orc / ExecutionUtils.h
1 //===- ExecutionUtils.h - Utilities for executing code in Orc ---*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // Contains utilities for executing code in Orc.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
15 #define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
16
17 #include "llvm/ADT/StringMap.h"
18 #include "llvm/ADT/iterator_range.h"
19 #include "llvm/ExecutionEngine/JITSymbol.h"
20 #include "llvm/ExecutionEngine/Orc/Core.h"
21 #include "llvm/ExecutionEngine/Orc/OrcError.h"
22 #include "llvm/ExecutionEngine/RuntimeDyld.h"
23 #include "llvm/Support/DynamicLibrary.h"
24 #include <algorithm>
25 #include <cstdint>
26 #include <string>
27 #include <utility>
28 #include <vector>
29
30 namespace llvm {
31
32 class ConstantArray;
33 class GlobalVariable;
34 class Function;
35 class Module;
36 class TargetMachine;
37 class Value;
38
39 namespace orc {
40
41 /// This iterator provides a convenient way to iterate over the elements
42 ///        of an llvm.global_ctors/llvm.global_dtors instance.
43 ///
44 ///   The easiest way to get hold of instances of this class is to use the
45 /// getConstructors/getDestructors functions.
46 class CtorDtorIterator {
47 public:
48   /// Accessor for an element of the global_ctors/global_dtors array.
49   ///
50   ///   This class provides a read-only view of the element with any casts on
51   /// the function stripped away.
52   struct Element {
53     Element(unsigned Priority, Function *Func, Value *Data)
54       : Priority(Priority), Func(Func), Data(Data) {}
55
56     unsigned Priority;
57     Function *Func;
58     Value *Data;
59   };
60
61   /// Construct an iterator instance. If End is true then this iterator
62   ///        acts as the end of the range, otherwise it is the beginning.
63   CtorDtorIterator(const GlobalVariable *GV, bool End);
64
65   /// Test iterators for equality.
66   bool operator==(const CtorDtorIterator &Other) const;
67
68   /// Test iterators for inequality.
69   bool operator!=(const CtorDtorIterator &Other) const;
70
71   /// Pre-increment iterator.
72   CtorDtorIterator& operator++();
73
74   /// Post-increment iterator.
75   CtorDtorIterator operator++(int);
76
77   /// Dereference iterator. The resulting value provides a read-only view
78   ///        of this element of the global_ctors/global_dtors list.
79   Element operator*() const;
80
81 private:
82   const ConstantArray *InitList;
83   unsigned I;
84 };
85
86 /// Create an iterator range over the entries of the llvm.global_ctors
87 ///        array.
88 iterator_range<CtorDtorIterator> getConstructors(const Module &M);
89
90 /// Create an iterator range over the entries of the llvm.global_ctors
91 ///        array.
92 iterator_range<CtorDtorIterator> getDestructors(const Module &M);
93
94 /// Convenience class for recording constructor/destructor names for
95 ///        later execution.
96 template <typename JITLayerT>
97 class LegacyCtorDtorRunner {
98 public:
99   /// Construct a CtorDtorRunner for the given range using the given
100   ///        name mangling function.
101   LegacyCtorDtorRunner(std::vector<std::string> CtorDtorNames, VModuleKey K)
102       : CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
103
104   /// Run the recorded constructors/destructors through the given JIT
105   ///        layer.
106   Error runViaLayer(JITLayerT &JITLayer) const {
107     using CtorDtorTy = void (*)();
108
109     for (const auto &CtorDtorName : CtorDtorNames) {
110       if (auto CtorDtorSym = JITLayer.findSymbolIn(K, CtorDtorName, false)) {
111         if (auto AddrOrErr = CtorDtorSym.getAddress()) {
112           CtorDtorTy CtorDtor =
113             reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr));
114           CtorDtor();
115         } else
116           return AddrOrErr.takeError();
117       } else {
118         if (auto Err = CtorDtorSym.takeError())
119           return Err;
120         else
121           return make_error<JITSymbolNotFound>(CtorDtorName);
122       }
123     }
124     return Error::success();
125   }
126
127 private:
128   std::vector<std::string> CtorDtorNames;
129   orc::VModuleKey K;
130 };
131
132 class CtorDtorRunner {
133 public:
134   CtorDtorRunner(JITDylib &JD) : JD(JD) {}
135   void add(iterator_range<CtorDtorIterator> CtorDtors);
136   Error run();
137
138 private:
139   using CtorDtorList = std::vector<SymbolStringPtr>;
140   using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>;
141
142   JITDylib &JD;
143   CtorDtorPriorityMap CtorDtorsByPriority;
144 };
145
146 /// Support class for static dtor execution. For hosted (in-process) JITs
147 ///        only!
148 ///
149 ///   If a __cxa_atexit function isn't found C++ programs that use static
150 /// destructors will fail to link. However, we don't want to use the host
151 /// process's __cxa_atexit, because it will schedule JIT'd destructors to run
152 /// after the JIT has been torn down, which is no good. This class makes it easy
153 /// to override __cxa_atexit (and the related __dso_handle).
154 ///
155 ///   To use, clients should manually call searchOverrides from their symbol
156 /// resolver. This should generally be done after attempting symbol resolution
157 /// inside the JIT, but before searching the host process's symbol table. When
158 /// the client determines that destructors should be run (generally at JIT
159 /// teardown or after a return from main), the runDestructors method should be
160 /// called.
161 class LocalCXXRuntimeOverridesBase {
162 public:
163   /// Run any destructors recorded by the overriden __cxa_atexit function
164   /// (CXAAtExitOverride).
165   void runDestructors();
166
167 protected:
168   template <typename PtrTy> JITTargetAddress toTargetAddress(PtrTy *P) {
169     return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
170   }
171
172   using DestructorPtr = void (*)(void *);
173   using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
174   using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
175   CXXDestructorDataPairList DSOHandleOverride;
176   static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
177                                void *DSOHandle);
178 };
179
180 class LegacyLocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
181 public:
182   /// Create a runtime-overrides class.
183   template <typename MangleFtorT>
184   LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle) {
185     addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
186     addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
187   }
188
189   /// Search overrided symbols.
190   JITEvaluatedSymbol searchOverrides(const std::string &Name) {
191     auto I = CXXRuntimeOverrides.find(Name);
192     if (I != CXXRuntimeOverrides.end())
193       return JITEvaluatedSymbol(I->second, JITSymbolFlags::Exported);
194     return nullptr;
195   }
196
197 private:
198   void addOverride(const std::string &Name, JITTargetAddress Addr) {
199     CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
200   }
201
202   StringMap<JITTargetAddress> CXXRuntimeOverrides;
203 };
204
205 class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
206 public:
207   Error enable(JITDylib &JD, MangleAndInterner &Mangler);
208 };
209
210 /// A utility class to expose symbols found via dlsym to the JIT.
211 ///
212 /// If an instance of this class is attached to a JITDylib as a fallback
213 /// definition generator, then any symbol found in the given DynamicLibrary that
214 /// passes the 'Allow' predicate will be added to the JITDylib.
215 class DynamicLibrarySearchGenerator {
216 public:
217   using SymbolPredicate = std::function<bool(SymbolStringPtr)>;
218
219   /// Create a DynamicLibrarySearchGenerator that searches for symbols in the
220   /// given sys::DynamicLibrary.
221   /// If the Allow predicate is given then only symbols matching the predicate
222   /// will be searched for in the DynamicLibrary. If the predicate is not given
223   /// then all symbols will be searched for.
224   DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, const DataLayout &DL,
225                                 SymbolPredicate Allow = SymbolPredicate());
226
227   /// Permanently loads the library at the given path and, on success, returns
228   /// a DynamicLibrarySearchGenerator that will search it for symbol definitions
229   /// in the library. On failure returns the reason the library failed to load.
230   static Expected<DynamicLibrarySearchGenerator>
231   Load(const char *FileName, const DataLayout &DL,
232        SymbolPredicate Allow = SymbolPredicate());
233
234   /// Creates a DynamicLibrarySearchGenerator that searches for symbols in
235   /// the current process.
236   static Expected<DynamicLibrarySearchGenerator>
237   GetForCurrentProcess(const DataLayout &DL,
238                        SymbolPredicate Allow = SymbolPredicate()) {
239     return Load(nullptr, DL, std::move(Allow));
240   }
241
242   SymbolNameSet operator()(JITDylib &JD, const SymbolNameSet &Names);
243
244 private:
245   sys::DynamicLibrary Dylib;
246   SymbolPredicate Allow;
247   char GlobalPrefix;
248 };
249
250 } // end namespace orc
251 } // end namespace llvm
252
253 #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H