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 | |
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(Name: "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, TSM: ExitOnErr(parseExampleModule(Source: FooMod, Name: "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(RT: BarRT, TSM: ExitOnErr(parseExampleModule(Source: BarMod, Name: "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(RT: BazRT, TSM: ExitOnErr(parseExampleModule(Source: BazMod, Name: "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, UnmangledName: Name)) |
95 | dbgs() << *Sym << "\n" ; |
96 | else |
97 | dbgs() << "error: " << toString(E: 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 | |