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