[Orc] Expose the compile callback API through the C bindings.

llvm-svn: 251683
This commit is contained in:
Lang Hames 2015-10-30 03:20:21 +00:00
parent 9ef327c962
commit fd6e8dc369
5 changed files with 154 additions and 36 deletions

View File

@ -35,6 +35,8 @@ typedef uint32_t LLVMOrcModuleHandle;
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.
@ -61,6 +63,28 @@ void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledSymbol,
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.
*/

View File

@ -12,9 +12,6 @@
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));
@ -45,6 +42,28 @@ void LLVMOrcDisposeMangledSymbol(char *MangledName) {
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,

View File

@ -17,17 +17,18 @@
#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;
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(OrcCBindingsStack, LLVMOrcJITStackRef)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
class OrcCBindingsStack {
private:
public:
typedef orc::TargetAddress (*CExternalSymbolResolverFn)(const char *Name,
void *Ctx);
typedef orc::JITCompileCallbackManagerBase CompileCallbackMgr;
typedef orc::ObjectLinkingLayer<> ObjLayerT;
typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT;
@ -91,13 +92,14 @@ public:
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() {
@ -122,8 +124,27 @@ public:
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) {
@ -157,7 +178,7 @@ public:
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.
@ -194,7 +215,7 @@ public:
}
ModuleHandleT addIRModuleEager(Module* M,
CExternalSymbolResolverFn ExternalResolver,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
return addIRModule(CompileLayer, std::move(M),
llvm::make_unique<SectionMemoryManager>(),
@ -202,7 +223,7 @@ public:
}
ModuleHandleT addIRModuleLazy(Module* M,
CExternalSymbolResolverFn ExternalResolver,
LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
return addIRModule(CODLayer, std::move(M), nullptr,
std::move(ExternalResolver), ExternalResolverCtx);
@ -215,6 +236,8 @@ public:
}
orc::JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
if (auto Sym = IndirectStubsMgr->findStub(Name, ExportedSymbolsOnly))
return Sym;
return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
}
@ -241,6 +264,7 @@ private:
return NewHandle;
}
LLVMContext &Context;
DataLayout DL;
SectionMemoryManager CCMgrMemMgr;
@ -249,6 +273,8 @@ private:
std::unique_ptr<CompileCallbackMgr> CCMgr;
CODLayerT CODLayer;
std::unique_ptr<orc::IndirectStubsManagerBase> IndirectStubsMgr;
std::vector<std::unique_ptr<GenericHandle>> GenericHandles;
std::vector<unsigned> FreeHandleIndexes;

View File

@ -51,21 +51,41 @@ protected:
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 =
@ -82,17 +102,16 @@ TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) {
}
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");
@ -106,4 +125,37 @@ TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) {
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);
}
}

View File

@ -38,23 +38,20 @@ public:
InitializeNativeTargetAsmPrinter();
NativeTargetInitialized = true;
}
// Try to select a TargetMachine for the host.
TM.reset(EngineBuilder().selectTarget());
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;
}
};
// 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;
return TM;
}
protected:
std::unique_ptr<TargetMachine> TM;
private:
static bool NativeTargetInitialized;
};