Designing and Implementing a Production Compiler with Rust
Introduction
- From Machine Code to High-Level Languages
- The Compilation Pipeline in One Picture
- Compilers, Interpreters and JITs
- Why Build Your Own Compiler?
- How This Book Is Structured
Chapter 1: What Is a Compiler?
- The Compiler as Translation Engine
- The Modular Architecture
- A Concrete Example
- Compilers as Complex Systems
- The Compiler Landscape Today
- The Lumina Reference Compiler
- Prerequisites and Conventions
- The Journey Ahead
Chapter 2: Compiler Architecture
- The Need for Modular Design
- Phases and Representations
- The Lumina Pipeline Architecture
- Error Handling as a First-Class Concern
- Frontend-IR and Backend Separation
- The Lumina Build System and Project Layout
- Design Trade-offs in Compiler Architecture
- Summary
Chapter 3: Language Design for Implementation
- Language Design and Compiler Complexity
- Syntax Design Choices
- Type System Implications
- Memory Model and Ownership
- Evaluation Strategy and Semantics
- Standard Library and Runtime Expectations
- The Lumina Language Specification
- Implementation Language: Why Rust
- Summary
Chapter 4: Lexical Analysis
- The Role of the Lexer
- Token Types and Lexical Rules
- Building a Hand-Written Lexer
- Understanding the Lexer Code
- Error Handling in Lexical Analysis
- Lexer vs. Parser Responsibilities
- Lexer Engineering and Whitespace Handling
- Testing the Lexer
- Summary
Chapter 5: Parsing Fundamentals
- From Tokens to Structure
- Context-Free Grammars and Syntax
- LL vs LR Parsing
- Recursive Descent Parsing
- Parser Combinators vs Hand-Written
- Error Recovery in Parsing
- Implementing Lumina Parse with Recursive Descent
- Understanding the Parser Code
- Summary
Chapter 6: Abstract Syntax Trees
- Concrete Syntax Trees vs Abstract Syntax Trees
- AST Node Design and Representation
- Type Safety and Pattern Matching
- Source Location Tracking
- Desugaring and Pre-Transformation
- Implementing Lumina AST
- AST Traversal Patterns
- Summary
Chapter 7: Semantic Analysis and Symbol Tables
- What Semantic Analysis Does
- Symbol Tables and Scope
- Name Resolution Algorithms
- Declarations and Definitions
- Shadowing and Visibility Rules
- Semantic Errors and Diagnostics
- Implementing Lumina Semantic Analysis
- Understanding the Semantic Analyzer
- Summary
Chapter 8: Type Systems and Type Checking
- Static vs Dynamic Typing
- Type Checking Algorithms
- Type Inference vs Type Annotation
- Type Errors and Suggestions
- Implementing Lumina Type Checker
- Summary
Chapter 9: Intermediate Representations
- Why Intermediate Representations?
- Three-Address Code and SSA
- High-Level vs Low-Level IRs
- IR Design Principles
- Implementing Lumina IR
- Lowering AST to IR
- Summary
Chapter 10: Control Flow Graphs
- Basic Blocks and Control Flow
- Building Control Flow Graphs
- Dominators and Post-Dominators
- Natural Loops and Loop Headers
- CFG Optimization
- Implementing Lumina CFG
- Summary
Chapter 11: Static Single Assignment
- SSA and Its Benefits
- Phi Functions and Versioning
- SSA Construction Algorithms
- Sparse Conditional Constant Propagation
- Optimizing SSA Form
- Implementing Lumina SSA
- Summary
Chapter 12: Data Flow Analysis
- Data Flow Analysis Fundamentals
- Reaching Definitions and Available Expressions
- Live Variable Analysis
- Interprocedural Analysis
- Analysis Precision and Performance
- Implementing Lumina Data Flow
- Summary
Chapter 13: Core Optimizations
- The Optimization Framework
- Dead Code Elimination
- Constant Propagation and Folding
- Copy Propagation
- Common Subexpression Elimination
- Summary
Chapter 14: Loop Optimizations
- Loop Optimization Opportunities
- Loop-Invariant Code Motion
- Strength Reduction
- Induction Variable Elimination
- Loop Unrolling and Peeling
- Implementing Lumina Loop Optimizations
- Summary
Chapter 15: Advanced Optimizations
- Function Inlining Strategies
- Escape Analysis
- Tail Call Optimization
- Algebraic Simplification
- Profile-Guided Optimization
- Implementing Lumina Inliner
- Summary
Chapter 16: Instruction Selection
- The Instruction Selection Problem
- Tree-Pattern Matching
- Instruction Scheduling
- Peephole Optimization
- Lowering for x86-64
- Implementing Lumina Instruction Selection
- Summary
Chapter 17: Register Allocation
- Register Allocation Problems
- Graph Coloring Algorithms
- Linear Scan Allocation
- Spilling Strategies
- Register Pressure
- Implementing Lumina Register Allocator
- Summary
Chapter 18: Code Generation and Assembly
- Assembly Language and Encoding
- Machine Code Generation
- Relocations and Symbols
- ABI and Calling Conventions
- Emitting ELF Object Files
- Implementing Lumina Code Generator
- Summary
Chapter 19: Linking and Loading
- The Linker’s Job
- Static vs Dynamic Linking
- Symbol Resolution and Relocation
- Link-Time Optimization
- The Loader and Dynamic Linking
- Integrating Lumina with the Toolchain
- Summary
Chapter 20: Runtime Support
- What Compilers Need from Runtimes
- Initialization and Finalization
- Standard Library Design
- Error Handling and Panics
- Memory Management Patterns
- Building Lumina Runtime
- Summary
Chapter 21: Diagnostics and Debugging
- Error Message Design
- Source Maps and Location
- Diagnostic Suggestions
- Debug Information: DWARF
- Debugging the Compiler
- Implementing Lumina Diagnostics
- Summary
Chapter 22: JIT Compilation
- When and Why JIT?
- Compilation at Runtime
- Tiered Compilation
- Deoptimization
- LLVM ORC and Modern JIT Infrastructure
- JIT Design for Lumina
- Summary
Chapter 23: Incremental and Parallel Compilation
- The Incremental Compilation Problem
- Incremental Dependency Tracking
- Query-Based Incremental Systems
- Parallel Compilation
- Distributed Compilation
- Making Lumina Fast
- Summary
Chapter 24: Compiler Testing and Verification
- Compiler Testing Strategies
- Unit Testing Compiler Components
- End-to-End and Regression Tests
- Compiler Fuzzing
- Formal Verification of Compilers
- Testing Lumina
- Summary
Chapter 25: Performance Engineering
- Profiling Compiler Performance
- Compiler Memory Usage
- Compilation Time Optimizations
- Cache Efficiency in Compilers
- Benchmarking the Compiler
- Profiling Lumina Compilation
- Summary
Chapter 26: Compiler Frameworks and Ecosystems
- LLVM Architecture and Use Cases
- GCC: The Veteran Toolkit
- MLIR: Multilevel Intermediate Representation
- Cranelift for WebAssembly
- Parser Generators: ANTLR, LALRPOP, Tree-Sitter
- Choosing Your Compiler Stack
- Summary
Chapter 27: Hardware Awareness
- CPU Architectures and ISAs
- Instruction Latency and Throughput
- Memory Hierarchy Awareness
- Branch Prediction and Control Flow
- SIMD and Vectorization
- Hardware Features in Lumina
- Summary
Chapter 28: The Complete Lumina Compiler
- Architecture Overview
- Complete Project Structure
- The Compilation Driver
- Complete Lumina Program
- Extending Lumina
- Summary
Chapter 29: Extending and Evolving a Compiler
- Adding Language Features
- Supporting New Platforms
- Scaling the Codebase
- Maintaining Compiler Quality
- Compiler Versioning and Breaking Changes
- Community and Ecosystem
- Summary