summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2015-10-28 00:28:26 +0000
committerLang Hames <lhames@gmail.com>2015-10-28 00:28:26 +0000
commit5fc6406e3924021b53e0b5f246a5cb604c1c3624 (patch)
treef385f29316a704f8a73d63d873407f6ce209418d
parent727f95c8fc22e8356fcfa1582c30bc4679f9a33d (diff)
[Orc] Add experimental C bindings for Orc.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@251472 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm-c/OrcBindings.h111
-rw-r--r--lib/ExecutionEngine/Orc/CMakeLists.txt2
-rw-r--r--lib/ExecutionEngine/Orc/OrcCBindings.cpp80
-rw-r--r--lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp47
-rw-r--r--lib/ExecutionEngine/Orc/OrcCBindingsStack.h268
-rw-r--r--unittests/ExecutionEngine/Orc/CMakeLists.txt5
-rw-r--r--unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp2
-rw-r--r--unittests/ExecutionEngine/Orc/OrcCAPITest.cpp109
-rw-r--r--unittests/ExecutionEngine/Orc/OrcTestCommon.cpp2
-rw-r--r--unittests/ExecutionEngine/Orc/OrcTestCommon.h35
10 files changed, 658 insertions, 3 deletions
diff --git a/include/llvm-c/OrcBindings.h b/include/llvm-c/OrcBindings.h
new file mode 100644
index 00000000000..6b7284adb31
--- /dev/null
+++ b/include/llvm-c/OrcBindings.h
@@ -0,0 +1,111 @@
+/*===----------- llvm-c/OrcBindings.h - Orc Lib C Iface ---------*- C++ -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* This header declares the C interface to libLLVMOrcJIT.a, which implements *|
+|* JIT compilation of LLVM IR. *|
+|* *|
+|* Many exotic languages can interoperate with C code but have a harder time *|
+|* with C++ due to name mangling. So in addition to C, this interface enables *|
+|* tools written in such languages. *|
+|* *|
+|* Note: This interface is experimental. It is *NOT* stable, and may be *|
+|* changed without warning. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+
+#ifndef LLVM_C_ORCBINDINGS_H
+#define LLVM_C_ORCBINDINGS_H
+
+#include "llvm-c/Object.h"
+#include "llvm-c/Support.h"
+#include "llvm-c/TargetMachine.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct LLVMOrcOpaqueJITStack *LLVMOrcJITStackRef;
+typedef uint32_t LLVMOrcModuleHandle;
+typedef uint64_t LLVMOrcTargetAddress;
+typedef uint64_t (*LLVMOrcSymbolResolverFn)(const char *Name,
+ void *LookupCtx);
+
+/**
+ * Create an ORC JIT stack.
+ *
+ * The client owns the resulting stack, and must call OrcDisposeInstance(...)
+ * to destroy it and free its memory. The JIT stack will take ownership of the
+ * TargetMachine, which will be destroyed when the stack is destroyed. The
+ * client should not attempt to dispose of the Target Machine, or it will result
+ * in a double-free.
+ */
+LLVMOrcJITStackRef LLVMOrcCreateInstance(LLVMTargetMachineRef TM,
+ LLVMContextRef Context);
+
+/**
+ * Mangle the given symbol.
+ * Memory will be allocated for MangledSymbol to hold the result. The client
+ */
+void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledSymbol,
+ const char *Symbol);
+
+/**
+ * Dispose of a mangled symbol.
+ */
+
+void LLVMOrcDisposeMangledSymbol(char *MangledSymbol);
+
+/**
+ * Add module to be eagerly compiled.
+ */
+LLVMOrcModuleHandle
+LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, LLVMModuleRef Mod,
+ LLVMOrcSymbolResolverFn SymbolResolver,
+ void *SymbolResolverCtx);
+
+/**
+ * Add module to be lazily compiled one function at a time.
+ */
+LLVMOrcModuleHandle
+LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, LLVMModuleRef Mod,
+ LLVMOrcSymbolResolverFn SymbolResolver,
+ void *SymbolResolverCtx);
+
+/**
+ * Add an object file.
+ */
+LLVMOrcModuleHandle
+LLVMOrcAddObjectFile(LLVMOrcJITStackRef JITStack, LLVMObjectFileRef Obj,
+ LLVMOrcSymbolResolverFn SymbolResolver,
+ void *SymbolResolverCtx);
+
+/**
+ * Remove a module set from the JIT.
+ *
+ * This works for all modules that can be added via OrcAdd*, including object
+ * files.
+ */
+void LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, LLVMOrcModuleHandle H);
+
+/**
+ * Get symbol address from JIT instance.
+ */
+LLVMOrcTargetAddress LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
+ const char *SymbolName);
+
+/**
+ * Dispose of an ORC JIT stack.
+ */
+void LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack);
+
+#ifdef __cplusplus
+}
+#endif /* extern "C" */
+
+#endif /* LLVM_C_ORCBINDINGS_H */
diff --git a/lib/ExecutionEngine/Orc/CMakeLists.txt b/lib/ExecutionEngine/Orc/CMakeLists.txt
index 99fe22c001d..a17f52e322e 100644
--- a/lib/ExecutionEngine/Orc/CMakeLists.txt
+++ b/lib/ExecutionEngine/Orc/CMakeLists.txt
@@ -2,6 +2,8 @@ add_llvm_library(LLVMOrcJIT
ExecutionUtils.cpp
IndirectionUtils.cpp
NullResolver.cpp
+ OrcCBindings.cpp
+ OrcCBindingsStack.cpp
OrcMCJITReplacement.cpp
OrcTargetSupport.cpp
diff --git a/lib/ExecutionEngine/Orc/OrcCBindings.cpp b/lib/ExecutionEngine/Orc/OrcCBindings.cpp
new file mode 100644
index 00000000000..9643f466360
--- /dev/null
+++ b/lib/ExecutionEngine/Orc/OrcCBindings.cpp
@@ -0,0 +1,80 @@
+//===----------- OrcCBindings.cpp - C bindings for the Orc APIs -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcCBindingsStack.h"
+#include "llvm-c/OrcBindings.h"
+
+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));
+ LLVMContext &Ctx = *unwrap(Context);
+
+ Triple T(TM2->getTargetTriple());
+
+ auto CallbackMgrBuilder = OrcCBindingsStack::createCallbackManagerBuilder(T);
+ auto IndirectStubsMgrBuilder =
+ OrcCBindingsStack::createIndirectStubsMgrBuilder(T);
+
+ OrcCBindingsStack *JITStack =
+ new OrcCBindingsStack(*TM2, Ctx, CallbackMgrBuilder,
+ IndirectStubsMgrBuilder);
+
+ return wrap(JITStack);
+}
+
+void LLVMOrcGetMangledSymbol(LLVMOrcJITStackRef JITStack, char **MangledName,
+ const char *SymbolName) {
+ OrcCBindingsStack &J = *unwrap(JITStack);
+ std::string Mangled = J.mangle(SymbolName);
+ *MangledName = new char[Mangled.size() + 1];
+ strcpy(*MangledName, Mangled.c_str());
+}
+
+void LLVMOrcDisposeMangledSymbol(char *MangledName) {
+ delete[] MangledName;
+}
+
+LLVMOrcModuleHandle
+LLVMOrcAddEagerlyCompiledIR(LLVMOrcJITStackRef JITStack, LLVMModuleRef Mod,
+ LLVMOrcSymbolResolverFn SymbolResolver,
+ void *SymbolResolverCtx) {
+ OrcCBindingsStack &J = *unwrap(JITStack);
+ Module *M(unwrap(Mod));
+ return J.addIRModuleEager(M, SymbolResolver, SymbolResolverCtx);
+}
+
+LLVMOrcModuleHandle
+LLVMOrcAddLazilyCompiledIR(LLVMOrcJITStackRef JITStack, LLVMModuleRef Mod,
+ LLVMOrcSymbolResolverFn SymbolResolver,
+ void *SymbolResolverCtx) {
+ OrcCBindingsStack &J = *unwrap(JITStack);
+ Module *M(unwrap(Mod));
+ return J.addIRModuleLazy(M, SymbolResolver, SymbolResolverCtx);
+}
+
+void LLVMOrcRemoveModule(LLVMOrcJITStackRef JITStack, LLVMOrcModuleHandle H) {
+ OrcCBindingsStack &J = *unwrap(JITStack);
+ J.removeModule(H);
+}
+
+LLVMOrcTargetAddress LLVMOrcGetSymbolAddress(LLVMOrcJITStackRef JITStack,
+ const char *SymbolName) {
+ OrcCBindingsStack &J = *unwrap(JITStack);
+ auto Sym = J.findSymbol(SymbolName, true);
+ return Sym.getAddress();
+}
+
+void LLVMOrcDisposeInstance(LLVMOrcJITStackRef JITStack) {
+ delete unwrap(JITStack);
+}
diff --git a/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp b/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp
new file mode 100644
index 00000000000..93c698da104
--- /dev/null
+++ b/lib/ExecutionEngine/Orc/OrcCBindingsStack.cpp
@@ -0,0 +1,47 @@
+//===-------- OrcCBindingsStack.cpp - Orc JIT stack for C bindings --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcCBindingsStack.h"
+
+#include "llvm/ExecutionEngine/Orc/OrcTargetSupport.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/DynamicLibrary.h"
+#include <cstdio>
+#include <system_error>
+
+using namespace llvm;
+
+OrcCBindingsStack::CallbackManagerBuilder
+OrcCBindingsStack::createCallbackManagerBuilder(Triple T) {
+ switch (T.getArch()) {
+ default: return nullptr;
+
+ case Triple::x86_64: {
+ typedef orc::JITCompileCallbackManager<CompileLayerT,
+ orc::OrcX86_64> CCMgrT;
+ return [](CompileLayerT &CompileLayer, RuntimeDyld::MemoryManager &MemMgr,
+ LLVMContext &Context) {
+ return llvm::make_unique<CCMgrT>(CompileLayer, MemMgr, Context, 0,
+ 64);
+ };
+ }
+ }
+}
+
+OrcCBindingsStack::IndirectStubsManagerBuilder
+OrcCBindingsStack::createIndirectStubsMgrBuilder(Triple T) {
+ switch (T.getArch()) {
+ default: return nullptr;
+
+ case Triple::x86_64:
+ return [](){
+ return llvm::make_unique<orc::IndirectStubsManager<orc::OrcX86_64>>();
+ };
+ }
+}
diff --git a/lib/ExecutionEngine/Orc/OrcCBindingsStack.h b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
new file mode 100644
index 00000000000..5b58c009878
--- /dev/null
+++ b/lib/ExecutionEngine/Orc/OrcCBindingsStack.h
@@ -0,0 +1,268 @@
+//===--- OrcCBindingsStack.h - Orc JIT stack for C bindings ---*- C++ -*---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
+#define LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
+#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
+#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
+#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
+#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
+#include "llvm/IR/LLVMContext.h"
+
+namespace llvm {
+
+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;
+ typedef orc::CompileOnDemandLayer<CompileLayerT, CompileCallbackMgr> CODLayerT;
+
+ typedef std::function<
+ std::unique_ptr<CompileCallbackMgr>(CompileLayerT&,
+ RuntimeDyld::MemoryManager&,
+ LLVMContext&)>
+ CallbackManagerBuilder;
+
+ typedef CODLayerT::IndirectStubsManagerBuilderT IndirectStubsManagerBuilder;
+
+private:
+
+ typedef enum { Invalid, CODLayerHandle, ObjectLayerHandle } HandleType;
+ union RawHandleUnion {
+ RawHandleUnion() { memset(this, 0, sizeof(RawHandleUnion)); }
+ ObjLayerT::ObjSetHandleT Obj;
+ CODLayerT::ModuleSetHandleT COD;
+ };
+
+ struct ModuleHandleData {
+
+ ModuleHandleData() : Type(Invalid) {}
+
+ ModuleHandleData(ObjLayerT::ObjSetHandleT H)
+ : Type(ObjectLayerHandle) {
+ RawHandle.Obj = std::move(H);
+ }
+
+ ModuleHandleData(CODLayerT::ModuleSetHandleT H)
+ : Type(CODLayerHandle) {
+ RawHandle.COD = std::move(H);
+ }
+
+ HandleType Type;
+ RawHandleUnion RawHandle;
+ };
+
+public:
+
+ // We need a 'ModuleSetHandleT' to conform to the layer concept.
+ typedef unsigned ModuleSetHandleT;
+
+ typedef unsigned ModuleHandleT;
+
+ static CallbackManagerBuilder createCallbackManagerBuilder(Triple T);
+ static IndirectStubsManagerBuilder createIndirectStubsMgrBuilder(Triple T);
+
+ OrcCBindingsStack(TargetMachine &TM, LLVMContext &Context,
+ CallbackManagerBuilder &BuildCallbackMgr,
+ IndirectStubsManagerBuilder IndirectStubsMgrBuilder)
+ : 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),
+ CXXRuntimeOverrides([this](const std::string &S) { return mangle(S); }) {}
+
+ ~OrcCBindingsStack() {
+ // Run any destructors registered with __cxa_atexit.
+ CXXRuntimeOverrides.runDestructors();
+ // Run any IR destructors.
+ for (auto &DtorRunner : IRStaticDestructorRunners)
+ DtorRunner.runViaLayer(*this);
+ }
+
+ std::string mangle(StringRef Name) {
+ std::string MangledName;
+ {
+ raw_string_ostream MangledNameStream(MangledName);
+ Mangler::getNameWithPrefix(MangledNameStream, Name, DL);
+ }
+ return MangledName;
+ }
+
+ template <typename PtrTy>
+ static PtrTy fromTargetAddress(orc::TargetAddress Addr) {
+ return reinterpret_cast<PtrTy>(static_cast<uintptr_t>(Addr));
+ }
+
+ std::shared_ptr<RuntimeDyld::SymbolResolver>
+ createResolver(CExternalSymbolResolverFn ExternalResolver,
+ void *ExternalResolverCtx) {
+ auto Resolver = orc::createLambdaResolver(
+ [this, ExternalResolver, ExternalResolverCtx](const std::string &Name) {
+ // Search order:
+ // 1. JIT'd symbols.
+ // 2. Runtime overrides.
+ // 3. External resolver (if present).
+
+ if (auto Sym = CODLayer.findSymbol(Name, true))
+ return RuntimeDyld::SymbolInfo(Sym.getAddress(),
+ Sym.getFlags());
+ if (auto Sym = CXXRuntimeOverrides.searchOverrides(Name))
+ return Sym;
+
+ if (ExternalResolver)
+ return RuntimeDyld::SymbolInfo(ExternalResolver(Name.c_str(),
+ ExternalResolverCtx),
+ llvm::JITSymbolFlags::Exported);
+
+ return RuntimeDyld::SymbolInfo(nullptr);
+ },
+ [](const std::string &Name) {
+ return RuntimeDyld::SymbolInfo(nullptr);
+ }
+ );
+
+ return std::shared_ptr<RuntimeDyld::SymbolResolver>(std::move(Resolver));
+ }
+
+ template <typename LayerT>
+ ModuleHandleT addIRModule(LayerT &Layer,
+ Module *M,
+ std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr,
+ CExternalSymbolResolverFn ExternalResolver,
+ void *ExternalResolverCtx) {
+
+ // Attach a data-layout if one isn't already present.
+ if (M->getDataLayout().isDefault())
+ M->setDataLayout(DL);
+
+ // Record the static constructors and destructors. We have to do this before
+ // we hand over ownership of the module to the JIT.
+ std::vector<std::string> CtorNames, DtorNames;
+ for (auto Ctor : orc::getConstructors(*M))
+ CtorNames.push_back(mangle(Ctor.Func->getName()));
+ for (auto Dtor : orc::getDestructors(*M))
+ DtorNames.push_back(mangle(Dtor.Func->getName()));
+
+ // Create the resolver.
+ auto Resolver = createResolver(ExternalResolver, ExternalResolverCtx);
+
+ // Add the module to the JIT.
+ std::vector<Module*> S;
+ S.push_back(std::move(M));
+
+ auto LH = Layer.addModuleSet(std::move(S), std::move(MemMgr),
+ std::move(Resolver));
+ ModuleHandleT H = createHandle(LH);
+
+ // Run the static constructors, and save the static destructor runner for
+ // execution when the JIT is torn down.
+ orc::CtorDtorRunner<OrcCBindingsStack> CtorRunner(std::move(CtorNames), H);
+ CtorRunner.runViaLayer(*this);
+
+ IRStaticDestructorRunners.emplace_back(std::move(DtorNames), H);
+
+ return H;
+ }
+
+ ModuleHandleT addIRModuleEager(Module* M,
+ CExternalSymbolResolverFn ExternalResolver,
+ void *ExternalResolverCtx) {
+ return addIRModule(CompileLayer, std::move(M),
+ llvm::make_unique<SectionMemoryManager>(),
+ std::move(ExternalResolver), ExternalResolverCtx);
+ }
+
+ ModuleHandleT addIRModuleLazy(Module* M,
+ CExternalSymbolResolverFn ExternalResolver,
+ void *ExternalResolverCtx) {
+ return addIRModule(CODLayer, std::move(M), nullptr,
+ std::move(ExternalResolver), ExternalResolverCtx);
+ }
+
+ void removeModule(ModuleHandleT H) {
+ auto &HD = HandleData[H];
+ switch (HD.Type) {
+ case ObjectLayerHandle:
+ ObjectLayer.removeObjectSet(HD.RawHandle.Obj);
+ break;
+ case CODLayerHandle:
+ CODLayer.removeModuleSet(HD.RawHandle.COD);
+ break;
+ default:
+ llvm_unreachable("removeModule called on invalid handle type");
+ }
+ }
+
+ orc::JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
+ return CODLayer.findSymbol(mangle(Name), ExportedSymbolsOnly);
+ }
+
+ orc::JITSymbol findSymbolIn(ModuleHandleT H, const std::string &Name,
+ bool ExportedSymbolsOnly) {
+ auto &HD = HandleData[H];
+ switch (HD.Type) {
+ case ObjectLayerHandle:
+ return ObjectLayer.findSymbolIn(HD.RawHandle.Obj, mangle(Name),
+ ExportedSymbolsOnly);
+ case CODLayerHandle:
+ return CODLayer.findSymbolIn(HD.RawHandle.COD, mangle(Name),
+ ExportedSymbolsOnly);
+ default:
+ llvm_unreachable("removeModule called on invalid handle type");
+ }
+ }
+
+private:
+
+ template <typename LayerHandleT>
+ unsigned createHandle(LayerHandleT LH) {
+ unsigned NewHandle;
+ if (!FreeHandles.empty()) {
+ NewHandle = FreeHandles.back();
+ FreeHandles.pop_back();
+ HandleData[NewHandle] = ModuleHandleData(std::move(LH));
+ return NewHandle;
+ } else {
+ NewHandle = HandleData.size();
+ HandleData.push_back(ModuleHandleData(std::move(LH)));
+ }
+ return NewHandle;
+ }
+
+ DataLayout DL;
+ SectionMemoryManager CCMgrMemMgr;
+
+ ObjLayerT ObjectLayer;
+ CompileLayerT CompileLayer;
+ std::unique_ptr<CompileCallbackMgr> CCMgr;
+ CODLayerT CODLayer;
+
+ std::vector<ModuleHandleData> HandleData;
+ std::vector<unsigned> FreeHandles;
+
+ orc::LocalCXXRuntimeOverrides CXXRuntimeOverrides;
+ std::vector<orc::CtorDtorRunner<OrcCBindingsStack>> IRStaticDestructorRunners;
+};
+
+} // end namespace llvm
+
+#endif // LLVM_LIB_EXECUTIONENGINE_ORC_ORCCBINDINGSSTACK_H
diff --git a/unittests/ExecutionEngine/Orc/CMakeLists.txt b/unittests/ExecutionEngine/Orc/CMakeLists.txt
index 031eea5f5af..dc401c9743e 100644
--- a/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/unittests/ExecutionEngine/Orc/CMakeLists.txt
@@ -1,7 +1,11 @@
+
set(LLVM_LINK_COMPONENTS
Core
OrcJIT
+ MC
Support
+ Target
+ native
)
add_llvm_unittest(OrcJITTests
@@ -10,5 +14,6 @@ add_llvm_unittest(OrcJITTests
GlobalMappingLayerTest.cpp
LazyEmittingLayerTest.cpp
ObjectTransformLayerTest.cpp
+ OrcCAPITest.cpp
OrcTestCommon.cpp
)
diff --git a/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp b/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp
index 1a533b05838..38b60ea7fcd 100644
--- a/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp
+++ b/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp
@@ -18,7 +18,7 @@ namespace {
TEST(IndirectionUtilsTest, MakeStub) {
ModuleBuilder MB(getGlobalContext(), "x86_64-apple-macosx10.10", "");
- Function *F = MB.createFunctionDecl<void(DummyStruct, DummyStruct)>(MB.getModule(), "");
+ Function *F = MB.createFunctionDecl<void(DummyStruct, DummyStruct)>("");
SmallVector<AttributeSet, 4> Attrs;
Attrs.push_back(
AttributeSet::get(MB.getModule()->getContext(), 1U,
diff --git a/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
new file mode 100644
index 00000000000..bddb6a76bbf
--- /dev/null
+++ b/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
@@ -0,0 +1,109 @@
+//===--------------- OrcCAPITest.cpp - Unit tests Orc C API ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OrcTestCommon.h"
+#include "gtest/gtest.h"
+#include "llvm-c/OrcBindings.h"
+#include "llvm-c/Target.h"
+#include "llvm-c/TargetMachine.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+namespace llvm {
+
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef);
+
+class OrcCAPIExecutionTest : public testing::Test, public OrcExecutionTest {
+protected:
+
+ std::unique_ptr<Module> createTestModule(const Triple &TT) {
+ ModuleBuilder MB(getGlobalContext(), TT.str(), "");
+ Function *TestFunc = MB.createFunctionDecl<int()>("testFunc");
+ Function *Main = MB.createFunctionDecl<int(int, char*[])>("main");
+
+ Main->getBasicBlockList().push_back(BasicBlock::Create(getGlobalContext()));
+ IRBuilder<> B(&Main->back());
+ Value* Result = B.CreateCall(TestFunc);
+ B.CreateRet(Result);
+
+ return MB.takeModule();
+ }
+
+ typedef int (*MainFnTy)(void);
+
+ static int myTestFuncImpl(void) {
+ return 42;
+ }
+
+ static char *testFuncName;
+
+ static uint64_t myResolver(const char *Name, void *Ctx) {
+ if (!strncmp(Name, testFuncName, 8))
+ return (uint64_t)&myTestFuncImpl;
+ return 0;
+ }
+
+};
+
+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());
+
+ LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
+
+ LLVMOrcModuleHandle H =
+ LLVMOrcAddEagerlyCompiledIR(JIT, wrap(M.get()), myResolver, 0);
+ MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main");
+ int Result = MainFn();
+ EXPECT_EQ(Result, 42)
+ << "Eagerly JIT'd code did not return expected result";
+
+ LLVMOrcRemoveModule(JIT, H);
+
+ LLVMOrcDisposeMangledSymbol(testFuncName);
+ LLVMOrcDisposeInstance(JIT);
+}
+
+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());
+
+ LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
+ LLVMOrcModuleHandle H =
+ LLVMOrcAddLazilyCompiledIR(JIT, wrap(M.get()), myResolver, 0);
+ MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main");
+ int Result = MainFn();
+ EXPECT_EQ(Result, 42)
+ << "Lazily JIT'd code did not return expected result";
+
+ LLVMOrcRemoveModule(JIT, H);
+
+ LLVMOrcDisposeMangledSymbol(testFuncName);
+ LLVMOrcDisposeInstance(JIT);
+}
+
+}
diff --git a/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp b/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp
index 5fea3c89f86..1b5485d3b33 100644
--- a/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp
+++ b/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp
@@ -15,6 +15,8 @@
using namespace llvm;
+bool OrcExecutionTest::NativeTargetInitialized = false;
+
ModuleBuilder::ModuleBuilder(LLVMContext &Context, StringRef Triple,
StringRef Name)
: M(new Module(Name, Context)),
diff --git a/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/unittests/ExecutionEngine/Orc/OrcTestCommon.h
index 4be2e196707..18e3874acaf 100644
--- a/unittests/ExecutionEngine/Orc/OrcTestCommon.h
+++ b/unittests/ExecutionEngine/Orc/OrcTestCommon.h
@@ -20,21 +20,52 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/TypeBuilder.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/Orc/JITSymbol.h"
+#include "llvm/Support/TargetSelect.h"
#include <memory>
namespace llvm {
+// Base class for Orc tests that will execute code.
+class OrcExecutionTest {
+public:
+
+ OrcExecutionTest() {
+ if (!NativeTargetInitialized) {
+ InitializeNativeTarget();
+ InitializeNativeTargetAsmParser();
+ 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());
+
+ const Triple& TT = TM->getTargetTriple();
+
+ if (TT.getArch() == Triple::x86_64)
+ return std::move(TM);
+
+ return nullptr;
+ }
+
+private:
+ static bool NativeTargetInitialized;
+};
+
class ModuleBuilder {
public:
ModuleBuilder(LLVMContext &Context, StringRef Triple,
StringRef Name);
template <typename FuncType>
- Function* createFunctionDecl(Module *M, StringRef Name) {
+ Function* createFunctionDecl(StringRef Name) {
return Function::Create(
TypeBuilder<FuncType, false>::get(M->getContext()),
- GlobalValue::ExternalLinkage, Name, M);
+ GlobalValue::ExternalLinkage, Name, M.get());
}
Module* getModule() { return M.get(); }