Quentin Colombet
This is the code repository for LLVM Code Generation, First Edition, published by Packt.
The LLVM infrastructure is a popular compiler ecosystem widely used in the tech industry and academia. This technology is crucial for both experienced and aspiring compiler developers looking to make an impact in the field. Written by Quentin Colombet, a veteran LLVM contributor and architect of the GlobalISel framework, this book provides a primer on the main aspects of LLVM, with an emphasis on its backend infrastructure; that is, everything needed to transform the intermediate representation (IR) produced by frontends like Clang into assembly code and object files. You’ll learn how to write an optimizing code generator for a toy backend in LLVM. The chapters will guide you step by step through building this backend while exploring key concepts, such as the ABI, cost model, and register allocation. You’ll also find out how to express these concepts using LLVM's existing infrastructure and how established backends address these challenges. Furthermore, the book features code snippets that demonstrate the actual APIs. By the end of this book, you’ll have gained a deeper understanding of LLVM. The concepts presented are expected to remain stable across different LLVM versions, making this book a reliable quick reference guide for understanding LLVM.
Navigate in the different chX directory and look at the examples provided and do the exercises when applicable.
Each directory has its own README.md with specific directions.
Note: The exercises have been tested with the open source repository of LLVM at the Git hash 424c2d9b7e4d from February 13th 2025. Which is LLVM 20.1.1.
Some of the exercises interact directly with the LLVM C++ API. This API has no stability guarantee therefore it is possible that newer or older version of LLVM will not work with these exercises.
For the exercices that requires a version of LLVM handy, if you build your own make sure to use the CMAKE_INSTALL_PREFIX cmake variable to set the install path, then build the install target.
Then, you will need to provide this path to CMake in the different exercise.
Follow the READMEs in the different directories when you get there.
Quentin Colombet is a veteran LLVM contributor specializing in compiler backends. He is the architect of the new instruction selection framework (GlobalISel) and code owner of the LLVM register allocators. With over two decades of experience, he has worked on compiler backends for a variety of architectures, including GPU, CPU, microcontrollers, DSP, and ASICs. Quentin joined Apple in 2012 and has contributed to x86, Aarch64, and Apple GPU backends. He is passionate about helping newcomers onboard the LLVM infrastructure, having mentored interns and new hires over the years.
$ git clone https://github.com/llvm/llvm/project.git, the URL should be https://github.com/llvm/llvm-project.git. Therefore, the first line becomes $ git clone https://github.com/llvm/llvm-project.git.$ cmake –GNinja -DCMAKE_C_COMPILER=${BUILD_DIR}/bin/clang ${TESTSUITE_DIR}, – should be replaced with -. In the command $ cmake -GNinja -DCMAKE_C_COMPILER=${BUILD_DIR}/bin/clang -C${TESTSUITE_DIR}/cmake/cache/<specificOption>.cmake ${TESTSUITE_DIR}, cache should be replaced with caches. Same to /cmake/cache/O3.cmake.isCriticalEdge function from the IR library." should be "At the IR level, you can check if an edge is critical using the isCriticalEdge function from the Analysis library.". (Library name is changed from IR to Analysis.)GlobalValue::CommonLinkage", CommonLinkage is actually the one linkage type that doesn't work for functions. Instead, one can use the GlobalValue::ExternalLinkage enum value in this case.res should be declared as int res = 0; after the first line (int foo(int b) {) and before the for loop. Also, in the following diagram, there should be an additional arrow from the top rectangle going to the bottom most rectangle, so that it reflects the case where the loop is not entered and the function directly returns res.getOperand(0) and getOperand(1). In both the lines, getopenand(0) => and getopenand(n) => are to be disregarded.n) is the last/closet node that dominates n.", "closet" should be "closest".AnalysisUsage::setPreserved</*AnalysisPass*/>(), AnalysisUsage::setPreserved should be AnalysisUsage::addPreserved.Function::isTargetIntrinsic not Function::isTargetInstrinsic.%a. The correct value here is two: "the first two least significant bits of %a will be zeros".MCInstrPrinter should be MCInstPrinter.XXXInstrPrinter should be XXXInstPrinter.%vec1 = insertelement <2 x i32> %vec, i32 %a, i32 1 should be %vec1 = insertelement <2 x i32> %vec, i32 %b, i32 1 (i.e. %a should be %b).ReadAdvance and WriteRes classes or instantiations of InstR." should be "The bindings are simple instantiations of the ReadAdvance and WriteRes classes or instantiations of InstRW.". (InstR is changed to InstRW.)such a convention in Figure 20.3., Page 534: take a look at Figure 20.3, Page 536: illustrate it in Figure 20.3., Page 539: Figure 20.3 shows one of the ways, Figure 20.3 shows a simplified view of the stack, all of Figure 20.3 should be Figure 20.2MachineRegisterInfo should be MachineFrameInfo.588 followers · starred Jun 2025
13 followers · starred Jan 2026
62 followers · starred Mar 2026
412 followers · starred Sep 2025
Quentin Colombet
This is the code repository for LLVM Code Generation, First Edition, published by Packt.
The LLVM infrastructure is a popular compiler ecosystem widely used in the tech industry and academia. This technology is crucial for both experienced and aspiring compiler developers looking to make an impact in the field. Written by Quentin Colombet, a veteran LLVM contributor and architect of the GlobalISel framework, this book provides a primer on the main aspects of LLVM, with an emphasis on its backend infrastructure; that is, everything needed to transform the intermediate representation (IR) produced by frontends like Clang into assembly code and object files. You’ll learn how to write an optimizing code generator for a toy backend in LLVM. The chapters will guide you step by step through building this backend while exploring key concepts, such as the ABI, cost model, and register allocation. You’ll also find out how to express these concepts using LLVM's existing infrastructure and how established backends address these challenges. Furthermore, the book features code snippets that demonstrate the actual APIs. By the end of this book, you’ll have gained a deeper understanding of LLVM. The concepts presented are expected to remain stable across different LLVM versions, making this book a reliable quick reference guide for understanding LLVM.
Navigate in the different chX directory and look at the examples provided and do the exercises when applicable.
Each directory has its own README.md with specific directions.
Note: The exercises have been tested with the open source repository of LLVM at the Git hash 424c2d9b7e4d from February 13th 2025. Which is LLVM 20.1.1.
Some of the exercises interact directly with the LLVM C++ API. This API has no stability guarantee therefore it is possible that newer or older version of LLVM will not work with these exercises.
For the exercices that requires a version of LLVM handy, if you build your own make sure to use the CMAKE_INSTALL_PREFIX cmake variable to set the install path, then build the install target.
Then, you will need to provide this path to CMake in the different exercise.
Follow the READMEs in the different directories when you get there.
Quentin Colombet is a veteran LLVM contributor specializing in compiler backends. He is the architect of the new instruction selection framework (GlobalISel) and code owner of the LLVM register allocators. With over two decades of experience, he has worked on compiler backends for a variety of architectures, including GPU, CPU, microcontrollers, DSP, and ASICs. Quentin joined Apple in 2012 and has contributed to x86, Aarch64, and Apple GPU backends. He is passionate about helping newcomers onboard the LLVM infrastructure, having mentored interns and new hires over the years.
$ git clone https://github.com/llvm/llvm/project.git, the URL should be https://github.com/llvm/llvm-project.git. Therefore, the first line becomes $ git clone https://github.com/llvm/llvm-project.git.$ cmake –GNinja -DCMAKE_C_COMPILER=${BUILD_DIR}/bin/clang ${TESTSUITE_DIR}, – should be replaced with -. In the command $ cmake -GNinja -DCMAKE_C_COMPILER=${BUILD_DIR}/bin/clang -C${TESTSUITE_DIR}/cmake/cache/<specificOption>.cmake ${TESTSUITE_DIR}, cache should be replaced with caches. Same to /cmake/cache/O3.cmake.isCriticalEdge function from the IR library." should be "At the IR level, you can check if an edge is critical using the isCriticalEdge function from the Analysis library.". (Library name is changed from IR to Analysis.)GlobalValue::CommonLinkage", CommonLinkage is actually the one linkage type that doesn't work for functions. Instead, one can use the GlobalValue::ExternalLinkage enum value in this case.res should be declared as int res = 0; after the first line (int foo(int b) {) and before the for loop. Also, in the following diagram, there should be an additional arrow from the top rectangle going to the bottom most rectangle, so that it reflects the case where the loop is not entered and the function directly returns res.getOperand(0) and getOperand(1). In both the lines, getopenand(0) => and getopenand(n) => are to be disregarded.n) is the last/closet node that dominates n.", "closet" should be "closest".AnalysisUsage::setPreserved</*AnalysisPass*/>(), AnalysisUsage::setPreserved should be AnalysisUsage::addPreserved.Function::isTargetIntrinsic not Function::isTargetInstrinsic.%a. The correct value here is two: "the first two least significant bits of %a will be zeros".MCInstrPrinter should be MCInstPrinter.XXXInstrPrinter should be XXXInstPrinter.%vec1 = insertelement <2 x i32> %vec, i32 %a, i32 1 should be %vec1 = insertelement <2 x i32> %vec, i32 %b, i32 1 (i.e. %a should be %b).ReadAdvance and WriteRes classes or instantiations of InstR." should be "The bindings are simple instantiations of the ReadAdvance and WriteRes classes or instantiations of InstRW.". (InstR is changed to InstRW.)such a convention in Figure 20.3., Page 534: take a look at Figure 20.3, Page 536: illustrate it in Figure 20.3., Page 539: Figure 20.3 shows one of the ways, Figure 20.3 shows a simplified view of the stack, all of Figure 20.3 should be Figure 20.2MachineRegisterInfo should be MachineFrameInfo.588 followers · starred Jun 2025
13 followers · starred Jan 2026
62 followers · starred Mar 2026
412 followers · starred Sep 2025