├── .gitignore ├── CMakeLists.txt ├── skeleton ├── CMakeLists.txt └── Skeleton.cpp ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | build 2 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.4) 2 | project(llvm-pass-tutorial) 3 | 4 | # we need LLVM_HOME in order to automatically set LLVM_DIR 5 | if(NOT DEFINED ENV{LLVM_HOME}) 6 | message(FATAL_ERROR "$LLVM_HOME is not defined") 7 | else () 8 | set(ENV{LLVM_DIR} $ENV{LLVM_HOME}/lib/cmake/llvm) 9 | endif() 10 | 11 | find_package(LLVM REQUIRED CONFIG) 12 | add_definitions(${LLVM_DEFINITIONS}) 13 | include_directories(${LLVM_INCLUDE_DIRS}) 14 | link_directories(${LLVM_LIBRARY_DIRS}) 15 | if (${LLVM_VERSION_MAJOR} VERSION_GREATER_EQUAL 10) 16 | set(CMAKE_CXX_STANDARD 14) 17 | endif () 18 | 19 | add_subdirectory(skeleton) # Use your pass name here. 20 | -------------------------------------------------------------------------------- /skeleton/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(SkeletonPass MODULE 2 | # List your source files here. 3 | Skeleton.cpp 4 | ) 5 | 6 | # Use C++11 to compile your pass (i.e., supply -std=c++11). 7 | target_compile_features(SkeletonPass PRIVATE cxx_range_for cxx_auto_type) 8 | 9 | # LLVM is (typically) built with no C++ RTTI. We need to match that; 10 | # otherwise, we'll get linker errors about missing RTTI data. 11 | set_target_properties(SkeletonPass PROPERTIES 12 | COMPILE_FLAGS "-fno-rtti" 13 | ) 14 | 15 | # Get proper shared-library behavior (where symbols are not necessarily 16 | # resolved when the shared library is linked) on OS X. 17 | if(APPLE) 18 | set_target_properties(SkeletonPass PROPERTIES 19 | LINK_FLAGS "-undefined dynamic_lookup" 20 | ) 21 | endif(APPLE) 22 | -------------------------------------------------------------------------------- /skeleton/Skeleton.cpp: -------------------------------------------------------------------------------- 1 | #include "llvm/Pass.h" 2 | #include "llvm/IR/Function.h" 3 | #include "llvm/Support/raw_ostream.h" 4 | #include "llvm/IR/LegacyPassManager.h" 5 | #include "llvm/Transforms/IPO/PassManagerBuilder.h" 6 | using namespace llvm; 7 | 8 | namespace { 9 | struct SkeletonPass : public FunctionPass { 10 | static char ID; 11 | SkeletonPass() : FunctionPass(ID) {} 12 | 13 | virtual bool runOnFunction(Function &F) { 14 | errs() << "I saw a function called " << F.getName() << "!\n"; 15 | return false; 16 | } 17 | }; 18 | } 19 | 20 | char SkeletonPass::ID = 0; 21 | 22 | // Automatically enable the pass. 23 | // http://adriansampson.net/blog/clangpass.html 24 | static void registerSkeletonPass(const PassManagerBuilder &, 25 | legacy::PassManagerBase &PM) { 26 | PM.add(new SkeletonPass()); 27 | } 28 | static RegisterStandardPasses 29 | RegisterMyPass(PassManagerBuilder::EP_EarlyAsPossible, 30 | registerSkeletonPass); 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Based on code from Adrian Sampson 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2015 Adrian Sampson 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ## At a glance ## 3 | A step-by-step tutorial for building an out-of-source LLVM pass based on 4 | Adrian Sampson's "LLVM for Grad Students" 5 | 6 | ## Setup ## 7 | 8 | LLVM is an umbrella project for building compilers 9 | and code transformation tools. It consists of several sub-projects like Clang, 10 | LLD and, confusingly enough, the LLVM sub-project. We consider in this tutorial: 11 | - Building the LLVM *sub-project* from source 12 | - Building a trivial out-of-source LLVM pass. 13 | 14 | We will be building LLVM v`10.0.0` which is the latest as of this writing. 15 | We assume that you have a working compiler toolchain (GCC or LLVM) and that CMake is installed (minimum version 3.4). 16 | 17 | 18 | ## Compiling LLVM ## 19 | Compiling LLVM from source is mandatory if you are developing an in-source pass (within LLVM source tree). 20 | It can also be convenient in the case of developing out-of-source passes as it gives you full control over the compilation options. 21 | For example, a debug build of LLVM is much more pleasant to work with compared to an optimized one. To compile LLVM, please follow the following steps: 22 | 23 | 1. Download LLVM [source](http://llvm.org/releases/) 24 | and unpack it in a directory of your choice which will refer to as `[LLVM_SRC]` 25 | 26 | 2. Create a separate build directory 27 | ```bash 28 | $ mkdir llvm-build 29 | $ cd llvm-build 30 | ``` 31 | 3. Instruct CMake to detect and configure your build environment: 32 | 33 | ```bash 34 | $ cmake -DCMAKE_BUILD_TYPE=Debug -DLLVM_TARGETS_TO_BUILD=X86 [LLVM_SRC] 35 | ``` 36 | Note that we instructed cmake to only build `X86` backend. 37 | You can choose a different backend if needed. If you do not specify `LLVM_TARGETS_TO_BUILD`, 38 | then all supported backends will be built by default which requires more time. 39 | 40 | 4. Now start the actual compilation within your build directory 41 | 42 | ```bash 43 | $ cmake --build . 44 | ``` 45 | The `--build` option is a portable why to tell cmake to invoke the underlying 46 | build tool (make, ninja, xcodebuild, msbuild, etc.) 47 | 48 | 5. Building takes some time to finish. After that you can install LLVM in its default directory which is `/usr/local` 49 | ```bash 50 | $ cmake --build . --target install 51 | ``` 52 | Alternatively, it's possible to set a different install directory `[LLVM_HOME]`. 53 | Since we will need `[LLVM_HOME]` in the next stage, we assume that you have defined 54 | it as an environment variable `$LLVM_HOME`. Now you can issue the following command 55 | ```bash 56 | $ cmake -DCMAKE_INSTALL_PREFIX=$LLVM_HOME -P cmake_install.cmake 57 | ``` 58 | Note that `$LLVM_HOME` must __not__ contain `~` (tilde) to refer to your home directory 59 | as it won't be expanded. Use `$HOME` or an absolute path instead. 60 | 61 | ## Building a trivial LLVM pass ## 62 | 63 | To build the skeleton LLVM pass found in `skeleton` folder: 64 | ```bash 65 | $ cd llvm-pass-tutorial 66 | $ mkdir build 67 | $ cd build 68 | $ cmake .. 69 | $ make 70 | ``` 71 | `cmake` needs to find its LLVM configurations in `[LLVM_DIR]`. We automatically 72 | setup `[LLVM_DIR]` based on `$LLVM_HOME` for you. Now the easiest way to run the skeleton pass is to use Clang: 73 | ```bash 74 | $ clang-7.0 -Xclang -load -Xclang build/skeleton/libSkeletonPass.* something.c$ 75 | ``` 76 | Note that Clang is the compiler front-end of the LLVM project. 77 | It can be installed separately in binary form. 78 | 79 | ### Further resources 80 | This tutorial is based on the following resources 81 | 82 | - Adrian Sampson's blog entry "LLVM for Grad Students" ([link](http://adriansampson.net/blog/llvm.html)) 83 | - LLVM documentation: Writing an LLVM pass ([link](http://llvm.org/docs/WritingAnLLVMPass.html)) 84 | - LLVM documentation: Building LLVM with CMake ([link](http://llvm.org/docs/CMake.html#cmake-out-of-source-pass)) 85 | --------------------------------------------------------------------------------