1======================================================= 2Building a JIT: Starting out with KaleidoscopeJIT 3======================================================= 4 5.. contents:: 6 :local: 7 8Chapter 1 Introduction 9====================== 10 11**Warning: This tutorial is currently being updated to account for ORC API 12changes. Only Chapter 1 is up-to-date.** 13 14**Example code from Chapters 2 to 4 will compile and run, but has not been 15updated** 16 17Welcome to Chapter 1 of the "Building an ORC-based JIT in LLVM" tutorial. This 18tutorial runs through the implementation of a JIT compiler using LLVM's 19On-Request-Compilation (ORC) APIs. It begins with a simplified version of the 20KaleidoscopeJIT class used in the 21`Implementing a language with LLVM <LangImpl01.html>`_ tutorials and then 22introduces new features like concurrent compilation, optimization, lazy 23compilation and remote execution. 24 25The goal of this tutorial is to introduce you to LLVM's ORC JIT APIs, show how 26these APIs interact with other parts of LLVM, and to teach you how to recombine 27them to build a custom JIT that is suited to your use-case. 28 29The structure of the tutorial is: 30 31- Chapter #1: Investigate the simple KaleidoscopeJIT class. This will 32 introduce some of the basic concepts of the ORC JIT APIs, including the 33 idea of an ORC *Layer*. 34 35- `Chapter #2 <BuildingAJIT2.html>`_: Extend the basic KaleidoscopeJIT by adding 36 a new layer that will optimize IR and generated code. 37 38- `Chapter #3 <BuildingAJIT3.html>`_: Further extend the JIT by adding a 39 Compile-On-Demand layer to lazily compile IR. 40 41- `Chapter #4 <BuildingAJIT4.html>`_: Improve the laziness of our JIT by 42 replacing the Compile-On-Demand layer with a custom layer that uses the ORC 43 Compile Callbacks API directly to defer IR-generation until functions are 44 called. 45 46- `Chapter #5 <BuildingAJIT5.html>`_: Add process isolation by JITing code into 47 a remote process with reduced privileges using the JIT Remote APIs. 48 49To provide input for our JIT we will use a lightly modified version of the 50Kaleidoscope REPL from `Chapter 7 <LangImpl07.html>`_ of the "Implementing a 51language in LLVM tutorial". 52 53Finally, a word on API generations: ORC is the 3rd generation of LLVM JIT API. 54It was preceded by MCJIT, and before that by the (now deleted) legacy JIT. 55These tutorials don't assume any experience with these earlier APIs, but 56readers acquainted with them will see many familiar elements. Where appropriate 57we will make this connection with the earlier APIs explicit to help people who 58are transitioning from them to ORC. 59 60JIT API Basics 61============== 62 63The purpose of a JIT compiler is to compile code "on-the-fly" as it is needed, 64rather than compiling whole programs to disk ahead of time as a traditional 65compiler does. To support that aim our initial, bare-bones JIT API will have 66just two functions: 67 681. void addModule(std::unique_ptr<Module> M) -- Make the given IR module 69 available for execution. 702. Expected<JITSymbol> lookup() -- Search for pointers to 71 symbols (functions or variables) that have been added to the JIT. 72 73A basic use-case for this API, executing the 'main' function from a module, 74will look like: 75 76.. code-block:: c++ 77 78 std::unique_ptr<Module> M = buildModule(); 79 JIT J; 80 J.addModule(*M); 81 auto *Main = (int(*)(int, char*[]))J.lookup("main");.getAddress(); 82 int Result = Main(); 83 84The APIs that we build in these tutorials will all be variations on this simple 85theme. Behind this API we will refine the implementation of the JIT to add 86support for concurrent compilation, optimization and lazy compilation. 87Eventually we will extend the API itself to allow higher-level program 88representations (e.g. ASTs) to be added to the JIT. 89 90KaleidoscopeJIT 91=============== 92 93In the previous section we described our API, now we examine a simple 94implementation of it: The KaleidoscopeJIT class [1]_ that was used in the 95`Implementing a language with LLVM <LangImpl01.html>`_ tutorials. We will use 96the REPL code from `Chapter 7 <LangImpl07.html>`_ of that tutorial to supply the 97input for our JIT: Each time the user enters an expression the REPL will add a 98new IR module containing the code for that expression to the JIT. If the 99expression is a top-level expression like '1+1' or 'sin(x)', the REPL will also 100use the lookup method of our JIT class find and execute the code for the 101expression. In later chapters of this tutorial we will modify the REPL to enable 102new interactions with our JIT class, but for now we will take this setup for 103granted and focus our attention on the implementation of our JIT itself. 104 105Our KaleidoscopeJIT class is defined in the KaleidoscopeJIT.h header. After the 106usual include guards and #includes [2]_, we get to the definition of our class: 107 108.. code-block:: c++ 109 110 #ifndef LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H 111 #define LLVM_EXECUTIONENGINE_ORC_KALEIDOSCOPEJIT_H 112 113 #include "llvm/ADT/StringRef.h" 114 #include "llvm/ExecutionEngine/JITSymbol.h" 115 #include "llvm/ExecutionEngine/Orc/CompileUtils.h" 116 #include "llvm/ExecutionEngine/Orc/Core.h" 117 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" 118 #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h" 119 #include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h" 120 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h" 121 #include "llvm/ExecutionEngine/SectionMemoryManager.h" 122 #include "llvm/IR/DataLayout.h" 123 #include "llvm/IR/LLVMContext.h" 124 #include <memory> 125 126 namespace llvm { 127 namespace orc { 128 129 class KaleidoscopeJIT { 130 private: 131 132 ExecutionSession ES; 133 RTDyldObjectLinkingLayer ObjectLayer{ES, getMemoryMgr}; 134 IRCompileLayer CompileLayer{ES, ObjectLayer, 135 ConcurrentIRCompiler(getJTMB())}; 136 DataLayout DL{cantFail(getJTMB().getDefaultDataLayoutForTarget())}; 137 MangleAndInterner Mangle{ES, DL}; 138 ThreadSafeContext Ctx{llvm::make_unique<LLVMContext>()}; 139 140 static JITTargetMachineBuilder getJTMB() { 141 return cantFail(JITTargetMachineBuilder::detectHost()); 142 } 143 144 static std::unique_ptr<SectionMemoryManager> getMemoryMgr(VModuleKey) { 145 return llvm::make_unique<SectionMemoryManager>(); 146 } 147 148We begin with the ExecutionSession member, ``ES``, which provides context for 149our running JIT'd code. It holds the string pool for symbol names, the global 150mutex that guards the critical sections of JIT operations, error logging 151facilities, and other utilities. For basic use cases such as this, a default 152constructed ExecutionSession is all we will need. We will investigate more 153advanced uses of ExecutionSession in later chapters. Following our 154ExecutionSession we have two ORC *layers*: an RTDyldObjectLinkingLayer and an 155IRCompileLayer. We will be talking more about layers in the next chapter, but 156for now you can think of them as analogous to LLVM Passes: they wrap up useful 157JIT utilities behind an easy to compose interface. The first layer, ObjectLayer, 158is the foundation of our JIT: it takes in-memory object files produced by a 159compiler and links them on the fly to make them executable. This 160JIT-on-top-of-a-linker design was introduced in MCJIT, however the linker was 161hidden inside the MCJIT class. In ORC we expose the linker so that clients can 162access and configure it directly if they need to. In this tutorial our 163ObjectLayer will just be used to support the next layer in our stack: the 164CompileLayer, which will be responsible for taking LLVM IR, compiling it, and 165passing the resulting in-memory object files down to the object linking layer 166below. Our ObjectLayer is constructed with a reference to the ExecutionSession 167and the getMemoryMgr utility function, which it uses to generate a new memory 168manager for each object file as it is added. Next up is our CompileLayer, which 169is initialized with a reference to the ExecutionSession, a reference to the 170ObjectLayer (where it will send the objects produced by the compiler), and an IR 171compiler instance. In this case we are using the ConcurrentIRCompiler class 172which is constructed with a JITTargetMachineBuilder and can be called to compile 173IR concurrently from several threads (though in this chapter we will only use 174one). 175 176Following the ExecutionSession and layers we have three supporting member 177variables. The DataLayout, ``DL``; and MangleAndInterner, ``Mangle`` members are 178used to support portable lookups based on IR symbol names (more on that when we 179get to our ``lookup`` function below), and the ThreadSafeContext member, 180``Ctx``, manages an LLVMContext that can be used while building IR Modules for 181the JIT. 182 183After that, we have two static utility functions. The ``getJTMB()`` function 184returns a JITTargetMachineBuilder, which is a factory for building LLVM 185TargetMachine instances that are used by the compiler. In this first tutorial we 186will only need one (implicitly created) TargetMachine, but in future tutorials 187that enable concurrent compilation we will need one per thread. This is why we 188use a target machine builder, rather than a single TargetMachine. (note: Older 189LLVM JIT APIs that did not support concurrent compilation were constructed with 190a single TargetMachines). The ``getMemoryMgr()`` function constructs instances 191of RuntimeDyld::MemoryManager, and is used by the linking layer to generate a 192new memory manager for each object file. 193 194.. code-block:: c++ 195 196 public: 197 198 KaleidoscopeJIT() { 199 ES.getMainJITDylib().setGenerator( 200 cantFail(DynamicLibrarySearchGenerator::GetForCurrentProcess(DL))); 201 } 202 203 const DataLayout &getDataLayout() const { return DL; } 204 205 LLVMContext &getContext() { return *Ctx.getContext(); } 206 207Next up we have our class constructor. Our members have already been 208initialized, so the one thing that remains to do is to tweak the configuration 209of the *JITDylib* that we will store our code in. We want to modify this dylib 210to contain not only the symbols that we add to it, but also the symbols from 211our REPL process as well. We do this by attaching a 212``DynamicLibrarySearchGenerator`` instance using the 213``DynamicLibrarySearchGenerator::GetForCurrentProcess`` method. 214 215Following the constructor we have the ``getDataLayout()`` and ``getContext()`` 216methods. These are used to make data structures created and managed by the JIT 217(especially the LLVMContext) available to the REPL code that will build our 218IR modules. 219 220.. code-block:: c++ 221 222 void addModule(std::unique_ptr<Module> M) { 223 cantFail(CompileLayer.add(ES.getMainJITDylib(), 224 ThreadSafeModule(std::move(M), Ctx))); 225 } 226 227 Expected<JITEvaluatedSymbol> lookup(StringRef Name) { 228 return ES.lookup({&ES.getMainJITDylib()}, Mangle(Name.str())); 229 } 230 231Now we come to the first of our JIT API methods: addModule. This method is 232responsible for adding IR to the JIT and making it available for execution. In 233this initial implementation of our JIT we will make our modules "available for 234execution" by adding them to the CompileLayer, which will it turn store the 235Module in the main JITDylib. This process will create new symbol table entries 236in the JITDylib for each definition in the module, and will defer compilation of 237the module until any of its definitions is looked up. Note that this is not lazy 238compilation: just referencing a definition, even if it is never used, will be 239enough to trigger compilation. In later chapters we will teach our JIT to defer 240compilation of functions until they're actually called. To add our Module we 241must first wrap it in a ThreadSafeModule instance, which manages the lifetime of 242the Module's LLVMContext (our Ctx member) in a thread-friendly way. In our 243example, all modules will share the Ctx member, which will exist for the 244duration of the JIT. Once we switch to concurrent compilation in later chapters 245we will use a new context per module. 246 247Our last method is ``lookup``, which allows us to look up addresses for 248function and variable definitions added to the JIT based on their symbol names. 249As noted above, lookup will implicitly trigger compilation for any symbol 250that has not already been compiled. Our lookup method calls through to 251`ExecutionSession::lookup`, passing in a list of dylibs to search (in our case 252just the main dylib), and the symbol name to search for, with a twist: We have 253to *mangle* the name of the symbol we're searching for first. The ORC JIT 254components use mangled symbols internally the same way a static compiler and 255linker would, rather than using plain IR symbol names. This allows JIT'd code 256to interoperate easily with precompiled code in the application or shared 257libraries. The kind of mangling will depend on the DataLayout, which in turn 258depends on the target platform. To allow us to remain portable and search based 259on the un-mangled name, we just re-produce this mangling ourselves using our 260``Mangle`` member function object. 261 262This brings us to the end of Chapter 1 of Building a JIT. You now have a basic 263but fully functioning JIT stack that you can use to take LLVM IR and make it 264executable within the context of your JIT process. In the next chapter we'll 265look at how to extend this JIT to produce better quality code, and in the 266process take a deeper look at the ORC layer concept. 267 268`Next: Extending the KaleidoscopeJIT <BuildingAJIT2.html>`_ 269 270Full Code Listing 271================= 272 273Here is the complete code listing for our running example. To build this 274example, use: 275 276.. code-block:: bash 277 278 # Compile 279 clang++ -g toy.cpp `llvm-config --cxxflags --ldflags --system-libs --libs core orcjit native` -O3 -o toy 280 # Run 281 ./toy 282 283Here is the code: 284 285.. literalinclude:: ../../examples/Kaleidoscope/BuildingAJIT/Chapter1/KaleidoscopeJIT.h 286 :language: c++ 287 288.. [1] Actually we use a cut-down version of KaleidoscopeJIT that makes a 289 simplifying assumption: symbols cannot be re-defined. This will make it 290 impossible to re-define symbols in the REPL, but will make our symbol 291 lookup logic simpler. Re-introducing support for symbol redefinition is 292 left as an exercise for the reader. (The KaleidoscopeJIT.h used in the 293 original tutorials will be a helpful reference). 294 295.. [2] +-----------------------------+-----------------------------------------------+ 296 | File | Reason for inclusion | 297 +=============================+===============================================+ 298 | JITSymbol.h | Defines the lookup result type | 299 | | JITEvaluatedSymbol | 300 +-----------------------------+-----------------------------------------------+ 301 | CompileUtils.h | Provides the SimpleCompiler class. | 302 +-----------------------------+-----------------------------------------------+ 303 | Core.h | Core utilities such as ExecutionSession and | 304 | | JITDylib. | 305 +-----------------------------+-----------------------------------------------+ 306 | ExecutionUtils.h | Provides the DynamicLibrarySearchGenerator | 307 | | class. | 308 +-----------------------------+-----------------------------------------------+ 309 | IRCompileLayer.h | Provides the IRCompileLayer class. | 310 +-----------------------------+-----------------------------------------------+ 311 | JITTargetMachineBuilder.h | Provides the JITTargetMachineBuilder class. | 312 +-----------------------------+-----------------------------------------------+ 313 | RTDyldObjectLinkingLayer.h | Provides the RTDyldObjectLinkingLayer class. | 314 +-----------------------------+-----------------------------------------------+ 315 | SectionMemoryManager.h | Provides the SectionMemoryManager class. | 316 +-----------------------------+-----------------------------------------------+ 317 | DataLayout.h | Provides the DataLayout class. | 318 +-----------------------------+-----------------------------------------------+ 319 | LLVMContext.h | Provides the LLVMContext class. | 320 +-----------------------------+-----------------------------------------------+ 321