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