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/OrcBindings.h" 13 #include "llvm-c/Target.h" 14 #include "llvm-c/TargetMachine.h" 15 16 #include <stdio.h> 17 #include <stdlib.h> 18 #include <string.h> 19 20 namespace llvm { 21 22 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(TargetMachine, LLVMTargetMachineRef); 23 24 class OrcCAPIExecutionTest : public testing::Test, public OrcExecutionTest { 25 protected: 26 27 std::unique_ptr<Module> createTestModule(const Triple &TT) { 28 ModuleBuilder MB(getGlobalContext(), 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(getGlobalContext())); 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)(void); 41 42 static int myTestFuncImpl(void) { 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, 0); 70 CCtx->Compiled = true; 71 LLVMOrcTargetAddress MainAddr = LLVMOrcGetSymbolAddress(JITStack, "main"); 72 LLVMOrcSetIndirectStubPointer(JITStack, "foo", MainAddr); 73 return MainAddr; 74 } 75 76 }; 77 78 char *OrcCAPIExecutionTest::testFuncName = 0; 79 80 TEST_F(OrcCAPIExecutionTest, TestEagerIRCompilation) { 81 if (!TM) 82 return; 83 84 LLVMOrcJITStackRef JIT = 85 LLVMOrcCreateInstance(wrap(TM.get()), LLVMGetGlobalContext()); 86 87 std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple()); 88 89 LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc"); 90 91 LLVMOrcModuleHandle H = 92 LLVMOrcAddEagerlyCompiledIR(JIT, wrap(M.get()), myResolver, 0); 93 MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main"); 94 int Result = MainFn(); 95 EXPECT_EQ(Result, 42) 96 << "Eagerly JIT'd code did not return expected result"; 97 98 LLVMOrcRemoveModule(JIT, H); 99 100 LLVMOrcDisposeMangledSymbol(testFuncName); 101 LLVMOrcDisposeInstance(JIT); 102 } 103 104 TEST_F(OrcCAPIExecutionTest, TestLazyIRCompilation) { 105 if (!TM) 106 return; 107 108 LLVMOrcJITStackRef JIT = 109 LLVMOrcCreateInstance(wrap(TM.get()), LLVMGetGlobalContext()); 110 111 std::unique_ptr<Module> M = createTestModule(TM->getTargetTriple()); 112 113 LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc"); 114 115 LLVMOrcModuleHandle H = 116 LLVMOrcAddLazilyCompiledIR(JIT, wrap(M.get()), myResolver, 0); 117 MainFnTy MainFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "main"); 118 int Result = MainFn(); 119 EXPECT_EQ(Result, 42) 120 << "Lazily JIT'd code did not return expected result"; 121 122 LLVMOrcRemoveModule(JIT, H); 123 124 LLVMOrcDisposeMangledSymbol(testFuncName); 125 LLVMOrcDisposeInstance(JIT); 126 } 127 128 TEST_F(OrcCAPIExecutionTest, TestDirectCallbacksAPI) { 129 if (!TM) 130 return; 131 132 LLVMOrcJITStackRef JIT = 133 LLVMOrcCreateInstance(wrap(TM.get()), LLVMGetGlobalContext()); 134 135 LLVMOrcGetMangledSymbol(JIT, &testFuncName, "testFunc"); 136 137 CompileContext C; 138 C.APIExecTest = this; 139 LLVMOrcCreateIndirectStub(JIT, "foo", 140 LLVMOrcCreateLazyCompileCallback(JIT, 141 myCompileCallback, 142 &C)); 143 MainFnTy FooFn = (MainFnTy)LLVMOrcGetSymbolAddress(JIT, "foo"); 144 int Result = FooFn(); 145 EXPECT_TRUE(C.Compiled) 146 << "Function wasn't lazily compiled"; 147 EXPECT_EQ(Result, 42) 148 << "Direct-callback JIT'd code did not return expected result"; 149 150 C.Compiled = false; 151 FooFn(); 152 EXPECT_FALSE(C.Compiled) 153 << "Direct-callback JIT'd code was JIT'd twice"; 154 155 LLVMOrcRemoveModule(JIT, C.H); 156 157 LLVMOrcDisposeMangledSymbol(testFuncName); 158 LLVMOrcDisposeInstance(JIT); 159 } 160 161 } 162