1*633ea072SLang Hames //===--- LLJITWithObjectCache.cpp - An LLJIT example with an ObjectCache --===// 2*633ea072SLang Hames // 3*633ea072SLang Hames // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*633ea072SLang Hames // See https://llvm.org/LICENSE.txt for license information. 5*633ea072SLang Hames // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*633ea072SLang Hames // 7*633ea072SLang Hames //===----------------------------------------------------------------------===// 8*633ea072SLang Hames 9*633ea072SLang Hames #include "llvm/ADT/StringMap.h" 10*633ea072SLang Hames #include "llvm/ExecutionEngine/ObjectCache.h" 11*633ea072SLang Hames #include "llvm/ExecutionEngine/Orc/LLJIT.h" 12*633ea072SLang Hames #include "llvm/IR/Function.h" 13*633ea072SLang Hames #include "llvm/IR/IRBuilder.h" 14*633ea072SLang Hames #include "llvm/IR/Module.h" 15*633ea072SLang Hames #include "llvm/Support/InitLLVM.h" 16*633ea072SLang Hames #include "llvm/Support/TargetSelect.h" 17*633ea072SLang Hames #include "llvm/Support/raw_ostream.h" 18*633ea072SLang Hames 19*633ea072SLang Hames #include "../ExampleModules.h" 20*633ea072SLang Hames 21*633ea072SLang Hames using namespace llvm; 22*633ea072SLang Hames using namespace llvm::orc; 23*633ea072SLang Hames 24*633ea072SLang Hames ExitOnError ExitOnErr; 25*633ea072SLang Hames 26*633ea072SLang Hames class MyObjectCache : public ObjectCache { 27*633ea072SLang Hames public: 28*633ea072SLang Hames void notifyObjectCompiled(const Module *M, 29*633ea072SLang Hames MemoryBufferRef ObjBuffer) override { 30*633ea072SLang Hames CachedObjects[M->getModuleIdentifier()] = MemoryBuffer::getMemBufferCopy( 31*633ea072SLang Hames ObjBuffer.getBuffer(), ObjBuffer.getBufferIdentifier()); 32*633ea072SLang Hames } 33*633ea072SLang Hames 34*633ea072SLang Hames std::unique_ptr<MemoryBuffer> getObject(const Module *M) override { 35*633ea072SLang Hames auto I = CachedObjects.find(M->getModuleIdentifier()); 36*633ea072SLang Hames if (I == CachedObjects.end()) { 37*633ea072SLang Hames dbgs() << "No object for " << M->getModuleIdentifier() 38*633ea072SLang Hames << " in cache. Compiling.\n"; 39*633ea072SLang Hames return nullptr; 40*633ea072SLang Hames } 41*633ea072SLang Hames 42*633ea072SLang Hames dbgs() << "Object for " << M->getModuleIdentifier() 43*633ea072SLang Hames << " loaded from cache.\n"; 44*633ea072SLang Hames return MemoryBuffer::getMemBuffer(I->second->getMemBufferRef()); 45*633ea072SLang Hames } 46*633ea072SLang Hames 47*633ea072SLang Hames private: 48*633ea072SLang Hames StringMap<std::unique_ptr<MemoryBuffer>> CachedObjects; 49*633ea072SLang Hames }; 50*633ea072SLang Hames 51*633ea072SLang Hames void runJITWithCache(ObjectCache &ObjCache) { 52*633ea072SLang Hames 53*633ea072SLang Hames // Create an LLJIT instance with a custom IRCompiler. 54*633ea072SLang Hames auto J = ExitOnErr( 55*633ea072SLang Hames LLJITBuilder() 56*633ea072SLang Hames .setCompileFunctionCreator( 57*633ea072SLang Hames [&](JITTargetMachineBuilder JTMB) 58*633ea072SLang Hames -> Expected<std::unique_ptr<IRCompileLayer::IRCompiler>> { 59*633ea072SLang Hames auto TM = JTMB.createTargetMachine(); 60*633ea072SLang Hames if (!TM) 61*633ea072SLang Hames return TM.takeError(); 62*633ea072SLang Hames return std::make_unique<TMOwningSimpleCompiler>(std::move(*TM), 63*633ea072SLang Hames &ObjCache); 64*633ea072SLang Hames }) 65*633ea072SLang Hames .create()); 66*633ea072SLang Hames 67*633ea072SLang Hames auto M = ExitOnErr(parseExampleModule(Add1Example, "add1")); 68*633ea072SLang Hames 69*633ea072SLang Hames ExitOnErr(J->addIRModule(std::move(M))); 70*633ea072SLang Hames 71*633ea072SLang Hames // Look up the JIT'd function, cast it to a function pointer, then call it. 72*633ea072SLang Hames auto Add1Sym = ExitOnErr(J->lookup("add1")); 73*633ea072SLang Hames int (*Add1)(int) = (int (*)(int))Add1Sym.getAddress(); 74*633ea072SLang Hames 75*633ea072SLang Hames int Result = Add1(42); 76*633ea072SLang Hames outs() << "add1(42) = " << Result << "\n"; 77*633ea072SLang Hames } 78*633ea072SLang Hames 79*633ea072SLang Hames int main(int argc, char *argv[]) { 80*633ea072SLang Hames // Initialize LLVM. 81*633ea072SLang Hames InitLLVM X(argc, argv); 82*633ea072SLang Hames 83*633ea072SLang Hames InitializeNativeTarget(); 84*633ea072SLang Hames InitializeNativeTargetAsmPrinter(); 85*633ea072SLang Hames 86*633ea072SLang Hames cl::ParseCommandLineOptions(argc, argv, "LLJITWithObjectCache"); 87*633ea072SLang Hames ExitOnErr.setBanner(std::string(argv[0]) + ": "); 88*633ea072SLang Hames 89*633ea072SLang Hames MyObjectCache MyCache; 90*633ea072SLang Hames 91*633ea072SLang Hames runJITWithCache(MyCache); 92*633ea072SLang Hames runJITWithCache(MyCache); 93*633ea072SLang Hames 94*633ea072SLang Hames return 0; 95*633ea072SLang Hames } 96