[Orc] Expose the compile callback API through the C bindings.
authorLang Hames <lhames@gmail.com>
Fri, 30 Oct 2015 03:20:21 +0000 (03:20 +0000)
committerLang Hames <lhames@gmail.com>
Fri, 30 Oct 2015 03:20:21 +0000 (03:20 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251683 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm-c/OrcBindings.h
lib/ExecutionEngine/Orc/OrcCBindings.cpp
lib/ExecutionEngine/Orc/OrcCBindingsStack.h
unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
unittests/ExecutionEngine/Orc/OrcTestCommon.h

index 6b7284a..78a7bc1 100644 (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.
  */
index 055636f..d3effee 100644 (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,
index dbedf00..6188b29 100644 (file)
 #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;
@@ -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;
 
index bddb6a7..095d425 100644 (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);
+}
+
 }
index bfdaced..15d9f54 100644 (file)
@@ -38,23 +38,20 @@ public:
       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;
 };