• ↑↓ to navigate
  • ↵ to open
  • ⟶ to select
  • ⌘ ⌥ ↵ to open in a panel
  • ←→ to navigate
  • esc to dismiss
⌘ '
keyboard shortcuts

The Problem

Compiler phases produce intermediate data (tokens, parse trees, IR) that must be stored between phases. Reading and writing this intermediate data to memory or disk has a cost. The compiler designer must decide how many times to scan the program and how much intermediate data to materialize.

Core Idea

A pass is a complete scan of the input (source code or intermediate representation) by a compiler. A single-pass compiler processes the source code once, combining multiple phases into one scan. A multi-pass compiler makes multiple scans, materializing intermediate representations between passes.

How It Works

In a single-pass compiler, lexical analysis, syntax analysis, and code generation are interleaved. As the parser recognizes a construct, it emits code immediately. In a multi-pass compiler, each phase runs as a separate pass, writing its output to a file or memory structure that the next pass reads. Pascal uses a single pass; C uses multiple passes.

Visual Explanation

compiler_pass cluster_single Single-Pass Compiler cluster_multi Multi-Pass Compiler S1 Source Code SPass One Pass (Lex + Syn + CodeGen) S1->SPass SOut Target Code SPass->SOut M1 Source Code Pass1 Pass 1 (Lex + Syn) M1->Pass1 IR1 IR File Pass1->IR1 Pass2 Pass 2 (Opt + Gen) IR1->Pass2 MOut Target Code Pass2->MOut

Key Properties

  • Single-pass: Faster compilation, less memory, tighter coupling of phases
  • Multi-pass: Better code quality, modular compiler design, supports optimization
  • Language constraints: Some languages require multi-pass (forward references, C requires seeing struct definitions before use)
  • Intermediate files: Multi-pass compilers read/write intermediate representation between passes

Semantic Network

semantic_Compiler_Pass THIS Compiler Pass REL1 Related Concept THIS--REL1 related REL2 Builds Into THIS--REL2 builds into

Connections

Edge Cases & Gotchas

  • Hybrid approaches: Modern compilers like GCC and LLVM are multi-pass but use efficient in-memory IR, not files between passes
  • Pascal is single-pass: Pascal was designed specifically to allow single-pass compilation — no forward references without explicit forward declaration
  • Multi-pass enables optimization: Dead code elimination, constant propagation, and loop transformations all require multiple passes to analyze