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