#ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
#define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/ExecutionEngine/Orc/Core.h"
#include "llvm/ExecutionEngine/Orc/Mangling.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/Object/Archive.h"
#include "llvm/Support/DynamicLibrary.h"
#include <algorithm>
#include <cstdint>
#include <utility>
#include <vector>
namespace llvm {
class ConstantArray;
class GlobalVariable;
class Function;
class Module;
class Value;
namespace orc {
class ObjectLayer;
class CtorDtorIterator {
public:
struct Element {
Element(unsigned Priority, Function *Func, Value *Data)
: Priority(Priority), Func(Func), Data(Data) {}
unsigned Priority;
Function *Func;
Value *Data;
};
CtorDtorIterator(const GlobalVariable *GV, bool End);
bool operator==(const CtorDtorIterator &Other) const;
bool operator!=(const CtorDtorIterator &Other) const;
CtorDtorIterator& operator++();
CtorDtorIterator operator++(int);
Element operator*() const;
private:
const ConstantArray *InitList;
unsigned I;
};
iterator_range<CtorDtorIterator> getConstructors(const Module &M);
iterator_range<CtorDtorIterator> getDestructors(const Module &M);
class StaticInitGVIterator {
public:
StaticInitGVIterator() = default;
StaticInitGVIterator(Module &M)
: I(M.global_values().begin()), E(M.global_values().end()),
ObjFmt(Triple(M.getTargetTriple()).getObjectFormat()) {
if (I != E) {
if (!isStaticInitGlobal(*I))
moveToNextStaticInitGlobal();
} else
I = E = Module::global_value_iterator();
}
bool operator==(const StaticInitGVIterator &O) const { return I == O.I; }
bool operator!=(const StaticInitGVIterator &O) const { return I != O.I; }
StaticInitGVIterator &operator++() {
assert(I != E && "Increment past end of range");
moveToNextStaticInitGlobal();
return *this;
}
GlobalValue &operator*() { return *I; }
private:
bool isStaticInitGlobal(GlobalValue &GV);
void moveToNextStaticInitGlobal() {
++I;
while (I != E && !isStaticInitGlobal(*I))
++I;
if (I == E)
I = E = Module::global_value_iterator();
}
Module::global_value_iterator I, E;
Triple::ObjectFormatType ObjFmt;
};
inline iterator_range<StaticInitGVIterator> getStaticInitGVs(Module &M) {
return make_range(StaticInitGVIterator(M), StaticInitGVIterator());
}
class CtorDtorRunner {
public:
CtorDtorRunner(JITDylib &JD) : JD(JD) {}
void add(iterator_range<CtorDtorIterator> CtorDtors);
Error run();
private:
using CtorDtorList = std::vector<SymbolStringPtr>;
using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>;
JITDylib &JD;
CtorDtorPriorityMap CtorDtorsByPriority;
};
class LocalCXXRuntimeOverridesBase {
public:
void runDestructors();
protected:
template <typename PtrTy> JITTargetAddress toTargetAddress(PtrTy *P) {
return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P));
}
using DestructorPtr = void (*)(void *);
using CXXDestructorDataPair = std::pair<DestructorPtr, void *>;
using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>;
CXXDestructorDataPairList DSOHandleOverride;
static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
void *DSOHandle);
};
class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase {
public:
Error enable(JITDylib &JD, MangleAndInterner &Mangler);
};
class ItaniumCXAAtExitSupport {
public:
struct AtExitRecord {
void (*F)(void *);
void *Ctx;
};
void registerAtExit(void (*F)(void *), void *Ctx, void *DSOHandle);
void runAtExits(void *DSOHandle);
private:
std::mutex AtExitsMutex;
DenseMap<void *, std::vector<AtExitRecord>> AtExitRecords;
};
class DynamicLibrarySearchGenerator : public DefinitionGenerator {
public:
using SymbolPredicate = std::function<bool(const SymbolStringPtr &)>;
DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, char GlobalPrefix,
SymbolPredicate Allow = SymbolPredicate());
static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
Load(const char *FileName, char GlobalPrefix,
SymbolPredicate Allow = SymbolPredicate());
static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
GetForCurrentProcess(char GlobalPrefix,
SymbolPredicate Allow = SymbolPredicate()) {
return Load(nullptr, GlobalPrefix, std::move(Allow));
}
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
JITDylibLookupFlags JDLookupFlags,
const SymbolLookupSet &Symbols) override;
private:
sys::DynamicLibrary Dylib;
SymbolPredicate Allow;
char GlobalPrefix;
};
class StaticLibraryDefinitionGenerator : public DefinitionGenerator {
public:
using GetObjectFileInterface =
unique_function<Expected<MaterializationUnit::Interface>(
ExecutionSession &ES, MemoryBufferRef ObjBuffer)>;
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
Load(ObjectLayer &L, const char *FileName,
GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface());
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
Load(ObjectLayer &L, const char *FileName, const Triple &TT,
GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface());
static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
GetObjectFileInterface GetObjFileInterface = GetObjectFileInterface());
Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,
JITDylibLookupFlags JDLookupFlags,
const SymbolLookupSet &Symbols) override;
private:
StaticLibraryDefinitionGenerator(ObjectLayer &L,
std::unique_ptr<MemoryBuffer> ArchiveBuffer,
GetObjectFileInterface GetObjFileInterface,
Error &Err);
ObjectLayer &L;
GetObjectFileInterface GetObjFileInterface;
std::unique_ptr<MemoryBuffer> ArchiveBuffer;
std::unique_ptr<object::Archive> Archive;
};
} }
#endif