aboutsummaryrefslogtreecommitdiff
path: root/llvm/examples/OrcV2Examples/LLJITRemovableCode/LLJITRemovableCode.cpp
blob: a91ebbb730ce93e3a06227a66421f0094fee063e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
//===--------- LLJITRemovableCode.cpp -- LLJIT with Code Removal ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// In this example we will use an the resource management APIs to transfer
// ownership of modules, remove modules from a JITDylib, and then a whole
// JITDylib from the ExecutionSession.
//
//===----------------------------------------------------------------------===//

#include "llvm/ExecutionEngine/Orc/LLJIT.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Pass.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"

#include "../ExampleModules.h"

using namespace llvm;
using namespace llvm::orc;

ExitOnError ExitOnErr;

// Example IR modules.
//
// We will use a few modules containing no-op functions to demonstrate the code
// removal APIs.

const llvm::StringRef FooMod =
    R"(
  define void @foo() {
  entry:
    ret void
  }
)";

const llvm::StringRef BarMod =
    R"(
  define void @bar() {
  entry:
    ret void
  }
)";

const llvm::StringRef BazMod =
    R"(
  define void @baz() {
  entry:
    ret void
  }
)";

int main(int argc, char *argv[]) {
  // Initialize LLVM.
  InitLLVM X(argc, argv);

  InitializeNativeTarget();
  InitializeNativeTargetAsmPrinter();

  ExitOnErr.setBanner(std::string(argv[0]) + ": ");

  // (1) Create LLJIT instance.
  auto J = ExitOnErr(LLJITBuilder().create());

  // (2) Create a new JITDylib to use for this example.
  auto &JD = ExitOnErr(J->createJITDylib("JD"));

  // (3) Add the 'foo' module with no explicit resource tracker. The resources
  // for 'foo' will be tracked by the default tracker for JD. We will not be
  // able to free it separately, but its resources will still be freed when we
  // clear or remove JD.
  ExitOnErr(J->addIRModule(JD, ExitOnErr(parseExampleModule(FooMod, "foo"))));

  // (4) Create a tracker for the module 'bar' and use it to add that module.
  auto BarRT = JD.createResourceTracker();
  ExitOnErr(
      J->addIRModule(BarRT, ExitOnErr(parseExampleModule(BarMod, "bar"))));

  // (5) Create a tracker for the module 'baz' and use it to add that module.
  auto BazRT = JD.createResourceTracker();
  ExitOnErr(
      J->addIRModule(BazRT, ExitOnErr(parseExampleModule(BazMod, "baz"))));

  // (6) Print out the symbols in their initial state:
  auto PrintSymbol = [&](StringRef Name) {
    dbgs() << Name << " = ";
    if (auto Sym = J->lookup(JD, Name))
      dbgs() << *Sym << "\n";
    else
      dbgs() << "error: " << toString(Sym.takeError()) << "\n";
  };

  dbgs() << "Initially:\n";
  PrintSymbol("foo");
  PrintSymbol("bar");
  PrintSymbol("baz");

  // (7) Reset BazRT. This will implicitly transfer tracking of module baz to
  // JD's default resource tracker.
  dbgs() << "After implicitly transferring ownership of baz to JD's default "
            "tracker:\n";
  BazRT = nullptr;
  PrintSymbol("foo");
  PrintSymbol("bar");
  PrintSymbol("baz");

  // (8) Remove BarRT. This should remove the bar symbol.
  dbgs() << "After removing bar (lookup for bar should yield a missing symbol "
            "error):\n";
  ExitOnErr(BarRT->remove());
  PrintSymbol("foo");
  PrintSymbol("bar");
  PrintSymbol("baz");

  // (9) Clear JD. This should remove all symbols currently in the JITDylib.
  dbgs() << "After clearing JD (lookup should yield missing symbol errors for "
            "all symbols):\n";
  ExitOnErr(JD.clear());
  PrintSymbol("foo");
  PrintSymbol("bar");
  PrintSymbol("baz");

  // (10) Remove JD from the ExecutionSession. JD can no longer be used.
  dbgs() << "Removing JD.\n";
  ExitOnErr(J->getExecutionSession().removeJITDylib(JD));

  dbgs() << "done.\n";

  return 0;
}