Home | History | Annotate | Download | only in Orc
      1 //===--------------- OrcCAPITest.cpp - Unit tests Orc C API ---------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "OrcTestCommon.h"
     11 #include "gtest/gtest.h"
     12 #include "llvm-c/Core.h"
     13 #include "llvm-c/OrcBindings.h"
     14 #include "llvm-c/Target.h"
     15 #include "llvm-c/TargetMachine.h"
     16 
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 #include <string.h>
     20 
     21 namespace llvm {
     22 
     23 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef)
     24 
     25 class OrcCAPIExecutionTest : public testing::Test, public OrcExecutionTest {
     26 protected:
     27   std::unique_ptr<Module> createTestModule(const Triple &TT) {
     28     ModuleBuilder MB(Context, TT.str(), "");
     29     Function *TestFunc = MB.createFunctionDecl<int()>("testFunc");
     30     Function *Main = MB.createFunctionDecl<int(int, char*[])>("main");
     31 
     32     Main->getBasicBlockList().push_back(BasicBlock::Create(Context));
     33     IRBuilder<> B(&Main->back());
     34     Value* Result = B.CreateCall(TestFunc);
     35     B.CreateRet(Result);
     36 
     37     return MB.takeModule();
     38   }
     39 
     40   typedef int (*MainFnTy)();
     41 
     42   static int myTestFuncImpl() {
     43     return 42;
     44   }
     45 
     46   static char *testFuncName;
     47 
     48   static uint64_t myResolver(const char *Name, void *Ctx) {
     49     if (!strncmp(Name, testFuncName, 8))
     50       return (uint64_t)&myTestFuncImpl;
     51     return 0;
     52   }
     53 
     54   struct CompileContext {
     55     CompileContext() : Compiled(false) { }
     56 
     57     OrcCAPIExecutionTest* APIExecTest;
     58     std::unique_ptr<Module> M;
     59     LLVMOrcModuleHandle H;
     60     bool Compiled;
     61   };
     62 
     63   static LLVMOrcTargetAddress myCompileCallback(LLVMOrcJITStackRef JITStack,
     64                                                 void *Ctx) {
     65     CompileContext *CCtx = static_cast<CompileContext*>(Ctx);
     66     auto *ET = CCtx->APIExecTest;
     67     CCtx->M = ET->createTestModule(ET->TM->getTargetTriple());
     68     CCtx->H = LLVMOrcAddEagerlyCompiledIR(JITStack, wrap(CCtx->M.get()),
     69                                           myResolver, nullptr);
     70     CCtx->Compiled = true;
     71     LLVMOrcTargetAddress MainAddr = LLVMOrcGetSymbolAddress(JITStack, "main");
     72     LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr);
     73     return MainAddr;
     74   }
     75 };
     76 
     77 char *OrcCAPIExecutionTest::testFuncName = nullptr;
     78 
     79 TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) {
     80   if (!TM)
     81     return;
     82 
     83   LLVMOrcJITStackRef JIT =
     84     LLVMOrcCreateInstance(wrap(TM.get()));
     85 
     86   std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
     87 
     88   LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
     89 
     90   LLVMOrcModuleHandle H =
     91     LLVMOrcAddEagerlyCompiledIR(JIT, wrap(M.get()), myResolver, nullptr);
     92   MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main");
     93   int Result = MainFn();
     94   EXPECT_EQ(Result, 42)
     95     << "Eagerly JIT'd code did not return expected result";
     96 
     97   LLVMOrcRemoveModule(JIT, H);
     98 
     99   LLVMOrcDisposeMangledSymbol(testFuncName);
    100   LLVMOrcDisposeInstance(JIT);
    101 }
    102 
    103 TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) {
    104   if (!TM)
    105     return;
    106 
    107   LLVMOrcJITStackRef JIT =
    108     LLVMOrcCreateInstance(wrap(TM.get()));
    109 
    110   std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple());
    111 
    112   LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
    113 
    114   LLVMOrcModuleHandle H =
    115     LLVMOrcAddLazilyCompiledIR(JIT, wrap(M.get()), myResolver, nullptr);
    116   MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main");
    117   int Result = MainFn();
    118   EXPECT_EQ(Result, 42)
    119     << "Lazily JIT'd code did not return expected result";
    120 
    121   LLVMOrcRemoveModule(JIT, H);
    122 
    123   LLVMOrcDisposeMangledSymbol(testFuncName);
    124   LLVMOrcDisposeInstance(JIT);
    125 }
    126 
    127 TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) {
    128   if (!TM)
    129     return;
    130 
    131   LLVMOrcJITStackRef JIT =
    132     LLVMOrcCreateInstance(wrap(TM.get()));
    133 
    134   LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc");
    135 
    136   CompileContext C;
    137   C.APIExecTest = this;
    138   LLVMOrcCreateIndirectStub(JIT, "foo",
    139                             LLVMOrcCreateLazyCompileCallback(JIT,
    140                                                              myCompileCallback,
    141                                                              &C));
    142   MainFnTy FooFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "foo");
    143   int Result = FooFn();
    144   EXPECT_TRUE(C.Compiled)
    145     << "Function wasn't lazily compiled";
    146   EXPECT_EQ(Result, 42)
    147     << "Direct-callback JIT'd code did not return expected result";
    148 
    149   C.Compiled = false;
    150   FooFn();
    151   EXPECT_FALSE(C.Compiled)
    152     << "Direct-callback JIT'd code was JIT'd twice";
    153 
    154   LLVMOrcRemoveModule(JIT, C.H);
    155 
    156   LLVMOrcDisposeMangledSymbol(testFuncName);
    157   LLVMOrcDisposeInstance(JIT);
    158 }
    159 
    160 } // namespace llvm
    161