typedef uint64_t LLVMOrcTargetAddress;
typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name,
void *LookupCtx);
+typedef uint64_t (*LLVMOrcLazyCompileCallbackFn)(LLVMOrcJITStackRef JITStack,
+ void *CallbackCtx);
/**
* Create an ORC JIT stack.
void LLVMOrcDisposeMangledSymbol(char *MangledSymbol);
+/**
+ * Create a lazy compile callback.
+ */
+LLVMOrcTargetAddress
+LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack,
+ LLVMOrcLazyCompileCallbackFn Callback,
+ void *CallbackCtx);
+
+/**
+ * Create a named indirect call stub.
+ */
+void LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
+ const char *StubName,
+ LLVMOrcTargetAddress InitAddr);
+
+/**
+ * Set the pointer for the given indirect stub.
+ */
+void LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
+ const char *StubName,
+ LLVMOrcTargetAddress NewAddr);
+
/**
* Add module to be eagerly compiled.
*/
using namespace llvm;
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
-
LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM,
LLVMContextRef Context) {
TargetMachine *TM2(unwrap(TM));
delete[] MangledName;
}
+LLVMOrcTargetAddress
+LLVMOrcCreateLazyCompileCallback(LLVMOrcJITStackRef JITStack,
+ LLVMOrcLazyCompileCallbackFn Callback,
+ void *CallbackCtx) {
+ OrcCBindingsStack &J = *unwrap(JITStack);
+ return J.createLazyCompileCallback(Callback, CallbackCtx);
+}
+
+void LLVMOrcCreateIndirectStub(LLVMOrcJITStackRef JITStack,
+ const char *StubName,
+ LLVMOrcTargetAddress InitAddr) {
+ OrcCBindingsStack &J = *unwrap(JITStack);
+ J.createIndirectStub(StubName, InitAddr);
+}
+
+void LLVMOrcSetIndirectStubPointer(LLVMOrcJITStackRef JITStack,
+ const char *StubName,
+ LLVMOrcTargetAddress NewAddr) {
+ OrcCBindingsStack &J = *unwrap(JITStack);
+ J.setIndirectStubPointer(StubName, NewAddr);
+}
+
LLVMOrcModuleHandle
LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, LLVMModuleRef Mod,
LLVMOrcSymbolResolverFn SymbolResolver,
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm-c/OrcBindings.h"
namespace llvm {
-class OrcCBindingsStack {
-private:
+class OrcCBindingsStack;
-public:
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
- typedef orc::TargetAddress (*CExternalSymbolResolverFn)(const char *Name,
- void *Ctx);
+class OrcCBindingsStack {
+public:
typedef orc::JITCompileCallbackManagerBase CompileCallbackMgr;
typedef orc::ObjectLinkingLayer<> ObjLayerT;
OrcCBindingsStack(TargetMachine &TM, LLVMContext &Context,
CallbackManagerBuilder &BuildCallbackMgr,
IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
- : DL(TM.createDataLayout()),
+ : Context(Context), DL(TM.createDataLayout()),
ObjectLayer(),
CompileLayer(ObjectLayer, orc::SimpleCompiler(TM)),
CCMgr(BuildCallbackMgr(CompileLayer, CCMgrMemMgr, Context)),
CODLayer(CompileLayer,
[](Function &F) { std::set<Function*> S; S.insert(&F); return S; },
*CCMgr, std::move(IndirectStubsMgrBuilder), false),
+ IndirectStubsMgr(IndirectStubsMgrBuilder()),
CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {}
~OrcCBindingsStack() {
return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
}
+ orc::TargetAddress
+ createLazyCompileCallback(LLVMOrcLazyCompileCallbackFn Callback,
+ void *CallbackCtx) {
+ auto CCInfo = CCMgr->getCompileCallback(Context);
+ CCInfo.setCompileAction(
+ [=]() -> orc::TargetAddress {
+ return Callback(wrap(this), CallbackCtx);
+ });
+ return CCInfo.getAddress();
+ }
+
+ void createIndirectStub(StringRef StubName, orc::TargetAddress Addr) {
+ IndirectStubsMgr->createStub(StubName, Addr, JITSymbolFlags::Exported);
+ }
+
+ void setIndirectStubPointer(StringRef Name, orc::TargetAddress Addr) {
+ IndirectStubsMgr->updatePointer(Name, Addr);
+ }
+
std::shared_ptr<RuntimeDyld::SymbolResolver>
- createResolver(CExternalSymbolResolverFn ExternalResolver,
+ createResolver(LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
auto Resolver = orc::createLambdaResolver(
[this, ExternalResolver, ExternalResolverCtx](const std::string &Name) {
ModuleHandleT addIRModule(LayerT &Layer,
Module *M,
std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
- CExternalSymbolResolverFn ExternalResolver,
+ LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
// Attach a data-layout if one isn't already present.
}
ModuleHandleT addIRModuleEager(Module* M,
- CExternalSymbolResolverFn ExternalResolver,
+ LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
return addIRModule(CompileLayer, std::move(M),
llvm::make_unique<SectionMemoryManager>(),
}
ModuleHandleT addIRModuleLazy(Module* M,
- CExternalSymbolResolverFn ExternalResolver,
+ LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
return addIRModule(CODLayer, std::move(M), nullptr,
std::move(ExternalResolver), ExternalResolverCtx);
}
orc::JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
+ return Sym;
return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
}
return NewHandle;
}
+ LLVMContext &Context;
DataLayout DL;
SectionMemoryManager CCMgrMemMgr;
std::unique_ptr<CompileCallbackMgr> CCMgr;
CODLayerT CODLayer;
+ std::unique_ptr<orc::IndirectStubsManagerBase> IndirectStubsMgr;
+
std::vector<std::unique_ptr<GenericHandle>> GenericHandles;
std::vector<unsigned> FreeHandleIndexes;
return 0;
}
+ struct CompileContext {
+ CompileContext() : Compiled(false) { }
+
+ OrcCAPIExecutionTest* APIExecTest;
+ std::unique_ptr<Module> M;
+ LLVMOrcModuleHandle H;
+ bool Compiled;
+ };
+
+ static LLVMOrcTargetAddress myCompileCallback(LLVMOrcJITStackRef JITStack,
+ void *Ctx) {
+ CompileContext *CCtx = static_cast<CompileContext*>(Ctx);
+ auto *ET = CCtx->APIExecTest;
+ CCtx->M = ET->createTestModule(ET->TM->getTargetTriple());
+ CCtx->H = LLVMOrcAddEagerlyCompiledIR(JITStack, wrap(CCtx->M.get()),
+ myResolver, 0);
+ CCtx->Compiled = true;
+ LLVMOrcTargetAddress MainAddr = LLVMOrcGetSymbolAddress(JITStack, "main");
+ LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr);
+ return MainAddr;
+ }
+
};
char *OrcCAPIExecutionTest::testFuncName = 0;
TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) {
- auto TM = getHostTargetMachineIfSupported();
-
if (!TM)
return;
- std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
-
LLVMOrcJITStackRef JIT =
LLVMOrcCreateInstance(wrap(TM.get()), LLVMGetGlobalContext());
+ std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
+
LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
LLVMOrcModuleHandle H =
}
TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) {
- auto TM = getHostTargetMachineIfSupported();
-
if (!TM)
return;
- std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
-
LLVMOrcJITStackRef JIT =
LLVMOrcCreateInstance(wrap(TM.get()), LLVMGetGlobalContext());
+ std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
+
LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
+
LLVMOrcModuleHandle H =
LLVMOrcAddLazilyCompiledIR(JIT, wrap(M.get()), myResolver, 0);
MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main");
LLVMOrcDisposeInstance(JIT);
}
+TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) {
+ if (!TM)
+ return;
+
+ LLVMOrcJITStackRef JIT =
+ LLVMOrcCreateInstance(wrap(TM.get()), LLVMGetGlobalContext());
+
+ LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
+
+ CompileContext C;
+ C.APIExecTest = this;
+ LLVMOrcCreateIndirectStub(JIT, "foo",
+ LLVMOrcCreateLazyCompileCallback(JIT,
+ myCompileCallback,
+ &C));
+ MainFnTy FooFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "foo");
+ int Result = FooFn();
+ EXPECT_TRUE(C.Compiled)
+ << "Function wasn't lazily compiled";
+ EXPECT_EQ(Result, 42)
+ << "Direct-callback JIT'd code did not return expected result";
+
+ C.Compiled = false;
+ FooFn();
+ EXPECT_FALSE(C.Compiled)
+ << "Direct-callback JIT'd code was JIT'd twice";
+
+ LLVMOrcRemoveModule(JIT, C.H);
+
+ LLVMOrcDisposeMangledSymbol(testFuncName);
+ LLVMOrcDisposeInstance(JIT);
+}
+
}
InitializeNativeTargetAsmPrinter();
NativeTargetInitialized = true;
}
- };
-
- // Get a target machine for the host if it supports JIT execution.
- std::unique_ptr<TargetMachine> getHostTargetMachineIfSupported() {
- std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget());
-
- if (!TM)
- return nullptr;
-
- const Triple& TT = TM->getTargetTriple();
- if (TT.getArch() != Triple::x86_64 || !TT.isOSDarwin())
- return nullptr;
+ // Try to select a TargetMachine for the host.
+ TM.reset(EngineBuilder().selectTarget());
- return TM;
- }
+ if (TM) {
+ // If we found a TargetMachine, check that it's one that Orc supports.
+ const Triple& TT = TM->getTargetTriple();
+ if (TT.getArch() != Triple::x86_64 || !TT.isOSDarwin())
+ TM = nullptr;
+ }
+ };
+protected:
+ std::unique_ptr<TargetMachine> TM;
private:
static bool NativeTargetInitialized;
};