summaryrefslogtreecommitdiffstats
path: root/include/llvm/ExecutionEngine
diff options
context:
space:
mode:
authorPirama Arumuga Nainar <pirama@google.com>2015-05-06 11:46:36 -0700
committerPirama Arumuga Nainar <pirama@google.com>2015-05-18 10:52:30 -0700
commit2c3e0051c31c3f5b2328b447eadf1cf9c4427442 (patch)
treec0104029af14e9f47c2ef58ca60e6137691f3c9b /include/llvm/ExecutionEngine
parente1bc145815f4334641be19f1c45ecf85d25b6e5a (diff)
downloadexternal_llvm-2c3e0051c31c3f5b2328b447eadf1cf9c4427442.zip
external_llvm-2c3e0051c31c3f5b2328b447eadf1cf9c4427442.tar.gz
external_llvm-2c3e0051c31c3f5b2328b447eadf1cf9c4427442.tar.bz2
Update aosp/master LLVM for rebase to r235153
Change-Id: I9bf53792f9fc30570e81a8d80d296c681d005ea7 (cherry picked from commit 0c7f116bb6950ef819323d855415b2f2b0aad987)
Diffstat (limited to 'include/llvm/ExecutionEngine')
-rw-r--r--include/llvm/ExecutionEngine/ExecutionEngine.h71
-rw-r--r--include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h96
-rw-r--r--include/llvm/ExecutionEngine/Orc/ExecutionUtils.h182
-rw-r--r--include/llvm/ExecutionEngine/Orc/IRCompileLayer.h14
-rw-r--r--include/llvm/ExecutionEngine/Orc/IRTransformLayer.h101
-rw-r--r--include/llvm/ExecutionEngine/Orc/IndirectionUtils.h54
-rw-r--r--include/llvm/ExecutionEngine/Orc/JITSymbol.h2
-rw-r--r--include/llvm/ExecutionEngine/Orc/LambdaResolver.h62
-rw-r--r--include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h45
-rw-r--r--include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h92
-rw-r--r--include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h105
-rw-r--r--include/llvm/ExecutionEngine/RTDyldMemoryManager.h138
-rw-r--r--include/llvm/ExecutionEngine/RuntimeDyld.h114
-rw-r--r--include/llvm/ExecutionEngine/SectionMemoryManager.h4
14 files changed, 745 insertions, 335 deletions
diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h
index abdaa0c..4b2add8 100644
--- a/include/llvm/ExecutionEngine/ExecutionEngine.h
+++ b/include/llvm/ExecutionEngine/ExecutionEngine.h
@@ -15,6 +15,7 @@
#ifndef LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H
#define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H
+#include "RuntimeDyld.h"
#include "llvm-c/ExecutionEngine.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
@@ -42,6 +43,7 @@ class GlobalVariable;
class GlobalValue;
class JITEventListener;
class MachineCodeInfo;
+class MCJITMemoryManager;
class MutexGuard;
class ObjectCache;
class RTDyldMemoryManager;
@@ -57,46 +59,34 @@ namespace object {
/// table. Access to this class should be serialized under a mutex.
class ExecutionEngineState {
public:
- struct AddressMapConfig : public ValueMapConfig<const GlobalValue*> {
- typedef ExecutionEngineState *ExtraData;
- static sys::Mutex *getMutex(ExecutionEngineState *EES);
- static void onDelete(ExecutionEngineState *EES, const GlobalValue *Old);
- static void onRAUW(ExecutionEngineState *, const GlobalValue *,
- const GlobalValue *);
- };
-
- typedef ValueMap<const GlobalValue *, void *, AddressMapConfig>
- GlobalAddressMapTy;
+ typedef StringMap<uint64_t> GlobalAddressMapTy;
private:
- ExecutionEngine &EE;
- /// GlobalAddressMap - A mapping between LLVM global values and their
- /// actualized version...
+ /// GlobalAddressMap - A mapping between LLVM global symbol names values and
+ /// their actualized version...
GlobalAddressMapTy GlobalAddressMap;
/// GlobalAddressReverseMap - This is the reverse mapping of GlobalAddressMap,
/// used to convert raw addresses into the LLVM global value that is emitted
/// at the address. This map is not computed unless getGlobalValueAtAddress
/// is called at some point.
- std::map<void *, AssertingVH<const GlobalValue> > GlobalAddressReverseMap;
+ std::map<uint64_t, std::string> GlobalAddressReverseMap;
public:
- ExecutionEngineState(ExecutionEngine &EE);
GlobalAddressMapTy &getGlobalAddressMap() {
return GlobalAddressMap;
}
- std::map<void*, AssertingVH<const GlobalValue> > &
- getGlobalAddressReverseMap() {
+ std::map<uint64_t, std::string> &getGlobalAddressReverseMap() {
return GlobalAddressReverseMap;
}
/// \brief Erase an entry from the mapping table.
///
/// \returns The address that \p ToUnmap was happed to.
- void *RemoveMapping(const GlobalValue *ToUnmap);
+ uint64_t RemoveMapping(StringRef Name);
};
/// \brief Abstract interface for implementation execution of LLVM modules,
@@ -139,15 +129,17 @@ protected:
virtual char *getMemoryForGV(const GlobalVariable *GV);
static ExecutionEngine *(*MCJITCtor)(
- std::unique_ptr<Module> M,
- std::string *ErrorStr,
- std::unique_ptr<RTDyldMemoryManager> MCJMM,
- std::unique_ptr<TargetMachine> TM);
+ std::unique_ptr<Module> M,
+ std::string *ErrorStr,
+ std::shared_ptr<MCJITMemoryManager> MM,
+ std::shared_ptr<RuntimeDyld::SymbolResolver> SR,
+ std::unique_ptr<TargetMachine> TM);
static ExecutionEngine *(*OrcMCJITReplacementCtor)(
- std::string *ErrorStr,
- std::unique_ptr<RTDyldMemoryManager> OrcJMM,
- std::unique_ptr<TargetMachine> TM);
+ std::string *ErrorStr,
+ std::shared_ptr<MCJITMemoryManager> MM,
+ std::shared_ptr<RuntimeDyld::SymbolResolver> SR,
+ std::unique_ptr<TargetMachine> TM);
static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M,
std::string *ErrorStr);
@@ -157,6 +149,9 @@ protected:
/// abort.
void *(*LazyFunctionCreator)(const std::string &);
+ /// getMangledName - Get mangled name.
+ std::string getMangledName(const GlobalValue *GV);
+
public:
/// lock - This lock protects the ExecutionEngine and MCJIT classes. It must
/// be held while changing the internal state of any of those classes.
@@ -228,7 +223,8 @@ public:
/// Map the address of a JIT section as returned from the memory manager
/// to the address in the target process as the running code will see it.
/// This is the address which will be used for relocation resolution.
- virtual void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) {
+ virtual void mapSectionAddress(const void *LocalAddress,
+ uint64_t TargetAddress) {
llvm_unreachable("Re-mapping of section addresses not supported with this "
"EE!");
}
@@ -286,6 +282,7 @@ public:
/// existing data in memory. Mappings are automatically removed when their
/// GlobalValue is destroyed.
void addGlobalMapping(const GlobalValue *GV, void *Addr);
+ void addGlobalMapping(StringRef Name, uint64_t Addr);
/// clearAllGlobalMappings - Clear all global mappings and start over again,
/// for use in dynamic compilation scenarios to move globals.
@@ -299,14 +296,17 @@ public:
/// address. This updates both maps as required. If "Addr" is null, the
/// entry for the global is removed from the mappings. This returns the old
/// value of the pointer, or null if it was not in the map.
- void *updateGlobalMapping(const GlobalValue *GV, void *Addr);
+ uint64_t updateGlobalMapping(const GlobalValue *GV, void *Addr);
+ uint64_t updateGlobalMapping(StringRef Name, uint64_t Addr);
+
+ /// getAddressToGlobalIfAvailable - This returns the address of the specified
+ /// global symbol.
+ uint64_t getAddressToGlobalIfAvailable(StringRef S);
/// getPointerToGlobalIfAvailable - This returns the address of the specified
/// global value if it is has already been codegen'd, otherwise it returns
/// null.
- ///
- /// This function is deprecated for the MCJIT execution engine. It doesn't
- /// seem to be needed in that case, but an equivalent can be added if it is.
+ void *getPointerToGlobalIfAvailable(StringRef S);
void *getPointerToGlobalIfAvailable(const GlobalValue *GV);
/// getPointerToGlobal - This returns the address of the specified global
@@ -470,7 +470,7 @@ public:
}
protected:
- ExecutionEngine() : EEState(*this) {}
+ ExecutionEngine() {}
explicit ExecutionEngine(std::unique_ptr<Module> M);
void emitGlobals();
@@ -500,7 +500,8 @@ private:
EngineKind::Kind WhichEngine;
std::string *ErrorStr;
CodeGenOpt::Level OptLevel;
- std::unique_ptr<RTDyldMemoryManager> MCJMM;
+ std::shared_ptr<MCJITMemoryManager> MemMgr;
+ std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver;
TargetOptions Options;
Reloc::Model RelocModel;
CodeModel::Model CMModel;
@@ -535,6 +536,12 @@ public:
/// memory manager. This option defaults to NULL.
EngineBuilder &setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm);
+ EngineBuilder&
+ setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
+
+ EngineBuilder&
+ setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR);
+
/// setErrorStr - Set the error string to write to on error. This option
/// defaults to NULL.
EngineBuilder &setErrorStr(std::string *e) {
diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
index 77b0c48..30f7f1c 100644
--- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h
@@ -16,7 +16,7 @@
#define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H
#include "IndirectionUtils.h"
-#include "LookasideRTDyldMM.h"
+#include "LambdaResolver.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include <list>
@@ -36,7 +36,7 @@ namespace orc {
/// compiled only when it is first called.
template <typename BaseLayerT, typename CompileCallbackMgrT>
class CompileOnDemandLayer {
-public:
+private:
/// @brief Lookup helper that provides compatibility with the classic
/// static-compilation symbol resolution process.
///
@@ -64,6 +64,8 @@ public:
/// @brief Construct a scoped lookup.
CODScopedLookup(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
+ virtual ~CODScopedLookup() {}
+
/// @brief Start a new context for a single logical module.
LMHandle createLogicalModule() {
Handles.push_back(SiblingHandlesList());
@@ -92,6 +94,10 @@ public:
return nullptr;
}
+ /// @brief Find an external symbol (via the user supplied SymbolResolver).
+ virtual RuntimeDyld::SymbolInfo
+ externalLookup(const std::string &Name) const = 0;
+
private:
JITSymbol findSymbolIn(LMHandle LMH, const std::string &Name) {
@@ -105,7 +111,29 @@ public:
PseudoDylibModuleSetHandlesList Handles;
};
-private:
+ template <typename ResolverPtrT>
+ class CODScopedLookupImpl : public CODScopedLookup {
+ public:
+ CODScopedLookupImpl(BaseLayerT &BaseLayer, ResolverPtrT Resolver)
+ : CODScopedLookup(BaseLayer), Resolver(std::move(Resolver)) {}
+
+ RuntimeDyld::SymbolInfo
+ externalLookup(const std::string &Name) const override {
+ return Resolver->findSymbol(Name);
+ }
+
+ private:
+ ResolverPtrT Resolver;
+ };
+
+ template <typename ResolverPtrT>
+ static std::shared_ptr<CODScopedLookup>
+ createCODScopedLookup(BaseLayerT &BaseLayer,
+ ResolverPtrT Resolver) {
+ typedef CODScopedLookupImpl<ResolverPtrT> Impl;
+ return std::make_shared<Impl>(BaseLayer, std::move(Resolver));
+ }
+
typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT;
typedef std::vector<BaseLayerModuleSetHandleT> BaseLayerModuleSetHandleListT;
@@ -138,36 +166,31 @@ public:
/// @brief Handle to a set of loaded modules.
typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT;
- // @brief Fallback lookup functor.
- typedef std::function<uint64_t(const std::string &)> LookupFtor;
-
/// @brief Construct a compile-on-demand layer instance.
CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr)
: BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr) {}
/// @brief Add a module to the compile-on-demand layer.
- template <typename ModuleSetT>
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
ModuleSetHandleT addModuleSet(ModuleSetT Ms,
- LookupFtor FallbackLookup = nullptr) {
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
- // If the user didn't supply a fallback lookup then just use
- // getSymbolAddress.
- if (!FallbackLookup)
- FallbackLookup = [=](const std::string &Name) {
- return findSymbol(Name, true).getAddress();
- };
+ assert(MemMgr == nullptr &&
+ "User supplied memory managers not supported with COD yet.");
// Create a lookup context and ModuleSetInfo for this module set.
// For the purposes of symbol resolution the set Ms will be treated as if
// the modules it contained had been linked together as a dylib.
- auto DylibLookup = std::make_shared<CODScopedLookup>(BaseLayer);
+ auto DylibLookup = createCODScopedLookup(BaseLayer, std::move(Resolver));
ModuleSetHandleT H =
ModuleSetInfos.insert(ModuleSetInfos.end(), ModuleSetInfo(DylibLookup));
ModuleSetInfo &MSI = ModuleSetInfos.back();
// Process each of the modules in this module set.
for (auto &M : Ms)
- partitionAndAdd(*M, MSI, FallbackLookup);
+ partitionAndAdd(*M, MSI);
return H;
}
@@ -203,8 +226,7 @@ public:
private:
- void partitionAndAdd(Module &M, ModuleSetInfo &MSI,
- LookupFtor FallbackLookup) {
+ void partitionAndAdd(Module &M, ModuleSetInfo &MSI) {
const char *AddrSuffix = "$orc_addr";
const char *BodySuffix = "$orc_body";
@@ -224,8 +246,7 @@ private:
auto FunctionModules = std::move(PartitionedModule.Functions);
// Emit the commons stright away.
- auto CommonHandle = addModule(std::move(CommonsModule), MSI, LogicalModule,
- FallbackLookup);
+ auto CommonHandle = addModule(std::move(CommonsModule), MSI, LogicalModule);
BaseLayer.emitAndFinalize(CommonHandle);
// Map of definition names to callback-info data structures. We'll use
@@ -255,10 +276,12 @@ private:
Function *Proto = StubsModule->getFunction(Name);
assert(Proto && "Failed to clone function decl into stubs module.");
auto CallbackInfo =
- CompileCallbackMgr.getCompileCallback(*Proto->getFunctionType());
+ CompileCallbackMgr.getCompileCallback(Proto->getContext());
GlobalVariable *FunctionBodyPointer =
- createImplPointer(*Proto, Name + AddrSuffix,
- CallbackInfo.getAddress());
+ createImplPointer(*Proto->getType(), *Proto->getParent(),
+ Name + AddrSuffix,
+ createIRTypedAddress(*Proto->getFunctionType(),
+ CallbackInfo.getAddress()));
makeStub(*Proto, *FunctionBodyPointer);
F.setName(Name + BodySuffix);
@@ -268,7 +291,7 @@ private:
NewStubInfos.push_back(StubInfos.insert(StubInfos.begin(), KV));
}
- auto H = addModule(std::move(SubM), MSI, LogicalModule, FallbackLookup);
+ auto H = addModule(std::move(SubM), MSI, LogicalModule);
// Set the compile actions for this module:
for (auto &KVPair : NewStubInfos) {
@@ -286,7 +309,7 @@ private:
// Ok - we've processed all the partitioned modules. Now add the
// stubs/globals module and set the update actions.
auto StubsH =
- addModule(std::move(StubsModule), MSI, LogicalModule, FallbackLookup);
+ addModule(std::move(StubsModule), MSI, LogicalModule);
for (auto &KVPair : StubInfos) {
std::string AddrName = Mangle(KVPair.first + AddrSuffix,
@@ -304,8 +327,7 @@ private:
BaseLayerModuleSetHandleT addModule(
std::unique_ptr<Module> M,
ModuleSetInfo &MSI,
- typename CODScopedLookup::LMHandle LogicalModule,
- LookupFtor FallbackLookup) {
+ typename CODScopedLookup::LMHandle LogicalModule) {
// Add this module to the JIT with a memory manager that uses the
// DylibLookup to resolve symbols.
@@ -313,19 +335,25 @@ private:
MSet.push_back(std::move(M));
auto DylibLookup = MSI.Lookup;
- auto MM =
- createLookasideRTDyldMM<SectionMemoryManager>(
+ auto Resolver =
+ createLambdaResolver(
[=](const std::string &Name) {
if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name))
- return Symbol.getAddress();
- return FallbackLookup(Name);
+ return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
+ Symbol.getFlags());
+ return DylibLookup->externalLookup(Name);
},
- [=](const std::string &Name) {
- return DylibLookup->findSymbol(LogicalModule, Name).getAddress();
+ [=](const std::string &Name) -> RuntimeDyld::SymbolInfo {
+ if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name))
+ return RuntimeDyld::SymbolInfo(Symbol.getAddress(),
+ Symbol.getFlags());
+ return nullptr;
});
BaseLayerModuleSetHandleT H =
- BaseLayer.addModuleSet(std::move(MSet), std::move(MM));
+ BaseLayer.addModuleSet(std::move(MSet),
+ make_unique<SectionMemoryManager>(),
+ std::move(Resolver));
// Add this module to the logical module lookup.
DylibLookup->addToLogicalModule(LogicalModule, H);
MSI.BaseLayerModuleSetHandles.push_back(H);
diff --git a/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
new file mode 100644
index 0000000..c10508c
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h
@@ -0,0 +1,182 @@
+//===-- ExecutionUtils.h - Utilities for executing code in Orc --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Contains utilities for executing code in Orc.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
+#define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
+
+#include "JITSymbol.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include <vector>
+
+namespace llvm {
+
+class ConstantArray;
+class GlobalVariable;
+class Function;
+class Module;
+class Value;
+
+namespace orc {
+
+/// @brief This iterator provides a convenient way to iterate over the elements
+/// of an llvm.global_ctors/llvm.global_dtors instance.
+///
+/// The easiest way to get hold of instances of this class is to use the
+/// getConstructors/getDestructors functions.
+class CtorDtorIterator {
+public:
+
+ /// @brief Accessor for an element of the global_ctors/global_dtors array.
+ ///
+ /// This class provides a read-only view of the element with any casts on
+ /// the function stripped away.
+ struct Element {
+ Element(unsigned Priority, const Function *Func, const Value *Data)
+ : Priority(Priority), Func(Func), Data(Data) {}
+
+ unsigned Priority;
+ const Function *Func;
+ const Value *Data;
+ };
+
+ /// @brief Construct an iterator instance. If End is true then this iterator
+ /// acts as the end of the range, otherwise it is the beginning.
+ CtorDtorIterator(const GlobalVariable *GV, bool End);
+
+ /// @brief Test iterators for equality.
+ bool operator==(const CtorDtorIterator &Other) const;
+
+ /// @brief Test iterators for inequality.
+ bool operator!=(const CtorDtorIterator &Other) const;
+
+ /// @brief Pre-increment iterator.
+ CtorDtorIterator& operator++();
+
+ /// @brief Post-increment iterator.
+ CtorDtorIterator operator++(int);
+
+ /// @brief Dereference iterator. The resulting value provides a read-only view
+ /// of this element of the global_ctors/global_dtors list.
+ Element operator*() const;
+
+private:
+ const ConstantArray *InitList;
+ unsigned I;
+};
+
+/// @brief Create an iterator range over the entries of the llvm.global_ctors
+/// array.
+iterator_range<CtorDtorIterator> getConstructors(const Module &M);
+
+/// @brief Create an iterator range over the entries of the llvm.global_ctors
+/// array.
+iterator_range<CtorDtorIterator> getDestructors(const Module &M);
+
+/// @brief Convenience class for recording constructor/destructor names for
+/// later execution.
+template <typename JITLayerT>
+class CtorDtorRunner {
+public:
+
+ /// @brief Construct a CtorDtorRunner for the given range using the given
+ /// name mangling function.
+ CtorDtorRunner(std::vector<std::string> CtorDtorNames,
+ typename JITLayerT::ModuleSetHandleT H)
+ : CtorDtorNames(std::move(CtorDtorNames)), H(H) {}
+
+ /// @brief Run the recorded constructors/destructors through the given JIT
+ /// layer.
+ bool runViaLayer(JITLayerT &JITLayer) const {
+ typedef void (*CtorDtorTy)();
+
+ bool Error = false;
+ for (const auto &CtorDtorName : CtorDtorNames)
+ if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) {
+ CtorDtorTy CtorDtor =
+ reinterpret_cast<CtorDtorTy>(
+ static_cast<uintptr_t>(CtorDtorSym.getAddress()));
+ CtorDtor();
+ } else
+ Error = true;
+ return !Error;
+ }
+
+private:
+ std::vector<std::string> CtorDtorNames;
+ typename JITLayerT::ModuleSetHandleT H;
+};
+
+/// @brief Support class for static dtor execution. For hosted (in-process) JITs
+/// only!
+///
+/// If a __cxa_atexit function isn't found C++ programs that use static
+/// destructors will fail to link. However, we don't want to use the host
+/// process's __cxa_atexit, because it will schedule JIT'd destructors to run
+/// after the JIT has been torn down, which is no good. This class makes it easy
+/// to override __cxa_atexit (and the related __dso_handle).
+///
+/// To use, clients should manually call searchOverrides from their symbol
+/// resolver. This should generally be done after attempting symbol resolution
+/// inside the JIT, but before searching the host process's symbol table. When
+/// the client determines that destructors should be run (generally at JIT
+/// teardown or after a return from main), the runDestructors method should be
+/// called.
+class LocalCXXRuntimeOverrides {
+public:
+
+ /// Create a runtime-overrides class.
+ template <typename MangleFtorT>
+ LocalCXXRuntimeOverrides(const MangleFtorT &Mangle) {
+ addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride));
+ addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride));
+ }
+
+ /// Search overrided symbols.
+ RuntimeDyld::SymbolInfo searchOverrides(const std::string &Name) {
+ auto I = CXXRuntimeOverrides.find(Name);
+ if (I != CXXRuntimeOverrides.end())
+ return RuntimeDyld::SymbolInfo(I->second, JITSymbolFlags::Exported);
+ return nullptr;
+ }
+
+ /// Run any destructors recorded by the overriden __cxa_atexit function
+ /// (CXAAtExitOverride).
+ void runDestructors();
+
+private:
+
+ template <typename PtrTy>
+ TargetAddress toTargetAddress(PtrTy* P) {
+ return static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(P));
+ }
+
+ void addOverride(const std::string &Name, TargetAddress Addr) {
+ CXXRuntimeOverrides.insert(std::make_pair(Name, Addr));
+ }
+
+ StringMap<TargetAddress> CXXRuntimeOverrides;
+
+ typedef void (*DestructorPtr)(void*);
+ typedef std::pair<DestructorPtr, void*> CXXDestructorDataPair;
+ typedef std::vector<CXXDestructorDataPair> CXXDestructorDataPairList;
+ CXXDestructorDataPairList DSOHandleOverride;
+ static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg,
+ void *DSOHandle);
+};
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H
diff --git a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
index 6a47622..6379022 100644
--- a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h
@@ -52,14 +52,16 @@ public:
/// @brief Set an ObjectCache to query before compiling.
void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; }
- /// @brief Compile each module in the given module set, then then add the
- /// resulting set of objects to the base layer, along with the memory
- // manager MM.
+ /// @brief Compile each module in the given module set, then add the resulting
+ /// set of objects to the base layer along with the memory manager and
+ /// symbol resolver.
///
/// @return A handle for the added modules.
- template <typename ModuleSetT>
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
ModuleSetHandleT addModuleSet(ModuleSetT Ms,
- std::unique_ptr<RTDyldMemoryManager> MM) {
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
OwningObjectVec Objects;
OwningBufferVec Buffers;
@@ -81,7 +83,7 @@ public:
}
ModuleSetHandleT H =
- BaseLayer.addObjectSet(Objects, std::move(MM));
+ BaseLayer.addObjectSet(Objects, std::move(MemMgr), std::move(Resolver));
BaseLayer.takeOwnershipOfBuffers(H, std::move(Buffers));
diff --git a/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
new file mode 100644
index 0000000..4dabb9a
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h
@@ -0,0 +1,101 @@
+//===----- IRTransformLayer.h - Run all IR through a functor ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Run all IR passed in through a user supplied functor.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
+#define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
+
+#include "JITSymbol.h"
+
+namespace llvm {
+namespace orc {
+
+/// @brief IR mutating layer.
+///
+/// This layer accepts sets of LLVM IR Modules (via addModuleSet). It
+/// immediately applies the user supplied functor to each module, then adds
+/// the set of transformed modules to the layer below.
+template <typename BaseLayerT, typename TransformFtor>
+class IRTransformLayer {
+public:
+ /// @brief Handle to a set of added modules.
+ typedef typename BaseLayerT::ModuleSetHandleT ModuleSetHandleT;
+
+ /// @brief Construct an IRTransformLayer with the given BaseLayer
+ IRTransformLayer(BaseLayerT &BaseLayer,
+ TransformFtor Transform = TransformFtor())
+ : BaseLayer(BaseLayer), Transform(std::move(Transform)) {}
+
+ /// @brief Apply the transform functor to each module in the module set, then
+ /// add the resulting set of modules to the base layer, along with the
+ /// memory manager and symbol resolver.
+ ///
+ /// @return A handle for the added modules.
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
+ ModuleSetHandleT addModuleSet(ModuleSetT Ms,
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+
+ for (auto I = Ms.begin(), E = Ms.end(); I != E; ++I)
+ *I = Transform(std::move(*I));
+
+ return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr),
+ std::move(Resolver));
+ }
+
+ /// @brief Remove the module set associated with the handle H.
+ void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeModuleSet(H); }
+
+ /// @brief Search for the given named symbol.
+ /// @param Name The name of the symbol to search for.
+ /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+ /// @return A handle for the given named symbol, if it exists.
+ JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ return BaseLayer.findSymbol(Name, ExportedSymbolsOnly);
+ }
+
+ /// @brief Get the address of the given symbol in the context of the set of
+ /// modules represented by the handle H. This call is forwarded to the
+ /// base layer's implementation.
+ /// @param H The handle for the module set to search in.
+ /// @param Name The name of the symbol to search for.
+ /// @param ExportedSymbolsOnly If true, search only for exported symbols.
+ /// @return A handle for the given named symbol, if it is found in the
+ /// given module set.
+ JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly);
+ }
+
+ /// @brief Immediately emit and finalize the module set represented by the
+ /// given handle.
+ /// @param H Handle for module set to emit/finalize.
+ void emitAndFinalize(ModuleSetHandleT H) {
+ BaseLayer.emitAndFinalize(H);
+ }
+
+ /// @brief Access the transform functor directly.
+ TransformFtor& getTransform() { return Transform; }
+
+ /// @brief Access the mumate functor directly.
+ const TransformFtor& getTransform() const { return Transform; }
+
+private:
+ BaseLayerT &BaseLayer;
+ TransformFtor Transform;
+};
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H
diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
index 8ce1d4d..7b4f611 100644
--- a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
+++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
@@ -16,6 +16,7 @@
#include "JITSymbol.h"
#include "llvm/ADT/DenseSet.h"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
@@ -37,11 +38,11 @@ public:
/// the compile and update actions for the callback.
class CompileCallbackInfo {
public:
- CompileCallbackInfo(Constant *Addr, CompileFtor &Compile,
+ CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile,
UpdateFtor &Update)
: Addr(Addr), Compile(Compile), Update(Update) {}
- Constant* getAddress() const { return Addr; }
+ TargetAddress getAddress() const { return Addr; }
void setCompileAction(CompileFtor Compile) {
this->Compile = std::move(Compile);
}
@@ -49,7 +50,7 @@ public:
this->Update = std::move(Update);
}
private:
- Constant *Addr;
+ TargetAddress Addr;
CompileFtor &Compile;
UpdateFtor &Update;
};
@@ -94,7 +95,7 @@ public:
}
/// @brief Get/create a compile callback with the given signature.
- virtual CompileCallbackInfo getCompileCallback(FunctionType &FT) = 0;
+ virtual CompileCallbackInfo getCompileCallback(LLVMContext &Context) = 0;
protected:
@@ -125,27 +126,23 @@ public:
/// there is no existing callback trampoline.
/// (Trampolines are allocated in blocks for
/// efficiency.)
- JITCompileCallbackManager(JITLayerT &JIT, LLVMContext &Context,
+ JITCompileCallbackManager(JITLayerT &JIT, RuntimeDyld::MemoryManager &MemMgr,
+ LLVMContext &Context,
TargetAddress ErrorHandlerAddress,
unsigned NumTrampolinesPerBlock)
: JITCompileCallbackManagerBase(ErrorHandlerAddress,
NumTrampolinesPerBlock),
- JIT(JIT) {
+ JIT(JIT), MemMgr(MemMgr) {
emitResolverBlock(Context);
}
/// @brief Get/create a compile callback with the given signature.
- CompileCallbackInfo getCompileCallback(FunctionType &FT) final {
- TargetAddress TrampolineAddr = getAvailableTrampolineAddr(FT.getContext());
+ CompileCallbackInfo getCompileCallback(LLVMContext &Context) final {
+ TargetAddress TrampolineAddr = getAvailableTrampolineAddr(Context);
auto &CallbackHandler =
this->ActiveTrampolines[TrampolineAddr];
- Constant *AddrIntVal =
- ConstantInt::get(Type::getInt64Ty(FT.getContext()), TrampolineAddr);
- Constant *AddrPtrVal =
- ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal,
- PointerType::get(&FT, 0));
- return CompileCallbackInfo(AddrPtrVal, CallbackHandler.Compile,
+ return CompileCallbackInfo(TrampolineAddr, CallbackHandler.Compile,
CallbackHandler.Update);
}
@@ -162,7 +159,9 @@ private:
std::unique_ptr<Module> M(new Module("resolver_block_module",
Context));
TargetT::insertResolverBlock(*M, *this);
- auto H = JIT.addModuleSet(SingletonSet(std::move(M)), nullptr);
+ auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr,
+ static_cast<RuntimeDyld::SymbolResolver*>(
+ nullptr));
JIT.emitAndFinalize(H);
auto ResolverBlockSymbol =
JIT.findSymbolIn(H, TargetT::ResolverBlockName, false);
@@ -187,7 +186,9 @@ private:
TargetT::insertCompileCallbackTrampolines(*M, ResolverBlockAddr,
this->NumTrampolinesPerBlock,
this->ActiveTrampolines.size());
- auto H = JIT.addModuleSet(SingletonSet(std::move(M)), nullptr);
+ auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr,
+ static_cast<RuntimeDyld::SymbolResolver*>(
+ nullptr));
JIT.emitAndFinalize(H);
for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) {
std::string Name = GetLabelName(I);
@@ -198,10 +199,11 @@ private:
}
JITLayerT &JIT;
+ RuntimeDyld::MemoryManager &MemMgr;
TargetAddress ResolverBlockAddr;
};
-/// @brief Get an update functor for updating the value of a named function
+/// @brief Get an update functor that updates the value of a named function
/// pointer.
template <typename JITLayerT>
JITCompileCallbackManagerBase::UpdateFtor
@@ -217,13 +219,26 @@ getLocalFPUpdater(JITLayerT &JIT, typename JITLayerT::ModuleSetHandleT H,
};
}
-GlobalVariable* createImplPointer(Function &F, const Twine &Name,
- Constant *Initializer);
+/// @brief Build a function pointer of FunctionType with the given constant
+/// address.
+///
+/// Usage example: Turn a trampoline address into a function pointer constant
+/// for use in a stub.
+Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr);
+/// @brief Create a function pointer with the given type, name, and initializer
+/// in the given Module.
+GlobalVariable* createImplPointer(PointerType &PT, Module &M,
+ const Twine &Name, Constant *Initializer);
+
+/// @brief Turn a function declaration into a stub function that makes an
+/// indirect call using the given function pointer.
void makeStub(Function &F, GlobalVariable &ImplPointer);
typedef std::map<Module*, DenseSet<const GlobalValue*>> ModulePartitionMap;
+/// @brief Extract subsections of a Module into the given Module according to
+/// the given ModulePartitionMap.
void partition(Module &M, const ModulePartitionMap &PMap);
/// @brief Struct for trivial "complete" partitioning of a module.
@@ -239,6 +254,7 @@ public:
Functions(std::move(S.Functions)) {}
};
+/// @brief Extract every function in M into a separate module.
FullyPartitionedModule fullyPartition(Module &M);
} // End namespace orc.
diff --git a/include/llvm/ExecutionEngine/Orc/JITSymbol.h b/include/llvm/ExecutionEngine/Orc/JITSymbol.h
index 7c3ad56..422a376 100644
--- a/include/llvm/ExecutionEngine/Orc/JITSymbol.h
+++ b/include/llvm/ExecutionEngine/Orc/JITSymbol.h
@@ -27,7 +27,7 @@ typedef uint64_t TargetAddress;
/// @brief Represents a symbol in the JIT.
class JITSymbol : public JITSymbolBase {
-public:
+public:
typedef std::function<TargetAddress()> GetAddressFtor;
diff --git a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
new file mode 100644
index 0000000..faa2365
--- /dev/null
+++ b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h
@@ -0,0 +1,62 @@
+//===-- LambdaResolverMM - Redirect symbol lookup via a functor -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines a RuntimeDyld::SymbolResolver subclass that uses a user-supplied
+// functor for symbol resolution.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H
+#define LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace orc {
+
+template <typename ExternalLookupFtorT, typename DylibLookupFtorT>
+class LambdaResolver : public RuntimeDyld::SymbolResolver {
+public:
+
+ LambdaResolver(ExternalLookupFtorT ExternalLookupFtor,
+ DylibLookupFtorT DylibLookupFtor)
+ : ExternalLookupFtor(ExternalLookupFtor),
+ DylibLookupFtor(DylibLookupFtor) {}
+
+ RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) final {
+ return ExternalLookupFtor(Name);
+ }
+
+ RuntimeDyld::SymbolInfo
+ findSymbolInLogicalDylib(const std::string &Name) final {
+ return DylibLookupFtor(Name);
+ }
+
+private:
+ ExternalLookupFtorT ExternalLookupFtor;
+ DylibLookupFtorT DylibLookupFtor;
+};
+
+template <typename ExternalLookupFtorT,
+ typename DylibLookupFtorT>
+std::unique_ptr<LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT>>
+createLambdaResolver(ExternalLookupFtorT ExternalLookupFtor,
+ DylibLookupFtorT DylibLookupFtor) {
+ typedef LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT> LR;
+ return make_unique<LR>(std::move(ExternalLookupFtor),
+ std::move(DylibLookupFtor));
+}
+
+} // End namespace orc.
+} // End namespace llvm.
+
+#endif // LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H
diff --git a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
index ac5fccf..71c83f7 100644
--- a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h
@@ -15,11 +15,11 @@
#define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
#include "JITSymbol.h"
-#include "LookasideRTDyldMM.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Mangler.h"
#include "llvm/IR/Module.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
#include <list>
@@ -94,10 +94,11 @@ private:
BaseLayer.emitAndFinalize(Handle);
}
- template <typename ModuleSetT>
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
static std::unique_ptr<EmissionDeferredSet>
- create(BaseLayerT &B, ModuleSetT Ms,
- std::unique_ptr<RTDyldMemoryManager> MM);
+ create(BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver);
protected:
virtual const GlobalValue* searchGVs(StringRef Name,
@@ -109,12 +110,15 @@ private:
BaseLayerHandleT Handle;
};
- template <typename ModuleSetT>
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
class EmissionDeferredSetImpl : public EmissionDeferredSet {
public:
EmissionDeferredSetImpl(ModuleSetT Ms,
- std::unique_ptr<RTDyldMemoryManager> MM)
- : Ms(std::move(Ms)), MM(std::move(MM)) {}
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver)
+ : Ms(std::move(Ms)), MemMgr(std::move(MemMgr)),
+ Resolver(std::move(Resolver)) {}
protected:
@@ -145,7 +149,8 @@ private:
// We don't need the mangled names set any more: Once we've emitted this
// to the base layer we'll just look for symbols there.
MangledSymbols.reset();
- return BaseLayer.addModuleSet(std::move(Ms), std::move(MM));
+ return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr),
+ std::move(Resolver));
}
private:
@@ -206,7 +211,8 @@ private:
}
ModuleSetT Ms;
- std::unique_ptr<RTDyldMemoryManager> MM;
+ MemoryManagerPtrT MemMgr;
+ SymbolResolverPtrT Resolver;
mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
};
@@ -223,12 +229,15 @@ public:
LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
/// @brief Add the given set of modules to the lazy emitting layer.
- template <typename ModuleSetT>
+ template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
ModuleSetHandleT addModuleSet(ModuleSetT Ms,
- std::unique_ptr<RTDyldMemoryManager> MM) {
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
return ModuleSetList.insert(
ModuleSetList.end(),
- EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MM)));
+ EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MemMgr),
+ std::move(Resolver)));
}
/// @brief Remove the module set represented by the given handle.
@@ -277,12 +286,16 @@ public:
};
template <typename BaseLayerT>
-template <typename ModuleSetT>
+template <typename ModuleSetT, typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet>
LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create(
- BaseLayerT &B, ModuleSetT Ms, std::unique_ptr<RTDyldMemoryManager> MM) {
- return llvm::make_unique<EmissionDeferredSetImpl<ModuleSetT>>(std::move(Ms),
- std::move(MM));
+ BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+ typedef EmissionDeferredSetImpl<ModuleSetT, MemoryManagerPtrT, SymbolResolverPtrT>
+ EDS;
+ return llvm::make_unique<EDS>(std::move(Ms), std::move(MemMgr),
+ std::move(Resolver));
}
} // End namespace orc.
diff --git a/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h b/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h
deleted file mode 100644
index 4456404..0000000
--- a/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h
+++ /dev/null
@@ -1,92 +0,0 @@
-//===- LookasideRTDyldMM - Redirect symbol lookup via a functor -*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// Defines an adapter for RuntimeDyldMM that allows lookups for external
-// symbols to go via a functor.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H
-#define LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H
-
-#include "llvm/ADT/STLExtras.h"
-#include <memory>
-#include <vector>
-
-namespace llvm {
-namespace orc {
-
-/// @brief Defines an adapter for RuntimeDyldMM that allows lookups for external
-/// symbols to go via a functor, before falling back to the lookup logic
-/// provided by the underlying RuntimeDyldMM instance.
-///
-/// This class is useful for redirecting symbol lookup back to various layers
-/// of a JIT component stack, e.g. to enable lazy module emission.
-///
-template <typename BaseRTDyldMM, typename ExternalLookupFtor,
- typename DylibLookupFtor>
-class LookasideRTDyldMM : public BaseRTDyldMM {
-public:
- /// @brief Create a LookasideRTDyldMM intance.
- LookasideRTDyldMM(ExternalLookupFtor ExternalLookup,
- DylibLookupFtor DylibLookup)
- : ExternalLookup(std::move(ExternalLookup)),
- DylibLookup(std::move(DylibLookup)) {}
-
- /// @brief Look up the given symbol address, first via the functor this
- /// instance was created with, then (if the symbol isn't found)
- /// via the underlying RuntimeDyldMM.
- uint64_t getSymbolAddress(const std::string &Name) override {
- if (uint64_t Addr = ExternalLookup(Name))
- return Addr;
- return BaseRTDyldMM::getSymbolAddress(Name);
- }
-
- uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) override {
- if (uint64_t Addr = DylibLookup(Name))
- return Addr;
- return BaseRTDyldMM::getSymbolAddressInLogicalDylib(Name);
- };
-
- /// @brief Get a reference to the ExternalLookup functor.
- ExternalLookupFtor &getExternalLookup() { return ExternalLookup; }
-
- /// @brief Get a const-reference to the ExternalLookup functor.
- const ExternalLookupFtor &getExternalLookup() const { return ExternalLookup; }
-
- /// @brief Get a reference to the DylibLookup functor.
- DylibLookupFtor &getDylibLookup() { return DylibLookup; }
-
- /// @brief Get a const-reference to the DylibLookup functor.
- const DylibLookupFtor &getDylibLookup() const { return DylibLookup; }
-
-private:
- ExternalLookupFtor ExternalLookup;
- DylibLookupFtor DylibLookup;
-};
-
-/// @brief Create a LookasideRTDyldMM from a base memory manager type, an
-/// external lookup functor, and a dylib lookup functor.
-template <typename BaseRTDyldMM, typename ExternalLookupFtor,
- typename DylibLookupFtor>
-std::unique_ptr<
- LookasideRTDyldMM<BaseRTDyldMM, ExternalLookupFtor, DylibLookupFtor>>
-createLookasideRTDyldMM(ExternalLookupFtor &&ExternalLookup,
- DylibLookupFtor &&DylibLookup) {
- typedef LookasideRTDyldMM<BaseRTDyldMM, ExternalLookupFtor, DylibLookupFtor>
- ThisLookasideMM;
- return llvm::make_unique<ThisLookasideMM>(
- std::forward<ExternalLookupFtor>(ExternalLookup),
- std::forward<DylibLookupFtor>(DylibLookup));
-}
-
-} // End namespace orc.
-} // End namespace llvm.
-
-#endif // LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H
diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
index 9838991..f3094da 100644
--- a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
+++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h
@@ -15,7 +15,7 @@
#define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
#include "JITSymbol.h"
-#include "LookasideRTDyldMM.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include <list>
@@ -38,13 +38,12 @@ protected:
LinkedObjectSet(const LinkedObjectSet&) = delete;
void operator=(const LinkedObjectSet&) = delete;
public:
- LinkedObjectSet(std::unique_ptr<RTDyldMemoryManager> MM)
- : MM(std::move(MM)), RTDyld(llvm::make_unique<RuntimeDyld>(&*this->MM)),
+ LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr,
+ RuntimeDyld::SymbolResolver &Resolver)
+ : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)),
State(Raw) {}
- // MSVC 2012 cannot infer a move constructor, so write it out longhand.
- LinkedObjectSet(LinkedObjectSet &&O)
- : MM(std::move(O.MM)), RTDyld(std::move(O.RTDyld)), State(O.State) {}
+ virtual ~LinkedObjectSet() {}
std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
addObject(const object::ObjectFile &Obj) {
@@ -57,14 +56,7 @@ protected:
bool NeedsFinalization() const { return (State == Raw); }
- void Finalize() {
- State = Finalizing;
- RTDyld->resolveRelocations();
- RTDyld->registerEHFrames();
- MM->finalizeMemory();
- OwnedBuffers.clear();
- State = Finalized;
- }
+ virtual void Finalize() = 0;
void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) {
assert((State != Finalized) &&
@@ -76,8 +68,7 @@ protected:
OwnedBuffers.push_back(std::move(B));
}
- private:
- std::unique_ptr<RTDyldMemoryManager> MM;
+ protected:
std::unique_ptr<RuntimeDyld> RTDyld;
enum { Raw, Finalizing, Finalized } State;
@@ -87,7 +78,7 @@ protected:
std::vector<std::unique_ptr<MemoryBuffer>> OwnedBuffers;
};
- typedef std::list<LinkedObjectSet> LinkedObjectSetListT;
+ typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;
public:
/// @brief Handle to a set of loaded objects.
@@ -99,7 +90,7 @@ public:
template <typename OwningMBSet>
void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) {
for (auto &MB : MBs)
- H->takeOwnershipOfBuffer(std::move(MB));
+ (*H)->takeOwnershipOfBuffer(std::move(MB));
}
};
@@ -120,6 +111,37 @@ public:
/// symbols.
template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
class ObjectLinkingLayer : public ObjectLinkingLayerBase {
+private:
+
+ template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
+ class ConcreteLinkedObjectSet : public LinkedObjectSet {
+ public:
+ ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver)
+ : LinkedObjectSet(*MemMgr, *Resolver), MemMgr(std::move(MemMgr)),
+ Resolver(std::move(Resolver)) { }
+
+ void Finalize() override {
+ State = Finalizing;
+ RTDyld->resolveRelocations();
+ RTDyld->registerEHFrames();
+ MemMgr->finalizeMemory();
+ OwnedBuffers.clear();
+ State = Finalized;
+ }
+
+ private:
+ MemoryManagerPtrT MemMgr;
+ SymbolResolverPtrT Resolver;
+ };
+
+ template <typename MemoryManagerPtrT, typename SymbolResolverPtrT>
+ std::unique_ptr<LinkedObjectSet>
+ createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver) {
+ typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS;
+ return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver));
+ }
+
public:
/// @brief LoadedObjectInfo list. Contains a list of owning pointers to
@@ -127,21 +149,16 @@ public:
typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
LoadedObjInfoList;
- /// @brief Functor to create RTDyldMemoryManager instances.
- typedef std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateRTDyldMMFtor;
-
/// @brief Functor for receiving finalization notifications.
typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
/// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded,
- /// NotifyFinalized and CreateMemoryManager functors.
+ /// and NotifyFinalized functors.
ObjectLinkingLayer(
- CreateRTDyldMMFtor CreateMemoryManager = CreateRTDyldMMFtor(),
NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
: NotifyLoaded(std::move(NotifyLoaded)),
- NotifyFinalized(std::move(NotifyFinalized)),
- CreateMemoryManager(std::move(CreateMemoryManager)) {}
+ NotifyFinalized(std::move(NotifyFinalized)) {}
/// @brief Add a set of objects (or archives) that will be treated as a unit
/// for the purposes of symbol lookup and memory management.
@@ -154,19 +171,18 @@ public:
/// This version of this method allows the client to pass in an
/// RTDyldMemoryManager instance that will be used to allocate memory and look
/// up external symbol addresses for the given objects.
- template <typename ObjSetT>
+ template <typename ObjSetT,
+ typename MemoryManagerPtrT,
+ typename SymbolResolverPtrT>
ObjSetHandleT addObjectSet(const ObjSetT &Objects,
- std::unique_ptr<RTDyldMemoryManager> MM) {
-
- if (!MM) {
- assert(CreateMemoryManager &&
- "No memory manager or memory manager creator provided.");
- MM = CreateMemoryManager();
- }
-
- ObjSetHandleT Handle = LinkedObjSetList.insert(
- LinkedObjSetList.end(), LinkedObjectSet(std::move(MM)));
- LinkedObjectSet &LOS = *Handle;
+ MemoryManagerPtrT MemMgr,
+ SymbolResolverPtrT Resolver) {
+ ObjSetHandleT Handle =
+ LinkedObjSetList.insert(
+ LinkedObjSetList.end(),
+ createLinkedObjectSet(std::move(MemMgr), std::move(Resolver)));
+
+ LinkedObjectSet &LOS = **Handle;
LoadedObjInfoList LoadedObjInfos;
for (auto &Obj : Objects)
@@ -212,11 +228,11 @@ public:
/// given object set.
JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
bool ExportedSymbolsOnly) {
- if (auto Sym = H->getSymbol(Name)) {
+ if (auto Sym = (*H)->getSymbol(Name)) {
if (Sym.isExported() || !ExportedSymbolsOnly) {
auto Addr = Sym.getAddress();
auto Flags = Sym.getFlags();
- if (!H->NeedsFinalization()) {
+ if (!(*H)->NeedsFinalization()) {
// If this instance has already been finalized then we can just return
// the address.
return JITSymbol(Addr, Flags);
@@ -225,10 +241,10 @@ public:
// it. The functor still needs to double-check whether finalization is
// required, in case someone else finalizes this set before the
// functor is called.
- auto GetAddress =
+ auto GetAddress =
[this, Addr, H]() {
- if (H->NeedsFinalization()) {
- H->Finalize();
+ if ((*H)->NeedsFinalization()) {
+ (*H)->Finalize();
if (NotifyFinalized)
NotifyFinalized(H);
}
@@ -244,14 +260,14 @@ public:
/// @brief Map section addresses for the objects associated with the handle H.
void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
TargetAddress TargetAddr) {
- H->mapSectionAddress(LocalAddress, TargetAddr);
+ (*H)->mapSectionAddress(LocalAddress, TargetAddr);
}
/// @brief Immediately emit and finalize the object set represented by the
/// given handle.
/// @param H Handle for object set to emit/finalize.
void emitAndFinalize(ObjSetHandleT H) {
- H->Finalize();
+ (*H)->Finalize();
if (NotifyFinalized)
NotifyFinalized(H);
}
@@ -260,7 +276,6 @@ private:
LinkedObjectSetListT LinkedObjSetList;
NotifyLoadedFtor NotifyLoaded;
NotifyFinalizedFtor NotifyFinalized;
- CreateRTDyldMMFtor CreateMemoryManager;
};
} // End namespace orc.
diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
index 792a499..207bad0 100644
--- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
+++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h
@@ -14,6 +14,7 @@
#ifndef LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H
#define LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H
+#include "RuntimeDyld.h"
#include "llvm-c/ExecutionEngine.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/CBindingWrapping.h"
@@ -27,89 +28,91 @@ class ExecutionEngine;
class ObjectFile;
}
+class MCJITMemoryManager : public RuntimeDyld::MemoryManager {
+public:
+ /// This method is called after an object has been loaded into memory but
+ /// before relocations are applied to the loaded sections. The object load
+ /// may have been initiated by MCJIT to resolve an external symbol for another
+ /// object that is being finalized. In that case, the object about which
+ /// the memory manager is being notified will be finalized immediately after
+ /// the memory manager returns from this call.
+ ///
+ /// Memory managers which are preparing code for execution in an external
+ /// address space can use this call to remap the section addresses for the
+ /// newly loaded object.
+ virtual void notifyObjectLoaded(ExecutionEngine *EE,
+ const object::ObjectFile &) {}
+};
+
// RuntimeDyld clients often want to handle the memory management of
// what gets placed where. For JIT clients, this is the subset of
// JITMemoryManager required for dynamic loading of binaries.
//
// FIXME: As the RuntimeDyld fills out, additional routines will be needed
// for the varying types of objects to be allocated.
-class RTDyldMemoryManager {
+class RTDyldMemoryManager : public MCJITMemoryManager,
+ public RuntimeDyld::SymbolResolver {
RTDyldMemoryManager(const RTDyldMemoryManager&) = delete;
void operator=(const RTDyldMemoryManager&) = delete;
public:
RTDyldMemoryManager() {}
- virtual ~RTDyldMemoryManager();
-
- /// Allocate a memory block of (at least) the given size suitable for
- /// executable code. The SectionID is a unique identifier assigned by the JIT
- /// engine, and optionally recorded by the memory manager to access a loaded
- /// section.
- virtual uint8_t *allocateCodeSection(
- uintptr_t Size, unsigned Alignment, unsigned SectionID,
- StringRef SectionName) = 0;
-
- /// Allocate a memory block of (at least) the given size suitable for data.
- /// The SectionID is a unique identifier assigned by the JIT engine, and
- /// optionally recorded by the memory manager to access a loaded section.
- virtual uint8_t *allocateDataSection(
- uintptr_t Size, unsigned Alignment, unsigned SectionID,
- StringRef SectionName, bool IsReadOnly) = 0;
-
- /// Inform the memory manager about the total amount of memory required to
- /// allocate all sections to be loaded:
- /// \p CodeSize - the total size of all code sections
- /// \p DataSizeRO - the total size of all read-only data sections
- /// \p DataSizeRW - the total size of all read-write data sections
- ///
- /// Note that by default the callback is disabled. To enable it
- /// redefine the method needsToReserveAllocationSpace to return true.
- virtual void reserveAllocationSpace(
- uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) { }
-
- /// Override to return true to enable the reserveAllocationSpace callback.
- virtual bool needsToReserveAllocationSpace() { return false; }
-
- /// Register the EH frames with the runtime so that c++ exceptions work.
- ///
- /// \p Addr parameter provides the local address of the EH frame section
- /// data, while \p LoadAddr provides the address of the data in the target
- /// address space. If the section has not been remapped (which will usually
- /// be the case for local execution) these two values will be the same.
- virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size);
+ ~RTDyldMemoryManager() override;
- virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size);
+ void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
+ void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override;
/// This method returns the address of the specified function or variable in
/// the current process.
static uint64_t getSymbolAddressInProcess(const std::string &Name);
+ /// Legacy symbol lookup - DEPRECATED! Please override findSymbol instead.
+ ///
/// This method returns the address of the specified function or variable.
/// It is used to resolve symbols during module linking.
virtual uint64_t getSymbolAddress(const std::string &Name) {
return getSymbolAddressInProcess(Name);
}
- /// This method returns the address of the specified symbol if it exists
- /// within the logical dynamic library represented by this
- /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this
- /// interface should return addresses for hidden symbols.
+ /// This method returns a RuntimeDyld::SymbolInfo for the specified function
+ /// or variable. It is used to resolve symbols during module linking.
+ ///
+ /// By default this falls back on the legacy lookup method:
+ /// 'getSymbolAddress'. The address returned by getSymbolAddress is treated as
+ /// a strong, exported symbol, consistent with historical treatment by
+ /// RuntimeDyld.
///
- /// This is of particular importance for the Orc JIT APIs, which support lazy
- /// compilation by breaking up modules: Each of those broken out modules
- /// must be able to resolve hidden symbols provided by the others. Clients
- /// writing memory managers for MCJIT can usually ignore this method.
+ /// Clients writing custom RTDyldMemoryManagers are encouraged to override
+ /// this method and return a SymbolInfo with the flags set correctly. This is
+ /// necessary for RuntimeDyld to correctly handle weak and non-exported symbols.
+ RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override {
+ return RuntimeDyld::SymbolInfo(getSymbolAddress(Name),
+ JITSymbolFlags::Exported);
+ }
+
+ /// Legacy symbol lookup -- DEPRECATED! Please override
+ /// findSymbolInLogicalDylib instead.
///
- /// This method will be queried by RuntimeDyld when checking for previous
- /// definitions of common symbols. It will *not* be queried by default when
- /// resolving external symbols (this minimises the link-time overhead for
- /// MCJIT clients who don't care about Orc features). If you are writing a
- /// RTDyldMemoryManager for Orc and want "external" symbol resolution to
- /// search the logical dylib, you should override your getSymbolAddress
- /// method call this method directly.
+ /// Default to treating all modules as separate.
virtual uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) {
return 0;
}
+ /// Default to treating all modules as separate.
+ ///
+ /// By default this falls back on the legacy lookup method:
+ /// 'getSymbolAddressInLogicalDylib'. The address returned by
+ /// getSymbolAddressInLogicalDylib is treated as a strong, exported symbol,
+ /// consistent with historical treatment by RuntimeDyld.
+ ///
+ /// Clients writing custom RTDyldMemoryManagers are encouraged to override
+ /// this method and return a SymbolInfo with the flags set correctly. This is
+ /// necessary for RuntimeDyld to correctly handle weak and non-exported symbols.
+ RuntimeDyld::SymbolInfo
+ findSymbolInLogicalDylib(const std::string &Name) override {
+ return RuntimeDyld::SymbolInfo(getSymbolAddressInLogicalDylib(Name),
+ JITSymbolFlags::Exported);
+ }
+
/// This method returns the address of the specified function. As such it is
/// only useful for resolving library symbols, not code generated symbols.
///
@@ -121,30 +124,6 @@ public:
/// MCJIT or RuntimeDyld. Use getSymbolAddress instead.
virtual void *getPointerToNamedFunction(const std::string &Name,
bool AbortOnFailure = true);
-
- /// This method is called after an object has been loaded into memory but
- /// before relocations are applied to the loaded sections. The object load
- /// may have been initiated by MCJIT to resolve an external symbol for another
- /// object that is being finalized. In that case, the object about which
- /// the memory manager is being notified will be finalized immediately after
- /// the memory manager returns from this call.
- ///
- /// Memory managers which are preparing code for execution in an external
- /// address space can use this call to remap the section addresses for the
- /// newly loaded object.
- virtual void notifyObjectLoaded(ExecutionEngine *EE,
- const object::ObjectFile &) {}
-
- /// This method is called when object loading is complete and section page
- /// permissions can be applied. It is up to the memory manager implementation
- /// to decide whether or not to act on this method. The memory manager will
- /// typically allocate all sections as read-write and then apply specific
- /// permissions when this method is called. Code sections cannot be executed
- /// until this function has been called. In addition, any cache coherency
- /// operations needed to reliably use the memory are also performed.
- ///
- /// Returns true if an error occurred, false otherwise.
- virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0;
};
// Create wrappers for C Binding types (see CBindingWrapping.h).
@@ -153,4 +132,5 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS(
} // namespace llvm
+
#endif
diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h
index fe0ccda..5723f05 100644
--- a/include/llvm/ExecutionEngine/RuntimeDyld.h
+++ b/include/llvm/ExecutionEngine/RuntimeDyld.h
@@ -16,7 +16,6 @@
#include "JITSymbolFlags.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/Support/Memory.h"
#include <memory>
@@ -29,19 +28,13 @@ namespace object {
class RuntimeDyldImpl;
class RuntimeDyldCheckerImpl;
-
+
class RuntimeDyld {
friend class RuntimeDyldCheckerImpl;
RuntimeDyld(const RuntimeDyld &) = delete;
void operator=(const RuntimeDyld &) = delete;
- // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public
- // interface.
- std::unique_ptr<RuntimeDyldImpl> Dyld;
- RTDyldMemoryManager *MM;
- bool ProcessAllSections;
- RuntimeDyldCheckerImpl *Checker;
protected:
// Change the address associated with a section when resolving relocations.
// Any relocations already associated with the symbol will be re-resolved.
@@ -82,7 +75,101 @@ public:
unsigned BeginIdx, EndIdx;
};
- RuntimeDyld(RTDyldMemoryManager *);
+ /// \brief Memory Management.
+ class MemoryManager {
+ public:
+ virtual ~MemoryManager() {};
+
+ /// Allocate a memory block of (at least) the given size suitable for
+ /// executable code. The SectionID is a unique identifier assigned by the
+ /// RuntimeDyld instance, and optionally recorded by the memory manager to
+ /// access a loaded section.
+ virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ StringRef SectionName) = 0;
+
+ /// Allocate a memory block of (at least) the given size suitable for data.
+ /// The SectionID is a unique identifier assigned by the JIT engine, and
+ /// optionally recorded by the memory manager to access a loaded section.
+ virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+ unsigned SectionID,
+ StringRef SectionName,
+ bool IsReadOnly) = 0;
+
+ /// Inform the memory manager about the total amount of memory required to
+ /// allocate all sections to be loaded:
+ /// \p CodeSize - the total size of all code sections
+ /// \p DataSizeRO - the total size of all read-only data sections
+ /// \p DataSizeRW - the total size of all read-write data sections
+ ///
+ /// Note that by default the callback is disabled. To enable it
+ /// redefine the method needsToReserveAllocationSpace to return true.
+ virtual void reserveAllocationSpace(uintptr_t CodeSize,
+ uintptr_t DataSizeRO,
+ uintptr_t DataSizeRW) {}
+
+ /// Override to return true to enable the reserveAllocationSpace callback.
+ virtual bool needsToReserveAllocationSpace() { return false; }
+
+ /// Register the EH frames with the runtime so that c++ exceptions work.
+ ///
+ /// \p Addr parameter provides the local address of the EH frame section
+ /// data, while \p LoadAddr provides the address of the data in the target
+ /// address space. If the section has not been remapped (which will usually
+ /// be the case for local execution) these two values will be the same.
+ virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
+ size_t Size) = 0;
+ virtual void deregisterEHFrames(uint8_t *addr, uint64_t LoadAddr,
+ size_t Size) = 0;
+
+ /// This method is called when object loading is complete and section page
+ /// permissions can be applied. It is up to the memory manager implementation
+ /// to decide whether or not to act on this method. The memory manager will
+ /// typically allocate all sections as read-write and then apply specific
+ /// permissions when this method is called. Code sections cannot be executed
+ /// until this function has been called. In addition, any cache coherency
+ /// operations needed to reliably use the memory are also performed.
+ ///
+ /// Returns true if an error occurred, false otherwise.
+ virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0;
+
+ private:
+ virtual void anchor();
+ };
+
+ /// \brief Symbol resolution.
+ class SymbolResolver {
+ public:
+ virtual ~SymbolResolver() {};
+
+ /// This method returns the address of the specified function or variable.
+ /// It is used to resolve symbols during module linking.
+ virtual SymbolInfo findSymbol(const std::string &Name) = 0;
+
+ /// This method returns the address of the specified symbol if it exists
+ /// within the logical dynamic library represented by this
+ /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this
+ /// interface should return addresses for hidden symbols.
+ ///
+ /// This is of particular importance for the Orc JIT APIs, which support lazy
+ /// compilation by breaking up modules: Each of those broken out modules
+ /// must be able to resolve hidden symbols provided by the others. Clients
+ /// writing memory managers for MCJIT can usually ignore this method.
+ ///
+ /// This method will be queried by RuntimeDyld when checking for previous
+ /// definitions of common symbols. It will *not* be queried by default when
+ /// resolving external symbols (this minimises the link-time overhead for
+ /// MCJIT clients who don't care about Orc features). If you are writing a
+ /// RTDyldMemoryManager for Orc and want "external" symbol resolution to
+ /// search the logical dylib, you should override your getSymbolAddress
+ /// method call this method directly.
+ virtual SymbolInfo findSymbolInLogicalDylib(const std::string &Name) = 0;
+ private:
+ virtual void anchor();
+ };
+
+ /// \brief Construct a RuntimeDyld instance.
+ RuntimeDyld(MemoryManager &MemMgr, SymbolResolver &Resolver);
~RuntimeDyld();
/// Add the referenced object file to the list of objects to be loaded and
@@ -131,6 +218,15 @@ public:
assert(!Dyld && "setProcessAllSections must be called before loadObject.");
this->ProcessAllSections = ProcessAllSections;
}
+
+private:
+ // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public
+ // interface.
+ std::unique_ptr<RuntimeDyldImpl> Dyld;
+ MemoryManager &MemMgr;
+ SymbolResolver &Resolver;
+ bool ProcessAllSections;
+ RuntimeDyldCheckerImpl *Checker;
};
} // end namespace llvm
diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h
index b825aff..0b0dcb0 100644
--- a/include/llvm/ExecutionEngine/SectionMemoryManager.h
+++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h
@@ -16,7 +16,7 @@
#define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ExecutionEngine/RuntimeDyld.h"
+#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/Memory.h"
@@ -40,7 +40,7 @@ class SectionMemoryManager : public RTDyldMemoryManager {
public:
SectionMemoryManager() { }
- virtual ~SectionMemoryManager();
+ ~SectionMemoryManager() override;
/// \brief Allocates a memory block of (at least) the given size suitable for
/// executable code.