10b57cec5SDimitry Andric //===- ExecutionUtils.h - Utilities for executing code in Orc ---*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // Contains utilities for executing code in Orc.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
140b57cec5SDimitry Andric #define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
170b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
180b57cec5SDimitry Andric #include "llvm/ExecutionEngine/JITSymbol.h"
190b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/Core.h"
205ffd83dbSDimitry Andric #include "llvm/ExecutionEngine/Orc/Mangling.h"
210b57cec5SDimitry Andric #include "llvm/ExecutionEngine/Orc/OrcError.h"
220b57cec5SDimitry Andric #include "llvm/ExecutionEngine/RuntimeDyld.h"
238bcb0991SDimitry Andric #include "llvm/Object/Archive.h"
240b57cec5SDimitry Andric #include "llvm/Support/DynamicLibrary.h"
250b57cec5SDimitry Andric #include <algorithm>
260b57cec5SDimitry Andric #include <cstdint>
270b57cec5SDimitry Andric #include <string>
280b57cec5SDimitry Andric #include <utility>
290b57cec5SDimitry Andric #include <vector>
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric namespace llvm {
320b57cec5SDimitry Andric 
330b57cec5SDimitry Andric class ConstantArray;
340b57cec5SDimitry Andric class GlobalVariable;
350b57cec5SDimitry Andric class Function;
360b57cec5SDimitry Andric class Module;
370b57cec5SDimitry Andric class TargetMachine;
380b57cec5SDimitry Andric class Value;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric namespace orc {
410b57cec5SDimitry Andric 
428bcb0991SDimitry Andric class ObjectLayer;
438bcb0991SDimitry Andric 
44480093f4SDimitry Andric /// Run a main function, returning the result.
45480093f4SDimitry Andric ///
46480093f4SDimitry Andric /// If the optional ProgramName argument is given then it will be inserted
47480093f4SDimitry Andric /// before the strings in Args as the first argument to the called function.
48480093f4SDimitry Andric ///
49480093f4SDimitry Andric /// It is legal to have an empty argument list and no program name, however
50480093f4SDimitry Andric /// many main functions will expect a name argument at least, and will fail
51480093f4SDimitry Andric /// if none is provided.
52480093f4SDimitry Andric int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
53480093f4SDimitry Andric               Optional<StringRef> ProgramName = None);
54480093f4SDimitry Andric 
550b57cec5SDimitry Andric /// This iterator provides a convenient way to iterate over the elements
560b57cec5SDimitry Andric ///        of an llvm.global_ctors/llvm.global_dtors instance.
570b57cec5SDimitry Andric ///
580b57cec5SDimitry Andric ///   The easiest way to get hold of instances of this class is to use the
590b57cec5SDimitry Andric /// getConstructors/getDestructors functions.
600b57cec5SDimitry Andric class CtorDtorIterator {
610b57cec5SDimitry Andric public:
620b57cec5SDimitry Andric   /// Accessor for an element of the global_ctors/global_dtors array.
630b57cec5SDimitry Andric   ///
640b57cec5SDimitry Andric   ///   This class provides a read-only view of the element with any casts on
650b57cec5SDimitry Andric   /// the function stripped away.
660b57cec5SDimitry Andric   struct Element {
670b57cec5SDimitry Andric     Element(unsigned Priority, Function *Func, Value *Data)
680b57cec5SDimitry Andric       : Priority(Priority), Func(Func), Data(Data) {}
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric     unsigned Priority;
710b57cec5SDimitry Andric     Function *Func;
720b57cec5SDimitry Andric     Value *Data;
730b57cec5SDimitry Andric   };
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   /// Construct an iterator instance. If End is true then this iterator
760b57cec5SDimitry Andric   ///        acts as the end of the range, otherwise it is the beginning.
770b57cec5SDimitry Andric   CtorDtorIterator(const GlobalVariable *GV, bool End);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   /// Test iterators for equality.
800b57cec5SDimitry Andric   bool operator==(const CtorDtorIterator &Other) const;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric   /// Test iterators for inequality.
830b57cec5SDimitry Andric   bool operator!=(const CtorDtorIterator &Other) const;
840b57cec5SDimitry Andric 
850b57cec5SDimitry Andric   /// Pre-increment iterator.
860b57cec5SDimitry Andric   CtorDtorIterator& operator++();
870b57cec5SDimitry Andric 
880b57cec5SDimitry Andric   /// Post-increment iterator.
890b57cec5SDimitry Andric   CtorDtorIterator operator++(int);
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   /// Dereference iterator. The resulting value provides a read-only view
920b57cec5SDimitry Andric   ///        of this element of the global_ctors/global_dtors list.
930b57cec5SDimitry Andric   Element operator*() const;
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric private:
960b57cec5SDimitry Andric   const ConstantArray *InitList;
970b57cec5SDimitry Andric   unsigned I;
980b57cec5SDimitry Andric };
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric /// Create an iterator range over the entries of the llvm.global_ctors
1010b57cec5SDimitry Andric ///        array.
1020b57cec5SDimitry Andric iterator_range<CtorDtorIterator> getConstructors(const Module &M);
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric /// Create an iterator range over the entries of the llvm.global_ctors
1050b57cec5SDimitry Andric ///        array.
1060b57cec5SDimitry Andric iterator_range<CtorDtorIterator> getDestructors(const Module &M);
1070b57cec5SDimitry Andric 
1085ffd83dbSDimitry Andric /// This iterator provides a convenient way to iterate over GlobalValues that
1095ffd83dbSDimitry Andric /// have initialization effects.
1105ffd83dbSDimitry Andric class StaticInitGVIterator {
1115ffd83dbSDimitry Andric public:
1125ffd83dbSDimitry Andric   StaticInitGVIterator() = default;
1135ffd83dbSDimitry Andric 
1145ffd83dbSDimitry Andric   StaticInitGVIterator(Module &M)
1155ffd83dbSDimitry Andric       : I(M.global_values().begin()), E(M.global_values().end()),
1165ffd83dbSDimitry Andric         ObjFmt(Triple(M.getTargetTriple()).getObjectFormat()) {
1175ffd83dbSDimitry Andric     if (I != E) {
1185ffd83dbSDimitry Andric       if (!isStaticInitGlobal(*I))
1195ffd83dbSDimitry Andric         moveToNextStaticInitGlobal();
1205ffd83dbSDimitry Andric     } else
1215ffd83dbSDimitry Andric       I = E = Module::global_value_iterator();
1225ffd83dbSDimitry Andric   }
1235ffd83dbSDimitry Andric 
1245ffd83dbSDimitry Andric   bool operator==(const StaticInitGVIterator &O) const { return I == O.I; }
1255ffd83dbSDimitry Andric   bool operator!=(const StaticInitGVIterator &O) const { return I != O.I; }
1265ffd83dbSDimitry Andric 
1275ffd83dbSDimitry Andric   StaticInitGVIterator &operator++() {
1285ffd83dbSDimitry Andric     assert(I != E && "Increment past end of range");
1295ffd83dbSDimitry Andric     moveToNextStaticInitGlobal();
1305ffd83dbSDimitry Andric     return *this;
1315ffd83dbSDimitry Andric   }
1325ffd83dbSDimitry Andric 
1335ffd83dbSDimitry Andric   GlobalValue &operator*() { return *I; }
1345ffd83dbSDimitry Andric 
1355ffd83dbSDimitry Andric private:
1365ffd83dbSDimitry Andric   bool isStaticInitGlobal(GlobalValue &GV);
1375ffd83dbSDimitry Andric   void moveToNextStaticInitGlobal() {
1385ffd83dbSDimitry Andric     ++I;
1395ffd83dbSDimitry Andric     while (I != E && !isStaticInitGlobal(*I))
1405ffd83dbSDimitry Andric       ++I;
1415ffd83dbSDimitry Andric     if (I == E)
1425ffd83dbSDimitry Andric       I = E = Module::global_value_iterator();
1435ffd83dbSDimitry Andric   }
1445ffd83dbSDimitry Andric 
1455ffd83dbSDimitry Andric   Module::global_value_iterator I, E;
1465ffd83dbSDimitry Andric   Triple::ObjectFormatType ObjFmt;
1475ffd83dbSDimitry Andric };
1485ffd83dbSDimitry Andric 
1495ffd83dbSDimitry Andric /// Create an iterator range over the GlobalValues that contribute to static
1505ffd83dbSDimitry Andric /// initialization.
1515ffd83dbSDimitry Andric inline iterator_range<StaticInitGVIterator> getStaticInitGVs(Module &M) {
1525ffd83dbSDimitry Andric   return make_range(StaticInitGVIterator(M), StaticInitGVIterator());
1535ffd83dbSDimitry Andric }
1545ffd83dbSDimitry Andric 
1550b57cec5SDimitry Andric /// Convenience class for recording constructor/destructor names for
1560b57cec5SDimitry Andric ///        later execution.
1570b57cec5SDimitry Andric template <typename JITLayerT>
1580b57cec5SDimitry Andric class LegacyCtorDtorRunner {
1590b57cec5SDimitry Andric public:
1600b57cec5SDimitry Andric   /// Construct a CtorDtorRunner for the given range using the given
1610b57cec5SDimitry Andric   ///        name mangling function.
1620b57cec5SDimitry Andric   LLVM_ATTRIBUTE_DEPRECATED(
1630b57cec5SDimitry Andric       LegacyCtorDtorRunner(std::vector<std::string> CtorDtorNames,
1640b57cec5SDimitry Andric                            VModuleKey K),
1650b57cec5SDimitry Andric       "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. "
1660b57cec5SDimitry Andric       "Please use the ORCv2 CtorDtorRunner utility instead");
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric   LegacyCtorDtorRunner(ORCv1DeprecationAcknowledgement,
1690b57cec5SDimitry Andric                        std::vector<std::string> CtorDtorNames, VModuleKey K)
1700b57cec5SDimitry Andric       : CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   /// Run the recorded constructors/destructors through the given JIT
1730b57cec5SDimitry Andric   ///        layer.
1740b57cec5SDimitry Andric   Error runViaLayer(JITLayerT &JITLayer) const {
1750b57cec5SDimitry Andric     using CtorDtorTy = void (*)();
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric     for (const auto &CtorDtorName : CtorDtorNames) {
1780b57cec5SDimitry Andric       if (auto CtorDtorSym = JITLayer.findSymbolIn(K, CtorDtorName, false)) {
1790b57cec5SDimitry Andric         if (auto AddrOrErr = CtorDtorSym.getAddress()) {
1800b57cec5SDimitry Andric           CtorDtorTy CtorDtor =
1810b57cec5SDimitry Andric             reinterpret_cast<CtorDtorTy>(static_cast<uintptr_t>(*AddrOrErr));
1820b57cec5SDimitry Andric           CtorDtor();
1830b57cec5SDimitry Andric         } else
1840b57cec5SDimitry Andric           return AddrOrErr.takeError();
1850b57cec5SDimitry Andric       } else {
1860b57cec5SDimitry Andric         if (auto Err = CtorDtorSym.takeError())
1870b57cec5SDimitry Andric           return Err;
1880b57cec5SDimitry Andric         else
1890b57cec5SDimitry Andric           return make_error<JITSymbolNotFound>(CtorDtorName);
1900b57cec5SDimitry Andric       }
1910b57cec5SDimitry Andric     }
1920b57cec5SDimitry Andric     return Error::success();
1930b57cec5SDimitry Andric   }
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric private:
1960b57cec5SDimitry Andric   std::vector<std::string> CtorDtorNames;
1970b57cec5SDimitry Andric   orc::VModuleKey K;
1980b57cec5SDimitry Andric };
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric template <typename JITLayerT>
2010b57cec5SDimitry Andric LegacyCtorDtorRunner<JITLayerT>::LegacyCtorDtorRunner(
2020b57cec5SDimitry Andric     std::vector<std::string> CtorDtorNames, VModuleKey K)
2030b57cec5SDimitry Andric     : CtorDtorNames(std::move(CtorDtorNames)), K(K) {}
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric class CtorDtorRunner {
2060b57cec5SDimitry Andric public:
2070b57cec5SDimitry Andric   CtorDtorRunner(JITDylib &JD) : JD(JD) {}
2080b57cec5SDimitry Andric   void add(iterator_range<CtorDtorIterator> CtorDtors);
2090b57cec5SDimitry Andric   Error run();
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric private:
2120b57cec5SDimitry Andric   using CtorDtorList = std::vector<SymbolStringPtr>;
2130b57cec5SDimitry Andric   using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>;
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   JITDylib &JD;
2160b57cec5SDimitry Andric   CtorDtorPriorityMap CtorDtorsByPriority;
2170b57cec5SDimitry Andric };
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric /// Support class for static dtor execution. For hosted (in-process) JITs
2200b57cec5SDimitry Andric ///        only!
2210b57cec5SDimitry Andric ///
2220b57cec5SDimitry Andric ///   If a __cxa_atexit function isn't found C++ programs that use static
2230b57cec5SDimitry Andric /// destructors will fail to link. However, we don't want to use the host
2240b57cec5SDimitry Andric /// process's __cxa_atexit, because it will schedule JIT'd destructors to run
2250b57cec5SDimitry Andric /// after the JIT has been torn down, which is no good. This class makes it easy
2260b57cec5SDimitry Andric /// to override __cxa_atexit (and the related __dso_handle).
2270b57cec5SDimitry Andric ///
2280b57cec5SDimitry Andric ///   To use, clients should manually call searchOverrides from their symbol
2290b57cec5SDimitry Andric /// resolver. This should generally be done after attempting symbol resolution
2300b57cec5SDimitry Andric /// inside the JIT, but before searching the host process's symbol table. When
2310b57cec5SDimitry Andric /// the client determines that destructors should be run (generally at JIT
2320b57cec5SDimitry Andric /// teardown or after a return from main), the runDestructors method should be
2330b57cec5SDimitry Andric /// called.
2340b57cec5SDimitry Andric class LocalCXXRuntimeOverridesBase {
2350b57cec5SDimitry Andric public:
2360b57cec5SDimitry Andric   /// Run any destructors recorded by the overriden __cxa_atexit function
2370b57cec5SDimitry Andric   /// (CXAAtExitOverride).
2380b57cec5SDimitry Andric   void runDestructors();
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric protected:
2410b57cec5SDimitry Andric   template <typename PtrTy> JITTargetAddress toTargetAddress(PtrTy *P) {
2420b57cec5SDimitry Andric     return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
2430b57cec5SDimitry Andric   }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric   using DestructorPtr = void (*)(void *);
2460b57cec5SDimitry Andric   using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
2470b57cec5SDimitry Andric   using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
2480b57cec5SDimitry Andric   CXXDestructorDataPairList DSOHandleOverride;
2490b57cec5SDimitry Andric   static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
2500b57cec5SDimitry Andric                                void *DSOHandle);
2510b57cec5SDimitry Andric };
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric class LegacyLocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
2540b57cec5SDimitry Andric public:
2550b57cec5SDimitry Andric   /// Create a runtime-overrides class.
2560b57cec5SDimitry Andric   template <typename MangleFtorT>
2570b57cec5SDimitry Andric   LLVM_ATTRIBUTE_DEPRECATED(
2580b57cec5SDimitry Andric       LegacyLocalCXXRuntimeOverrides(const MangleFtorT &Mangle),
2590b57cec5SDimitry Andric       "ORCv1 utilities (utilities with the 'Legacy' prefix) are deprecated. "
2600b57cec5SDimitry Andric       "Please use the ORCv2 LocalCXXRuntimeOverrides utility instead");
2610b57cec5SDimitry Andric 
2620b57cec5SDimitry Andric   template <typename MangleFtorT>
2630b57cec5SDimitry Andric   LegacyLocalCXXRuntimeOverrides(ORCv1DeprecationAcknowledgement,
2640b57cec5SDimitry Andric                                  const MangleFtorT &Mangle) {
2650b57cec5SDimitry Andric     addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
2660b57cec5SDimitry Andric     addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
2670b57cec5SDimitry Andric   }
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric   /// Search overrided symbols.
2700b57cec5SDimitry Andric   JITEvaluatedSymbol searchOverrides(const std::string &Name) {
2710b57cec5SDimitry Andric     auto I = CXXRuntimeOverrides.find(Name);
2720b57cec5SDimitry Andric     if (I != CXXRuntimeOverrides.end())
2730b57cec5SDimitry Andric       return JITEvaluatedSymbol(I->second, JITSymbolFlags::Exported);
2740b57cec5SDimitry Andric     return nullptr;
2750b57cec5SDimitry Andric   }
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric private:
2780b57cec5SDimitry Andric   void addOverride(const std::string &Name, JITTargetAddress Addr) {
2790b57cec5SDimitry Andric     CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
2800b57cec5SDimitry Andric   }
2810b57cec5SDimitry Andric 
2820b57cec5SDimitry Andric   StringMap<JITTargetAddress> CXXRuntimeOverrides;
2830b57cec5SDimitry Andric };
2840b57cec5SDimitry Andric 
2850b57cec5SDimitry Andric template <typename MangleFtorT>
2860b57cec5SDimitry Andric LegacyLocalCXXRuntimeOverrides::LegacyLocalCXXRuntimeOverrides(
2870b57cec5SDimitry Andric     const MangleFtorT &Mangle) {
2880b57cec5SDimitry Andric   addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
2890b57cec5SDimitry Andric   addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
2900b57cec5SDimitry Andric }
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
2930b57cec5SDimitry Andric public:
2940b57cec5SDimitry Andric   Error enable(JITDylib &JD, MangleAndInterner &Mangler);
2950b57cec5SDimitry Andric };
2960b57cec5SDimitry Andric 
2975ffd83dbSDimitry Andric /// An interface for Itanium __cxa_atexit interposer implementations.
2985ffd83dbSDimitry Andric class ItaniumCXAAtExitSupport {
2995ffd83dbSDimitry Andric public:
3005ffd83dbSDimitry Andric   struct AtExitRecord {
3015ffd83dbSDimitry Andric     void (*F)(void *);
3025ffd83dbSDimitry Andric     void *Ctx;
3035ffd83dbSDimitry Andric   };
3045ffd83dbSDimitry Andric 
3055ffd83dbSDimitry Andric   void registerAtExit(void (*F)(void *), void *Ctx, void *DSOHandle);
3065ffd83dbSDimitry Andric   void runAtExits(void *DSOHandle);
3075ffd83dbSDimitry Andric 
3085ffd83dbSDimitry Andric private:
3095ffd83dbSDimitry Andric   std::mutex AtExitsMutex;
3105ffd83dbSDimitry Andric   DenseMap<void *, std::vector<AtExitRecord>> AtExitRecords;
3115ffd83dbSDimitry Andric };
3125ffd83dbSDimitry Andric 
3130b57cec5SDimitry Andric /// A utility class to expose symbols found via dlsym to the JIT.
3140b57cec5SDimitry Andric ///
3150b57cec5SDimitry Andric /// If an instance of this class is attached to a JITDylib as a fallback
3160b57cec5SDimitry Andric /// definition generator, then any symbol found in the given DynamicLibrary that
3170b57cec5SDimitry Andric /// passes the 'Allow' predicate will be added to the JITDylib.
3188bcb0991SDimitry Andric class DynamicLibrarySearchGenerator : public JITDylib::DefinitionGenerator {
3190b57cec5SDimitry Andric public:
320480093f4SDimitry Andric   using SymbolPredicate = std::function<bool(const SymbolStringPtr &)>;
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric   /// Create a DynamicLibrarySearchGenerator that searches for symbols in the
3230b57cec5SDimitry Andric   /// given sys::DynamicLibrary.
3240b57cec5SDimitry Andric   ///
3250b57cec5SDimitry Andric   /// If the Allow predicate is given then only symbols matching the predicate
3260b57cec5SDimitry Andric   /// will be searched for. If the predicate is not given then all symbols will
3270b57cec5SDimitry Andric   /// be searched for.
3280b57cec5SDimitry Andric   DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, char GlobalPrefix,
3290b57cec5SDimitry Andric                                 SymbolPredicate Allow = SymbolPredicate());
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric   /// Permanently loads the library at the given path and, on success, returns
3320b57cec5SDimitry Andric   /// a DynamicLibrarySearchGenerator that will search it for symbol definitions
3330b57cec5SDimitry Andric   /// in the library. On failure returns the reason the library failed to load.
3348bcb0991SDimitry Andric   static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
3350b57cec5SDimitry Andric   Load(const char *FileName, char GlobalPrefix,
3360b57cec5SDimitry Andric        SymbolPredicate Allow = SymbolPredicate());
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   /// Creates a DynamicLibrarySearchGenerator that searches for symbols in
3390b57cec5SDimitry Andric   /// the current process.
3408bcb0991SDimitry Andric   static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
3410b57cec5SDimitry Andric   GetForCurrentProcess(char GlobalPrefix,
3420b57cec5SDimitry Andric                        SymbolPredicate Allow = SymbolPredicate()) {
3430b57cec5SDimitry Andric     return Load(nullptr, GlobalPrefix, std::move(Allow));
3440b57cec5SDimitry Andric   }
3450b57cec5SDimitry Andric 
346480093f4SDimitry Andric   Error tryToGenerate(LookupKind K, JITDylib &JD,
347480093f4SDimitry Andric                       JITDylibLookupFlags JDLookupFlags,
348480093f4SDimitry Andric                       const SymbolLookupSet &Symbols) override;
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric private:
3510b57cec5SDimitry Andric   sys::DynamicLibrary Dylib;
3520b57cec5SDimitry Andric   SymbolPredicate Allow;
3530b57cec5SDimitry Andric   char GlobalPrefix;
3540b57cec5SDimitry Andric };
3550b57cec5SDimitry Andric 
3568bcb0991SDimitry Andric /// A utility class to expose symbols from a static library.
3578bcb0991SDimitry Andric ///
3588bcb0991SDimitry Andric /// If an instance of this class is attached to a JITDylib as a fallback
3598bcb0991SDimitry Andric /// definition generator, then any symbol found in the archive will result in
3608bcb0991SDimitry Andric /// the containing object being added to the JITDylib.
3618bcb0991SDimitry Andric class StaticLibraryDefinitionGenerator : public JITDylib::DefinitionGenerator {
3628bcb0991SDimitry Andric public:
3638bcb0991SDimitry Andric   /// Try to create a StaticLibraryDefinitionGenerator from the given path.
3648bcb0991SDimitry Andric   ///
3658bcb0991SDimitry Andric   /// This call will succeed if the file at the given path is a static library
3668bcb0991SDimitry Andric   /// is a valid archive, otherwise it will return an error.
3678bcb0991SDimitry Andric   static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
3688bcb0991SDimitry Andric   Load(ObjectLayer &L, const char *FileName);
3698bcb0991SDimitry Andric 
3705ffd83dbSDimitry Andric   /// Try to create a StaticLibraryDefinitionGenerator from the given path.
3715ffd83dbSDimitry Andric   ///
3725ffd83dbSDimitry Andric   /// This call will succeed if the file at the given path is a static library
3735ffd83dbSDimitry Andric   /// or a MachO universal binary containing a static library that is compatible
3745ffd83dbSDimitry Andric   /// with the given triple. Otherwise it will return an error.
3755ffd83dbSDimitry Andric   static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
3765ffd83dbSDimitry Andric   Load(ObjectLayer &L, const char *FileName, const Triple &TT);
3775ffd83dbSDimitry Andric 
3788bcb0991SDimitry Andric   /// Try to create a StaticLibrarySearchGenerator from the given memory buffer.
379480093f4SDimitry Andric   /// This call will succeed if the buffer contains a valid archive, otherwise
3808bcb0991SDimitry Andric   /// it will return an error.
3818bcb0991SDimitry Andric   static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
3828bcb0991SDimitry Andric   Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer);
3838bcb0991SDimitry Andric 
384480093f4SDimitry Andric   Error tryToGenerate(LookupKind K, JITDylib &JD,
385480093f4SDimitry Andric                       JITDylibLookupFlags JDLookupFlags,
386480093f4SDimitry Andric                       const SymbolLookupSet &Symbols) override;
3878bcb0991SDimitry Andric 
3888bcb0991SDimitry Andric private:
3898bcb0991SDimitry Andric   StaticLibraryDefinitionGenerator(ObjectLayer &L,
3908bcb0991SDimitry Andric                                    std::unique_ptr<MemoryBuffer> ArchiveBuffer,
3918bcb0991SDimitry Andric                                    Error &Err);
3928bcb0991SDimitry Andric 
3938bcb0991SDimitry Andric   ObjectLayer &L;
3948bcb0991SDimitry Andric   std::unique_ptr<MemoryBuffer> ArchiveBuffer;
395480093f4SDimitry Andric   std::unique_ptr<object::Archive> Archive;
3968bcb0991SDimitry Andric };
3978bcb0991SDimitry Andric 
3980b57cec5SDimitry Andric } // end namespace orc
3990b57cec5SDimitry Andric } // end namespace llvm
4000b57cec5SDimitry Andric 
4010b57cec5SDimitry Andric #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
402