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