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