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