1==================== 2Writing an LLVM Pass 3==================== 4 5.. program:: opt 6 7.. contents:: 8 :local: 9 10Introduction --- What is a pass? 11================================ 12 13.. warning:: 14 This document deals with the new pass manager. LLVM uses the legacy pass 15 manager for the codegen pipeline. For more details, see 16 :doc:`WritingAnLLVMPass` and :doc:`NewPassManager`. 17 18The LLVM pass framework is an important part of the LLVM system, because LLVM 19passes are where most of the interesting parts of the compiler exist. Passes 20perform the transformations and optimizations that make up the compiler, they 21build the analysis results that are used by these transformations, and they 22are, above all, a structuring technique for compiler code. 23 24Unlike passes under the legacy pass manager where the pass interface is 25defined via inheritance, passes under the new pass manager rely on 26concept-based polymorphism, meaning there is no explicit interface (see 27comments in ``PassManager.h`` for more details). All LLVM passes inherit from 28the CRTP mix-in ``PassInfoMixin<PassT>``. The pass should have a ``run()`` 29method which returns a ``PreservedAnalyses`` and takes in some unit of IR 30along with an analysis manager. For example, a function pass would have a 31``PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM);`` method. 32 33We start by showing you how to construct a pass, from setting up the build, 34creating the pass, to executing and testing it. Looking at existing passes is 35always a great way to learn details. 36 37Quick Start --- Writing hello world 38=================================== 39 40Here we describe how to write the "hello world" of passes. The "HelloWorld" 41pass is designed to simply print out the name of non-external functions that 42exist in the program being compiled. It does not modify the program at all, 43it just inspects it. 44 45The code below already exists; feel free to create a pass with a different 46name alongside the HelloWorld source files. 47 48.. _writing-an-llvm-npm-pass-build: 49 50Setting up the build 51-------------------- 52 53First, configure and build LLVM as described in :doc:`GettingStarted`. 54 55Next, we will reuse an existing directory (creating a new directory involves 56messing around with more CMake files than we want). For this example, we'll use 57``llvm/lib/Transforms/Utils/HelloWorld.cpp``, which has already been created. 58If you'd like to create your own pass, add a new source file into 59``llvm/lib/Transforms/Utils/CMakeLists.txt`` (assuming you want your pass in 60the ``Transforms/Utils`` directory. 61 62Now that we have the build set up for a new pass, we need to write the code 63for the pass itself. 64 65.. _writing-an-llvm-npm-pass-basiccode: 66 67Basic code required 68------------------- 69 70Now that the build is setup for a new pass, we just have to write it. 71 72First we need to define the pass in a header file. We'll create 73``llvm/include/llvm/Transforms/Utils/HelloWorld.h``. The file should 74contain the following boilerplate: 75 76.. code-block:: c++ 77 78 #ifndef LLVM_TRANSFORMS_HELLONEW_HELLOWORLD_H 79 #define LLVM_TRANSFORMS_HELLONEW_HELLOWORLD_H 80 81 #include "llvm/IR/PassManager.h" 82 83 namespace llvm { 84 85 class HelloWorldPass : public PassInfoMixin<HelloWorldPass> { 86 public: 87 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 88 }; 89 90 } // namespace llvm 91 92 #endif // LLVM_TRANSFORMS_HELLONEW_HELLOWORLD_H 93 94This creates the class for the pass with a declaration of the ``run()`` 95method which actually runs the pass. Inheriting from ``PassInfoMixin<PassT>`` 96sets up some more boilerplate so that we don't have to write it ourselves. 97 98Our class is in the ``llvm`` namespace so that we don't pollute the global 99namespace. 100 101Next we'll create ``llvm/lib/Transforms/Utils/HelloWorld.cpp``, starting 102with 103 104.. code-block:: c++ 105 106 #include "llvm/Transforms/Utils/HelloWorld.h" 107 108... to include the header file we just created. 109 110.. code-block:: c++ 111 112 using namespace llvm; 113 114... is required because the functions from the include files live in the llvm 115namespace. This should only be done in non-header files. 116 117Next we have the pass's ``run()`` definition: 118 119.. code-block:: c++ 120 121 PreservedAnalyses HelloWorldPass::run(Function &F, 122 FunctionAnalysisManager &AM) { 123 errs() << F.getName() << "\n"; 124 return PreservedAnalyses::all(); 125 } 126 127... which simply prints out the name of the function to stderr. The pass 128manager will ensure that the pass will be run on every function in a module. 129The ``PreservedAnalyses`` return value says that all analyses (e.g. dominator 130tree) are still valid after this pass since we didn't modify any functions. 131 132That's it for the pass itself. Now in order to "register" the pass, we need 133to add it to a couple places. Add the following to 134``llvm/lib/Passes/PassRegistry.def`` in the ``FUNCTION_PASS`` section 135 136.. code-block:: c++ 137 138 FUNCTION_PASS("helloworld", HelloWorldPass()) 139 140... which adds the pass under the name "helloworld". 141 142``llvm/lib/Passes/PassRegistry.def`` is #include'd into 143``llvm/lib/Passes/PassBuilder.cpp`` multiple times for various reasons. Since 144it constructs our pass, we need to also add the proper #include in 145``llvm/lib/Passes/PassBuilder.cpp``: 146 147.. code-block:: c++ 148 149 #include "llvm/Transforms/Utils/HelloWorld.h" 150 151This should be all the code necessary for our pass, now it's time to compile 152and run it. 153 154Running a pass with ``opt`` 155--------------------------- 156 157Now that you have a brand new shiny pass, we can build :program:`opt` and use 158it to run some LLVM IR through the pass. 159 160.. code-block:: console 161 162 $ ninja -C build/ opt 163 # or whatever build system/build directory you are using 164 165 $ cat /tmp/a.ll 166 define i32 @foo() { 167 %a = add i32 2, 3 168 ret i32 %a 169 } 170 171 define void @bar() { 172 ret void 173 } 174 175 $ build/bin/opt -disable-output /tmp/a.ll -passes=helloworld 176 foo 177 bar 178 179Our pass ran and printed the names of functions as expected! 180 181Testing a pass 182-------------- 183 184Testing our pass is important to prevent future regressions. We'll add a lit 185test at ``llvm/test/Transforms/Utils/helloworld.ll``. See 186:doc:`TestingGuide` for more information on testing. 187 188.. code-block:: llvm 189 190 $ cat llvm/test/Transforms/Utils/helloworld.ll 191 ; RUN: opt -disable-output -passes=helloworld %s 2>&1 | FileCheck %s 192 193 ; CHECK: {{^}}foo{{$}} 194 define i32 @foo() { 195 %a = add i32 2, 3 196 ret i32 %a 197 } 198 199 ; CHECK-NEXT: {{^}}bar{{$}} 200 define void @bar() { 201 ret void 202 } 203 204 $ ninja -C build check-llvm 205 # runs our new test alongside all other llvm lit tests 206 207FAQs 208==== 209 210Required passes 211--------------- 212 213A pass that defines a static ``isRequired()`` method that returns true is a required pass. For example: 214 215.. code-block:: c++ 216 217 class HelloWorldPass : public PassInfoMixin<HelloWorldPass> { 218 public: 219 PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); 220 221 static bool isRequired() { return true; } 222 }; 223 224A required pass is a pass that may not be skipped. An example of a required 225pass is ``AlwaysInlinerPass``, which must always be run to preserve 226``alwaysinline`` semantics. Pass managers are required since they may contain 227other required passes. 228 229An example of how a pass can be skipped is the ``optnone`` function 230attribute, which specifies that optimizations should not be run on the 231function. Required passes will still be run on ``optnone`` functions. 232 233For more implementation details, see 234``PassInstrumentation::runBeforePass()``. 235 236Registering passes as plugins 237----------------------------- 238 239LLVM provides a mechanism to register pass plugins within various tools like 240``clang`` or ``opt``. A pass plugin can add passes to default optimization 241pipelines or to be manually run via tools like ``opt``. For more information, 242see :doc:`NewPassManager`. 243 244Create a CMake project at the root of the repo alongside 245other projects. This project must contain the following minimal 246``CMakeLists.txt``: 247 248.. code-block:: cmake 249 250 add_llvm_pass_plugin(MyPassName source.cpp) 251 252See the definition of ``add_llvm_pass_plugin`` for more CMake details. 253 254The pass must provide at least one of two entry points for the new pass manager, 255one for static registration and one for dynamically loaded plugins: 256 257- ``llvm::PassPluginLibraryInfo get##Name##PluginInfo();`` 258- ``extern "C" ::llvm::PassPluginLibraryInfo llvmGetPassPluginInfo() LLVM_ATTRIBUTE_WEAK;`` 259 260Pass plugins are compiled and linked dynamically by default. Setting 261``LLVM_${NAME}_LINK_INTO_TOOLS`` to ``ON`` turns the project into a statically 262linked extension. 263 264For an in-tree example, see ``llvm/examples/Bye/``. 265 266To make ``PassBuilder`` aware of statically linked pass plugins: 267 268.. code-block:: c++ 269 270 // Declare plugin extension function declarations. 271 #define HANDLE_EXTENSION(Ext) llvm::PassPluginLibraryInfo get##Ext##PluginInfo(); 272 #include "llvm/Support/Extension.def" 273 274 ... 275 276 // Register plugin extensions in PassBuilder. 277 #define HANDLE_EXTENSION(Ext) get##Ext##PluginInfo().RegisterPassBuilderCallbacks(PB); 278 #include "llvm/Support/Extension.def" 279 280To make ``PassBuilder`` aware of dynamically linked pass plugins: 281 282.. code-block:: c++ 283 284 // Load plugin dynamically. 285 auto Plugin = PassPlugin::Load(PathToPlugin); 286 if (!Plugin) 287 report_error(); 288 // Register plugin extensions in PassBuilder. 289 Plugin.registerPassBuilderCallbacks(PB); 290