summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/docs/tutorial/BuildingAJIT3.rst
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2020-08-03 15:06:44 +0000
committerpatrick <patrick@openbsd.org>2020-08-03 15:06:44 +0000
commitb64793999546ed8adebaeebd9d8345d18db8927d (patch)
tree4357c27b561d73b0e089727c6ed659f2ceff5f47 /gnu/llvm/docs/tutorial/BuildingAJIT3.rst
parentAdd support for UTF-8 DISPLAY-HINTs with octet length. For now only (diff)
downloadwireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.tar.xz
wireguard-openbsd-b64793999546ed8adebaeebd9d8345d18db8927d.zip
Remove LLVM 8.0.1 files.
Diffstat (limited to 'gnu/llvm/docs/tutorial/BuildingAJIT3.rst')
-rw-r--r--gnu/llvm/docs/tutorial/BuildingAJIT3.rst191
1 files changed, 0 insertions, 191 deletions
diff --git a/gnu/llvm/docs/tutorial/BuildingAJIT3.rst b/gnu/llvm/docs/tutorial/BuildingAJIT3.rst
deleted file mode 100644
index 36ec2e707a7..00000000000
--- a/gnu/llvm/docs/tutorial/BuildingAJIT3.rst
+++ /dev/null
@@ -1,191 +0,0 @@
-=============================================
-Building a JIT: Per-function Lazy Compilation
-=============================================
-
-.. contents::
- :local:
-
-**This tutorial is under active development. It is incomplete and details may
-change frequently.** Nonetheless we invite you to try it out as it stands, and
-we welcome any feedback.
-
-Chapter 3 Introduction
-======================
-
-**Warning: This text is currently out of date due to ORC API updates.**
-
-**The example code has been updated and can be used. The text will be updated
-once the API churn dies down.**
-
-Welcome to Chapter 3 of the "Building an ORC-based JIT in LLVM" tutorial. This
-chapter discusses lazy JITing and shows you how to enable it by adding an ORC
-CompileOnDemand layer the JIT from `Chapter 2 <BuildingAJIT2.html>`_.
-
-Lazy Compilation
-================
-
-When we add a module to the KaleidoscopeJIT class from Chapter 2 it is
-immediately optimized, compiled and linked for us by the IRTransformLayer,
-IRCompileLayer and RTDyldObjectLinkingLayer respectively. This scheme, where all the
-work to make a Module executable is done up front, is simple to understand and
-its performance characteristics are easy to reason about. However, it will lead
-to very high startup times if the amount of code to be compiled is large, and
-may also do a lot of unnecessary compilation if only a few compiled functions
-are ever called at runtime. A truly "just-in-time" compiler should allow us to
-defer the compilation of any given function until the moment that function is
-first called, improving launch times and eliminating redundant work. In fact,
-the ORC APIs provide us with a layer to lazily compile LLVM IR:
-*CompileOnDemandLayer*.
-
-The CompileOnDemandLayer class conforms to the layer interface described in
-Chapter 2, but its addModule method behaves quite differently from the layers
-we have seen so far: rather than doing any work up front, it just scans the
-Modules being added and arranges for each function in them to be compiled the
-first time it is called. To do this, the CompileOnDemandLayer creates two small
-utilities for each function that it scans: a *stub* and a *compile
-callback*. The stub is a pair of a function pointer (which will be pointed at
-the function's implementation once the function has been compiled) and an
-indirect jump through the pointer. By fixing the address of the indirect jump
-for the lifetime of the program we can give the function a permanent "effective
-address", one that can be safely used for indirection and function pointer
-comparison even if the function's implementation is never compiled, or if it is
-compiled more than once (due to, for example, recompiling the function at a
-higher optimization level) and changes address. The second utility, the compile
-callback, represents a re-entry point from the program into the compiler that
-will trigger compilation and then execution of a function. By initializing the
-function's stub to point at the function's compile callback, we enable lazy
-compilation: The first attempted call to the function will follow the function
-pointer and trigger the compile callback instead. The compile callback will
-compile the function, update the function pointer for the stub, then execute
-the function. On all subsequent calls to the function, the function pointer
-will point at the already-compiled function, so there is no further overhead
-from the compiler. We will look at this process in more detail in the next
-chapter of this tutorial, but for now we'll trust the CompileOnDemandLayer to
-set all the stubs and callbacks up for us. All we need to do is to add the
-CompileOnDemandLayer to the top of our stack and we'll get the benefits of
-lazy compilation. We just need a few changes to the source:
-
-.. code-block:: c++
-
- ...
- #include "llvm/ExecutionEngine/SectionMemoryManager.h"
- #include "llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h"
- #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
- ...
-
- ...
- class KaleidoscopeJIT {
- private:
- std::unique_ptr<TargetMachine> TM;
- const DataLayout DL;
- RTDyldObjectLinkingLayer ObjectLayer;
- IRCompileLayer<decltype(ObjectLayer), SimpleCompiler> CompileLayer;
-
- using OptimizeFunction =
- std::function<std::shared_ptr<Module>(std::shared_ptr<Module>)>;
-
- IRTransformLayer<decltype(CompileLayer), OptimizeFunction> OptimizeLayer;
-
- std::unique_ptr<JITCompileCallbackManager> CompileCallbackManager;
- CompileOnDemandLayer<decltype(OptimizeLayer)> CODLayer;
-
- public:
- using ModuleHandle = decltype(CODLayer)::ModuleHandleT;
-
-First we need to include the CompileOnDemandLayer.h header, then add two new
-members: a std::unique_ptr<JITCompileCallbackManager> and a CompileOnDemandLayer,
-to our class. The CompileCallbackManager member is used by the CompileOnDemandLayer
-to create the compile callback needed for each function.
-
-.. code-block:: c++
-
- KaleidoscopeJIT()
- : TM(EngineBuilder().selectTarget()), DL(TM->createDataLayout()),
- ObjectLayer([]() { return std::make_shared<SectionMemoryManager>(); }),
- CompileLayer(ObjectLayer, SimpleCompiler(*TM)),
- OptimizeLayer(CompileLayer,
- [this](std::shared_ptr<Module> M) {
- return optimizeModule(std::move(M));
- }),
- CompileCallbackManager(
- orc::createLocalCompileCallbackManager(TM->getTargetTriple(), 0)),
- CODLayer(OptimizeLayer,
- [this](Function &F) { return std::set<Function*>({&F}); },
- *CompileCallbackManager,
- orc::createLocalIndirectStubsManagerBuilder(
- TM->getTargetTriple())) {
- llvm::sys::DynamicLibrary::LoadLibraryPermanently(nullptr);
- }
-
-Next we have to update our constructor to initialize the new members. To create
-an appropriate compile callback manager we use the
-createLocalCompileCallbackManager function, which takes a TargetMachine and a
-JITTargetAddress to call if it receives a request to compile an unknown
-function. In our simple JIT this situation is unlikely to come up, so we'll
-cheat and just pass '0' here. In a production quality JIT you could give the
-address of a function that throws an exception in order to unwind the JIT'd
-code's stack.
-
-Now we can construct our CompileOnDemandLayer. Following the pattern from
-previous layers we start by passing a reference to the next layer down in our
-stack -- the OptimizeLayer. Next we need to supply a 'partitioning function':
-when a not-yet-compiled function is called, the CompileOnDemandLayer will call
-this function to ask us what we would like to compile. At a minimum we need to
-compile the function being called (given by the argument to the partitioning
-function), but we could also request that the CompileOnDemandLayer compile other
-functions that are unconditionally called (or highly likely to be called) from
-the function being called. For KaleidoscopeJIT we'll keep it simple and just
-request compilation of the function that was called. Next we pass a reference to
-our CompileCallbackManager. Finally, we need to supply an "indirect stubs
-manager builder": a utility function that constructs IndirectStubManagers, which
-are in turn used to build the stubs for the functions in each module. The
-CompileOnDemandLayer will call the indirect stub manager builder once for each
-call to addModule, and use the resulting indirect stubs manager to create
-stubs for all functions in all modules in the set. If/when the module set is
-removed from the JIT the indirect stubs manager will be deleted, freeing any
-memory allocated to the stubs. We supply this function by using the
-createLocalIndirectStubsManagerBuilder utility.
-
-.. code-block:: c++
-
- // ...
- if (auto Sym = CODLayer.findSymbol(Name, false))
- // ...
- return cantFail(CODLayer.addModule(std::move(Ms),
- std::move(Resolver)));
- // ...
-
- // ...
- return CODLayer.findSymbol(MangledNameStream.str(), true);
- // ...
-
- // ...
- CODLayer.removeModule(H);
- // ...
-
-Finally, we need to replace the references to OptimizeLayer in our addModule,
-findSymbol, and removeModule methods. With that, we're up and running.
-
-**To be done:**
-
-** Chapter conclusion.**
-
-Full Code Listing
-=================
-
-Here is the complete code listing for our running example with a CompileOnDemand
-layer added to enable lazy function-at-a-time compilation. To build this example, use:
-
-.. code-block:: bash
-
- # Compile
- clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native` -O3 -o toy
- # Run
- ./toy
-
-Here is the code:
-
-.. literalinclude:: ../../examples/Kaleidoscope/BuildingAJIT/Chapter3/KaleidoscopeJIT.h
- :language: c++
-
-`Next: Extreme Laziness -- Using Compile Callbacks to JIT directly from ASTs <BuildingAJIT4.html>`_