290 lines · plain
1====================2Writing an LLVM Pass3====================4 5.. program:: opt6 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 pass15 manager for the codegen pipeline. For more details, see16 :doc:`WritingAnLLVMPass` and :doc:`NewPassManager`.17 18The LLVM pass framework is an important part of the LLVM system, because LLVM19passes are where most of the interesting parts of the compiler exist. Passes20perform the transformations and optimizations that make up the compiler, they21build the analysis results that are used by these transformations, and they22are, above all, a structuring technique for compiler code.23 24Unlike passes under the legacy pass manager where the pass interface is25defined via inheritance, passes under the new pass manager rely on26concept-based polymorphism, meaning there is no explicit interface (see27comments in ``PassManager.h`` for more details). All LLVM passes inherit from28the CRTP mix-in ``PassInfoMixin<PassT>``. The pass should have a ``run()``29method which returns a ``PreservedAnalyses`` and takes in some unit of IR30along with an analysis manager. For example, a function pass would have a31``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 is35always a great way to learn details.36 37Quick Start --- Writing hello world38===================================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 that42exist 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 different46name alongside the HelloWorld source files.47 48.. _writing-an-llvm-npm-pass-build:49 50Setting up the build51--------------------52 53First, configure and build LLVM as described in :doc:`GettingStarted`.54 55Next, we will reuse an existing directory (creating a new directory involves56messing around with more CMake files than we want). For this example, we'll use57``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 into59``llvm/lib/Transforms/Utils/CMakeLists.txt`` (assuming you want your pass in60the ``Transforms/Utils`` directory.61 62Now that we have the build set up for a new pass, we need to write the code63for the pass itself.64 65.. _writing-an-llvm-npm-pass-basiccode:66 67Basic code required68-------------------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 create73``llvm/include/llvm/Transforms/Utils/HelloWorld.h``. The file should74contain the following boilerplate:75 76.. code-block:: c++77 78 #ifndef LLVM_TRANSFORMS_HELLONEW_HELLOWORLD_H79 #define LLVM_TRANSFORMS_HELLONEW_HELLOWORLD_H80 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 llvm91 92 #endif // LLVM_TRANSFORMS_HELLONEW_HELLOWORLD_H93 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 global99namespace.100 101Next we'll create ``llvm/lib/Transforms/Utils/HelloWorld.cpp``, starting102with103 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 llvm115namespace. 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 pass128manager will ensure that the pass will be run on every function in a module.129The ``PreservedAnalyses`` return value says that all analyses (e.g. dominator130tree) 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 need133to add it to a couple places. Add the following to134``llvm/lib/Passes/PassRegistry.def`` in the ``FUNCTION_PASS`` section135 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 into143``llvm/lib/Passes/PassBuilder.cpp`` multiple times for various reasons. Since144it constructs our pass, we need to also add the proper #include in145``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 compile152and 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 use158it to run some LLVM IR through the pass.159 160.. code-block:: console161 162 $ ninja -C build/ opt163 # or whatever build system/build directory you are using164 165 $ cat /tmp/a.ll166 define i32 @foo() {167 %a = add i32 2, 3168 ret i32 %a169 }170 171 define void @bar() {172 ret void173 }174 175 $ build/bin/opt -disable-output /tmp/a.ll -passes=helloworld176 foo177 bar178 179Our pass ran and printed the names of functions as expected!180 181Testing a pass182--------------183 184Testing our pass is important to prevent future regressions. We'll add a lit185test at ``llvm/test/Transforms/Utils/helloworld.ll``. See186:doc:`TestingGuide` for more information on testing.187 188.. code-block:: llvm189 190 $ cat llvm/test/Transforms/Utils/helloworld.ll191 ; RUN: opt -disable-output -passes=helloworld %s 2>&1 | FileCheck %s192 193 ; CHECK: {{^}}foo{{$}}194 define i32 @foo() {195 %a = add i32 2, 3196 ret i32 %a197 }198 199 ; CHECK-NEXT: {{^}}bar{{$}}200 define void @bar() {201 ret void202 }203 204 $ ninja -C build check-llvm205 # runs our new test alongside all other llvm lit tests206 207FAQs208====209 210Required passes211---------------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 required225pass is ``AlwaysInlinerPass``, which must always be run to preserve226``alwaysinline`` semantics. Pass managers are required since they may contain227other required passes.228 229An example of how a pass can be skipped is the ``optnone`` function230attribute, which specifies that optimizations should not be run on the231function. Required passes will still be run on ``optnone`` functions.232 233For more implementation details, see234``PassInstrumentation::runBeforePass()``.235 236Registering passes as plugins237-----------------------------238 239LLVM provides a mechanism to register pass plugins within various tools like240``clang`` or ``opt``. A pass plugin can add passes to default optimization241pipelines 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 alongside245other projects. This project must contain the following minimal246``CMakeLists.txt``:247 248.. code-block:: cmake249 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. Setting261``LLVM_${NAME}_LINK_INTO_TOOLS`` to ``ON`` turns the project into a statically262linked 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