]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
MFV: r336486
[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/RuntimeDyld.h"
21 #include "llvm/ExecutionEngine/Orc/OrcError.h"
22 #include <algorithm>
23 #include <cstdint>
24 #include <string>
25 #include <vector>
26 #include <utility>
27
28 namespace llvm {
29
30 class ConstantArray;
31 class GlobalVariable;
32 class Function;
33 class Module;
34 class Value;
35
36 namespace orc {
37
38 /// @brief This iterator provides a convenient way to iterate over the elements
39 ///        of an llvm.global_ctors/llvm.global_dtors instance.
40 ///
41 ///   The easiest way to get hold of instances of this class is to use the
42 /// getConstructors/getDestructors functions.
43 class CtorDtorIterator {
44 public:
45   /// @brief Accessor for an element of the global_ctors/global_dtors array.
46   ///
47   ///   This class provides a read-only view of the element with any casts on
48   /// the function stripped away.
49   struct Element {
50     Element(unsigned Priority, Function *Func, Value *Data)
51       : Priority(Priority), Func(Func), Data(Data) {}
52
53     unsigned Priority;
54     Function *Func;
55     Value *Data;
56   };
57
58   /// @brief Construct an iterator instance. If End is true then this iterator
59   ///        acts as the end of the range, otherwise it is the beginning.
60   CtorDtorIterator(const GlobalVariable *GV, bool End);
61
62   /// @brief Test iterators for equality.
63   bool operator==(const CtorDtorIterator &Other) const;
64
65   /// @brief Test iterators for inequality.
66   bool operator!=(const CtorDtorIterator &Other) const;
67
68   /// @brief Pre-increment iterator.
69   CtorDtorIterator& operator++();
70
71   /// @brief Post-increment iterator.
72   CtorDtorIterator operator++(int);
73
74   /// @brief Dereference iterator. The resulting value provides a read-only view
75   ///        of this element of the global_ctors/global_dtors list.
76   Element operator*() const;
77
78 private:
79   const ConstantArray *InitList;
80   unsigned I;
81 };
82
83 /// @brief Create an iterator range over the entries of the llvm.global_ctors
84 ///        array.
85 iterator_range<CtorDtorIterator> getConstructors(const Module &M);
86
87 /// @brief Create an iterator range over the entries of the llvm.global_ctors
88 ///        array.
89 iterator_range<CtorDtorIterator> getDestructors(const Module &M);
90
91 /// @brief Convenience class for recording constructor/destructor names for
92 ///        later execution.
93 template <typename JITLayerT>
94 class CtorDtorRunner {
95 public:
96   /// @brief Construct a CtorDtorRunner for the given range using the given
97   ///        name mangling function.
98   CtorDtorRunner(std::vector<std::string> CtorDtorNames,
99                  typename JITLayerT::ModuleHandleT H)
100       : CtorDtorNames(std::move(CtorDtorNames)), H(H) {}
101
102   /// @brief Run the recorded constructors/destructors through the given JIT
103   ///        layer.
104   Error runViaLayer(JITLayerT &JITLayer) const {
105     using CtorDtorTy = void (*)();
106
107     for (const auto &CtorDtorName : CtorDtorNames)
108       if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) {
109         if (auto AddrOrErr = CtorDtorSym.getAddress()) {
110           CtorDtorTy CtorDtor =
111             reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr));
112           CtorDtor();
113         } else
114           return AddrOrErr.takeError();
115       } else {
116         if (auto Err = CtorDtorSym.takeError())
117           return Err;
118         else
119           return make_error<JITSymbolNotFound>(CtorDtorName);
120       }
121     return Error::success();
122   }
123
124 private:
125   std::vector<std::string> CtorDtorNames;
126   typename JITLayerT::ModuleHandleT H;
127 };
128
129 /// @brief Support class for static dtor execution. For hosted (in-process) JITs
130 ///        only!
131 ///
132 ///   If a __cxa_atexit function isn't found C++ programs that use static
133 /// destructors will fail to link. However, we don't want to use the host
134 /// process's __cxa_atexit, because it will schedule JIT'd destructors to run
135 /// after the JIT has been torn down, which is no good. This class makes it easy
136 /// to override __cxa_atexit (and the related __dso_handle).
137 ///
138 ///   To use, clients should manually call searchOverrides from their symbol
139 /// resolver. This should generally be done after attempting symbol resolution
140 /// inside the JIT, but before searching the host process's symbol table. When
141 /// the client determines that destructors should be run (generally at JIT
142 /// teardown or after a return from main), the runDestructors method should be
143 /// called.
144 class LocalCXXRuntimeOverrides {
145 public:
146   /// Create a runtime-overrides class.
147   template <typename MangleFtorT>
148   LocalCXXRuntimeOverrides(const MangleFtorT &Mangle) {
149     addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
150     addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
151   }
152
153   /// Search overrided symbols.
154   JITEvaluatedSymbol searchOverrides(const std::string &Name) {
155     auto I = CXXRuntimeOverrides.find(Name);
156     if (I != CXXRuntimeOverrides.end())
157       return JITEvaluatedSymbol(I->second, JITSymbolFlags::Exported);
158     return nullptr;
159   }
160
161   /// Run any destructors recorded by the overriden __cxa_atexit function
162   /// (CXAAtExitOverride).
163   void runDestructors();
164
165 private:
166   template <typename PtrTy>
167   JITTargetAddress toTargetAddress(PtrTy* P) {
168     return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
169   }
170
171   void addOverride(const std::string &Name, JITTargetAddress Addr) {
172     CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
173   }
174
175   StringMap<JITTargetAddress> CXXRuntimeOverrides;
176
177   using DestructorPtr = void (*)(void *);
178   using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
179   using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
180   CXXDestructorDataPairList DSOHandleOverride;
181   static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
182                                void *DSOHandle);
183 };
184
185 } // end namespace orc
186
187 } // end namespace llvm
188
189 #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H