Advanced Topic Recommendations
The course has reached Chapter 3 for now. The topics below go one step beyond the first pass through CSAPP. This list is intentionally short for now and will grow as the course moves forward.
RISC-V
Estimated Difficulty: ⭐⭐
RISC-V is an open instruction-set architecture (ISA), not a particular processor. Its small base instruction set can be combined with extensions for features such as multiplication, atomics, compressed instructions, and vectors. After learning x86-64 assembly, comparing the two ISAs is a useful way to separate ideas that belong to all machines from choices made by one architecture. An especially useful next step is to read the RISC-V calling convention and inspect how a compiler maps function arguments, return values, and stack frames to registers.
For further reading:
- RISC-V ISA Manuals — Ratified Specifications Library
- The RISC-V Unprivileged Architecture
- RISC-V Procedure Calling Convention
LLVM IR
Estimated Difficulty: ⭐⭐⭐
LLVM IR is a typed, low-level intermediate representation between a source
language and target-specific machine code. It uses static single assignment (SSA)
form for register-like values, so data dependencies and control-flow joins are
visible before the compiler chooses physical registers. This makes LLVM IR a good
place to observe what an optimizer changes while keeping the machine details that
matter for code generation. Try comparing the IR produced by clang -S -emit-llvm
at different optimization levels, then relate its load, store, and phi
instructions to the assembly you already know.
For further reading:
- LLVM Language Reference Manual
- My First Language Frontend with LLVM
- The LLVM Target-Independent Code Generator
Register Assignment
Estimated Difficulty: ⭐⭐⭐⭐⭐
Register assignment, usually called register allocation, maps the many temporary values used by a compiler to the small set of physical registers provided by a processor. The compiler tracks when each value is live and tries to keep values whose live ranges overlap in different registers. When the registers are not enough, it spills a value to the stack; calling conventions and instruction constraints add further restrictions. These decisions explain many of the moves, stack accesses, and reused registers that appear in optimized assembly.
For further reading: