[Orc] Add experimental C bindings for Orc.

llvm-svn: 251472
diff --git a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt b/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
index 031eea5..dc401c9 100644
--- a/llvm/unittests/ExecutionEngine/Orc/CMakeLists.txt
+++ b/llvm/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 @@
   GlobalMappingLayerTest.cpp
   LazyEmittingLayerTest.cpp
   ObjectTransformLayerTest.cpp
+  OrcCAPITest.cpp
   OrcTestCommon.cpp
   )
diff --git a/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp b/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp
index 1a533b05..38b60ea 100644
--- a/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp
+++ b/llvm/unittests/ExecutionEngine/Orc/IndirectionUtilsTest.cpp
@@ -18,7 +18,7 @@
 
 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/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp b/llvm/unittests/ExecutionEngine/Orc/OrcCAPITest.cpp
new file mode 100644
index 0000000..bddb6a7
--- /dev/null
+++ b/llvm/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/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp
index 5fea3c8..1b5485d 100644
--- a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.cpp
+++ b/llvm/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/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h b/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h
index 4be2e19..18e3874 100644
--- a/llvm/unittests/ExecutionEngine/Orc/OrcTestCommon.h
+++ b/llvm/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(); }