Learn LLVM 17: A beginner's guide to learning LLVM compiler tools and core libraries with C++ (2nd Edition) [2 ed.] 9781837631346

Learn how to build and use the complete spectrum of real-world compilers, including the frontend, optimization pipeline,

186 112

English Pages 615 Year 2024

Report DMCA / Copyright

DOWNLOAD FILE

Learn LLVM 17: A beginner's guide to learning LLVM compiler tools and core libraries with C++ (2nd Edition) [2 ed.]
 9781837631346

Table of contents :
Learn LLVM 17
Contributors
About the authors
About the reviewers
Preface
What’s new in this edition
Who this book is for
What this book covers
To get the most out of this book
Download the example code files
Conventions used
Get in touch
Share Your Thoughts
Download a free PDF copy of this book
Part 1: The Basics of Compiler Construction with LLVM
Chapter 1: Installing LLVM
Compiling LLVM versus installing binaries
Getting the prerequisites ready
Ubuntu
Fedora and RedHat
FreeBSD
OS X
Windows
Cloning the repository and building from source
Configuring Git
Cloning the repository
Creating a build directory
Generating the build system files
Compiling and installing LLVM
Customizing the build process
Variables defined by CMake
Using LLVM-defined build configuration variables
Summary
Chapter 2: The Structure of a Compiler
Building blocks of a compiler
An arithmetic expression language
Formalism for specifying the syntax of a programming language
How does grammar help the compiler writer?
Lexical analysis
A hand-written lexer
Syntactical analysis
A hand-written parser
The abstract syntax tree
Semantic analysis
Generating code with the LLVM backend
Textual representation of LLVM IR
Generating the IR from the AST
The missing pieces – the driver and the runtime library
Summary
Part 2: From Source to Machine Code Generation
Chapter 3: Turning the Source File into an Abstract Syntax Tree
Defining a real programming language
Creating the project layout
Managing the input files for the compiler
Handling messages for the user
Structuring the lexer
Constructing a recursive descent parser
Performing semantic analysis
Handling the scope of names
Using an LLVM-style RTTI for the AST
Creating the semantic analyzer
Summary
Chapter 4: Basics of IR Code Generation
Generating IR from the AST
Understanding the IR code
Learning about the load-and-store approach
Mapping the control flow to basic blocks
Using AST numbering to generate IR code in SSA form
Defining the data structure to hold values
Reading and writing values local to a basic block
Searching the predecessor blocks for a value
Optimizing the generated phi instructions
Sealing a block
Creating the IR code for expressions
Emitting the IR code for a function
Controlling visibility with linkage and name mangling
Converting a type from an AST description into LLVM types
Creating the LLVM IR function
Emitting the function body
Setting up the module and the driver
Wrapping all in the code generator
Initializing the target machine class
Emitting assembler text and object code
Summary
Chapter 5: IR Generation for High-Level Language Constructs
Technical requirements
Working with arrays, structs, and pointers
Getting the application binary interface right
Creating IR code for classes and virtual functions
Implementing single inheritance
Extending single inheritance with interfaces
Adding support for multiple inheritance
Summary
Chapter 6: Advanced IR Generation
Throwing and catching exceptions
Raising an exception
Catching an exception
Integrating the exception handling code into the application
Generating metadata for type-based alias analysis
Understanding the need for additional metadata
Creating TBAA metadata in LLVM
Adding TBAA metadata to tinylang
Adding debug metadata
Understanding the general structure of debug metadata
Tracking variables and their values
Adding line numbers
Adding debug support to tinylang
Summary
Chapter 7: Optimizing IR
Technical requirements
The LLVM pass manager
Implementing a new pass
Developing the ppprofiler pass as a plugin
Adding the pass to the LLVM source tree
Using the ppprofiler pass with LLVM tools
Adding an optimization pipeline to your compiler
Creating an optimization pipeline
Extending the pass pipeline
Summary
Part 3: Taking LLVM to the Next Level
Chapter 8: The TableGen Language
Technical requirements
Understanding the TableGen language
Experimenting with the TableGen language
Defining records and classes
Creating multiple records at once with multiclasses
Simulating function calls
Generating C++ code from a TableGen file
Defining data in the TableGen language
Implementing a TableGen backend
Drawbacks of TableGen
Summary
Chapter 9: JIT Compilation
Technical requirements
LLVM’s overall JIT implementation and use cases
Using JIT compilation for direct execution
Exploring the lli tool
Implementing our own JIT compiler with LLJIT
Integrating the LLJIT engine into the calculator
Code generation changes to support JIT compilation via LLJIT
Building an LLJIT-based calculator
Building a JIT compiler class from scratch
Creating a JIT compiler class
Using our new JIT compiler class
Summary
Chapter 10: Debugging Using LLVM Tools
Technical requirements
Instrumenting an application with sanitizers
Detecting memory access problems with the address sanitizer
Finding uninitialized memory accesses with the memory sanitizer
Pointing out data races with the thread sanitizer
Finding bugs with libFuzzer
Limitations and alternatives
Performance profiling with XRay
Checking the source with the clang static analyzer
Adding a new checker to the clang static analyzer
Creating your own clang-based tool
Summary
Part 4: Roll Your Own Backend
Chapter 11: The Target Description
Setting the stage for a new backend
Adding the new architecture to the Triple class
Extending the ELF file format definition in LLVM
Creating the target description
Adding the register definition
Defining the instruction formats and the instruction information
Creating the top-level file for the target description
Adding the M88k backend to LLVM
Implementing the assembler parser
Creating the disassembler
Summary
Chapter 12: Instruction Selection
Defining the rules of the calling convention
Implementing the rules of the calling convention
Instruction selection via the selection DAG
Implementing DAG lowering – handling legal types and setting operations
Implementing DAG lowering – lowering formal arguments
Implementing DAG lowering – lowering return values
Implementing DAG-to-DAG transformations within instruction selection
Adding register and instruction information
Putting an empty frame lowering in place
Emitting machine instructions
Creating the target machine and the sub-target
Implementing M88kSubtarget
Implementing M88kTargetMachine – defining the definitions
Implementing M88kTargetMachine – adding the implementation
Global instruction selection
Lowering arguments and return values
Legalizing the generic machine instructions
Selecting a register bank for operands
Translating generic machine instructions
Running an example
How to further evolve the backend
Summary
Chapter 13: Beyond Instruction Selection
Adding a new machine function pass to LLVM
Implementing the top-level interface for the M88k target
Adding the TargetMachine implementation for machine function passes
Developing the specifics of the machine function pass
Building newly implemented machine function passes
A glimpse of running a machine function pass with llc
Integrating a new target into the clang frontend
Implementing the driver integration within clang
Implementing ABI support for M88k within clang
Implementing the toolchain support for M88k within clang
Building the M88k target with clang integration
Targeting a different CPU architecture
Summary
Index
Why subscribe?
Other Books You May Enjoy
Packt is searching for authors like you
Share Your Thoughts
Download a free PDF copy of this book

Polecaj historie