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("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() << formatv("{0:x}\n", Sym->getAddress()); 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