From ebdc60a232d097e3ea392f42a1e0a2f2f7c4b48f Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Tue, 12 Apr 2022 14:47:07 -0700 Subject: [PATCH] [examples][ORC] Add a new example showing the ORCv2 removable code APIs. --- llvm/examples/OrcV2Examples/CMakeLists.txt | 1 + .../LLJITRemovableCode/CMakeLists.txt | 14 +++ .../LLJITRemovableCode/LLJITRemovableCode.cpp | 137 +++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 llvm/examples/OrcV2Examples/LLJITRemovableCode/CMakeLists.txt create mode 100644 llvm/examples/OrcV2Examples/LLJITRemovableCode/LLJITRemovableCode.cpp diff --git a/llvm/examples/OrcV2Examples/CMakeLists.txt b/llvm/examples/OrcV2Examples/CMakeLists.txt index 736ceff6..d4957c2 100644 --- a/llvm/examples/OrcV2Examples/CMakeLists.txt +++ b/llvm/examples/OrcV2Examples/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory(LLJITDumpObjects) +add_subdirectory(LLJITRemovableCode) add_subdirectory(LLJITWithCustomObjectLinkingLayer) add_subdirectory(LLJITWithExecutorProcessControl) add_subdirectory(LLJITWithGDBRegistrationListener) diff --git a/llvm/examples/OrcV2Examples/LLJITRemovableCode/CMakeLists.txt b/llvm/examples/OrcV2Examples/LLJITRemovableCode/CMakeLists.txt new file mode 100644 index 0000000..3ab58c1 --- /dev/null +++ b/llvm/examples/OrcV2Examples/LLJITRemovableCode/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LLVM_LINK_COMPONENTS + Core + ExecutionEngine + IPO + IRReader + OrcJIT + ScalarOpts + Support + nativecodegen + ) + +add_llvm_example(LLJITRemovableCode + LLJITRemovableCode.cpp + ) diff --git a/llvm/examples/OrcV2Examples/LLJITRemovableCode/LLJITRemovableCode.cpp b/llvm/examples/OrcV2Examples/LLJITRemovableCode/LLJITRemovableCode.cpp new file mode 100644 index 0000000..29735d1 --- /dev/null +++ b/llvm/examples/OrcV2Examples/LLJITRemovableCode/LLJITRemovableCode.cpp @@ -0,0 +1,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() << formatv("{0:x}\n", Sym->getAddress()); + 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; +} -- 2.7.4