xref: /llvm-project/llvm/examples/OrcV2Examples/LLJITRemovableCode/LLJITRemovableCode.cpp (revision d467396ae0594310848f84f29ec5439fde3ef905)
1 //===--------- LLJITRemovableCode.cpp -- LLJIT with Code Removal ----------===//
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 // In this example we will use an the resource management APIs to transfer
10 // ownership of modules, remove modules from a JITDylib, and then a whole
11 // JITDylib from the ExecutionSession.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
16 #include "llvm/IR/LegacyPassManager.h"
17 #include "llvm/Pass.h"
18 #include "llvm/Support/InitLLVM.h"
19 #include "llvm/Support/TargetSelect.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include "llvm/Transforms/IPO.h"
22 #include "llvm/Transforms/Scalar.h"
23 
24 #include "../ExampleModules.h"
25 
26 using namespace llvm;
27 using namespace llvm::orc;
28 
29 ExitOnError ExitOnErr;
30 
31 // Example IR modules.
32 //
33 // We will use a few modules containing no-op functions to demonstrate the code
34 // removal APIs.
35 
36 const llvm::StringRef FooMod =
37     R"(
38   define void @foo() {
39   entry:
40     ret void
41   }
42 )";
43 
44 const llvm::StringRef BarMod =
45     R"(
46   define void @bar() {
47   entry:
48     ret void
49   }
50 )";
51 
52 const llvm::StringRef BazMod =
53     R"(
54   define void @baz() {
55   entry:
56     ret void
57   }
58 )";
59 
main(int argc,char * argv[])60 int main(int argc, char *argv[]) {
61   // Initialize LLVM.
62   InitLLVM X(argc, argv);
63 
64   InitializeNativeTarget();
65   InitializeNativeTargetAsmPrinter();
66 
67   ExitOnErr.setBanner(std::string(argv[0]) + ": ");
68 
69   // (1) Create LLJIT instance.
70   auto J = ExitOnErr(LLJITBuilder().create());
71 
72   // (2) Create a new JITDylib to use for this example.
73   auto &JD = ExitOnErr(J->createJITDylib("JD"));
74 
75   // (3) Add the 'foo' module with no explicit resource tracker. The resources
76   // for 'foo' will be tracked by the default tracker for JD. We will not be
77   // able to free it separately, but its resources will still be freed when we
78   // clear or remove JD.
79   ExitOnErr(J->addIRModule(JD, ExitOnErr(parseExampleModule(FooMod, "foo"))));
80 
81   // (4) Create a tracker for the module 'bar' and use it to add that module.
82   auto BarRT = JD.createResourceTracker();
83   ExitOnErr(
84       J->addIRModule(BarRT, ExitOnErr(parseExampleModule(BarMod, "bar"))));
85 
86   // (5) Create a tracker for the module 'baz' and use it to add that module.
87   auto BazRT = JD.createResourceTracker();
88   ExitOnErr(
89       J->addIRModule(BazRT, ExitOnErr(parseExampleModule(BazMod, "baz"))));
90 
91   // (6) Print out the symbols in their initial state:
92   auto PrintSymbol = [&](StringRef Name) {
93     dbgs() << Name << " = ";
94     if (auto Sym = J->lookup(JD, Name))
95       dbgs() << *Sym << "\n";
96     else
97       dbgs() << "error: " << toString(Sym.takeError()) << "\n";
98   };
99 
100   dbgs() << "Initially:\n";
101   PrintSymbol("foo");
102   PrintSymbol("bar");
103   PrintSymbol("baz");
104 
105   // (7) Reset BazRT. This will implicitly transfer tracking of module baz to
106   // JD's default resource tracker.
107   dbgs() << "After implicitly transferring ownership of baz to JD's default "
108             "tracker:\n";
109   BazRT = nullptr;
110   PrintSymbol("foo");
111   PrintSymbol("bar");
112   PrintSymbol("baz");
113 
114   // (8) Remove BarRT. This should remove the bar symbol.
115   dbgs() << "After removing bar (lookup for bar should yield a missing symbol "
116             "error):\n";
117   ExitOnErr(BarRT->remove());
118   PrintSymbol("foo");
119   PrintSymbol("bar");
120   PrintSymbol("baz");
121 
122   // (9) Clear JD. This should remove all symbols currently in the JITDylib.
123   dbgs() << "After clearing JD (lookup should yield missing symbol errors for "
124             "all symbols):\n";
125   ExitOnErr(JD.clear());
126   PrintSymbol("foo");
127   PrintSymbol("bar");
128   PrintSymbol("baz");
129 
130   // (10) Remove JD from the ExecutionSession. JD can no longer be used.
131   dbgs() << "Removing JD.\n";
132   ExitOnErr(J->getExecutionSession().removeJITDylib(JD));
133 
134   dbgs() << "done.\n";
135 
136   return 0;
137 }
138