Table of Contents
-
Introduction
- Compiler and Runtime System Project
- Why Compiler or Runtime System Design?
- Overall Learning Goals
- Getting Started
-
Overview
- General Architectures
- Compiler Structure
- Runtime System Structure
-
Programming Language
- Language Specification
- Syntax Specification
- Extended Backus-Naur Form
- EBNF for Arithmetic Expressions
- Problematic Syntax
- Special EBNF Features
- Other Syntax Notations
- Syntax Summary
- Semantic Specification
- Our Programming Language J0
- Project Instructions
-
Lexer
- Task of a Lexer
- Tokens
- Regular Languages
- An Excursion in Language Theory
- Lexing Based on Finite Automaton
- Maximum Munch
- White Spaces
- Comments
- Token Representation
- The Lexer Implementation
- Scanning Integers
- Handling the Minimum Integer Literal
- Scanning Identifiers and Keywords
- Skipping Comments
- Scanning String Literals
- Error Handling
- Lexer Generators
- Project Instructions
-
Parser
- Context-Free Languages
- Task of a Parser
- Parse Tree
- Abstract Syntax Tree
- Parsing Strategies
- Recursive Descent Parser
- The Parser Implementation
- Predictive Direct Parsing
- The Lexer Implementation
- Parser Classification
- Parser Generators
- Abstract Syntax Tree Design
- Syntax Tree Construction
- Syntax Error Handling
- Undetected Errors in the Parser
- Syntax-Directed Translation
- Powerfulness of LR-Parsers
- Building an SLR-Parser
-
Bottom-Up Parsing
- Adjusted Grammar
- State Machine
- Constructing the Parsing Table
- Running the Bottom-Up Parser
- Project Instructions
-
Semantic Checker
- Task of a Semantic Checker
- Symbol Table
- Shadowing
- Local Variable Scopes
- Symbol Table Design
- Predefined Declarations
- Semantic Checker Resolution
- Symbol Table Construction
- Type Resolution in Symbol Table
- Name Resolution
- Designator Resolution in the AST
- Type Resolution in AST
- Visitor-Based Type Resolution
- Semantic Checks
- Checking Declarations
- Method Calls
- Type Checking
- Reserved Type and Constant Names
- Unique Declarations
- Dynamic Rules
- Intermediate Representation
- Project Instructions
-
Code Generator
- Compiler Frontend and Backend
- Task of Code Generator
- Targeting a Virtual Machine
- Stack Processor
- Instruction Set
- Control Flow
- Metadata
- Bytecode Generation
- Bytecode Assembler
- Template-Based Code Generation
- Translating Structured Statements
- Code-Generation Implementation
- Conditional Evaluation
- Method Calls
- Potential Optimizations
- Project Instructions
-
Code Optimization
- Task of an Optimizer
- Arithmetic Optimization
- Algebraic Simplification
- Moving Loop-Invariant Code
- Common Subexpression Elimination
- Dead Code Elimination
- Copy Propagation
- Constant Propagation
- Partial Redundancy Elimination
- Optimization Techniques
- Static Single Assignment
- Peephole Optimization
-
Dataflow Analysis
- Control Flow Graph
- Dataflow Computation
- Application to Constant Propagation
- Backwards Analysis
- Dataflow Analysis Classification
- Summary
- Project Instructions
-
Virtual Machine & Interpretation
- Virtual Machine
- Virtual Machine Design
- Loader
- Verifier
- Descriptors
- Code Patching
- VM Implementation
- Interpreter
- Procedural Support
- Managed Call Stack
- Unmanaged Call Stack
- Runtime Structures
- Security and Safety Measures
- Interpretation versus Compilation
- Project Instructions
-
Object-Oriented Runtime Support
- Compiler Support for Objects
- Out-Of-Scope Features
- Heap Management
- Object References
- Native Memory Access
- Object Layout
- Object-Specific Interpretation
- Array Support
- Simple Heap Design
- Upcoming Object-Oriented Support
- Project Instructions
-
Inheritance and Type Polymorphism
- Single Inheritance
- Code Reuse
- Type Polymorphism
- Efficient Type Tests and Casts
- Ancestor Tables
- Virtual Method Calls
- Virtual Tables
- Interface Polymorphism
- Multi-Inheritance
- Project Instructions
-
Garbage Collection
- Explicit Deallocation
- Dangling Pointer
- Memory Leak
- Definition of Garbage
- Reference Counting
- Garbage Collector
- Transitive Reachability
- Root Set
- Mark & Sweep Algorithm
- GC Implementation
- GC Trigger
- Stop-And-Go GC
- Root Set Collection
- Mark Flag
- Block Pointer Offsets
- GC Memory Footprint
- Free List
- Segregated Free Lists
- External Fragmentation
- Compacting GC
- Finalizers
- Resurrection
- Finalizer Implementation
- Finalizer Problems
- Weak References
- Incremental Garbage Collection
- Generational GC
- Partitioned GC
- Garbage Collection in C++?
- Project Instructions
-
Just-In-Time Compiler
- Task of the JIT-Compiler
- Hot Spots
- Profiling
- Intel 64 Architecture
- Instruction Set
- Cross-Compilation
- Template-Based Code Generation
- Register Allocation
- Local Register Allocation
- Register Clobbering
- Branch Instructions
- Global Register Allocation
- JIT-Compiler Implementation
- Allocation Consistency on Branches
- Register Pressure
- Optimal Global Register Allocation
- Assembler and Linker
- Native Stack Management
- Native Code Execution
- Other JIT-Compiler Aspects
- Project Instructions
-
Conclusion
- Out-of-Scope Topics
- Review of the Learning Goals
- Final Remark
- Appendix A: J0 Language Specification
- Appendix B: J0 Bytecode Specification
- Appendix C: AntLR 4 Grammar for J0
- Bibliography
- Index