What Compiler Outputs and Intermediate Representations Can You Inspect on Compiler Explorer?

Updated

Compiler Explorer (rust.godbolt.org) is an interactive online compiler that shows the assembly output of compiled code, and it also exposes a much wider set of compiler outputs and intermediate representations. For Rust specifically, you can inspect Rust HIR, Rust MIR, and Rust macro expansion in addition to the final assembly. For C, C++, and other LLVM-based languages, the tool offers LLVM IR, ClangIR, preprocessor output, and AST views. GCC-based compilers add GIMPLE, Tree/RTL, and optimization pass dumps. The exact set of available views depends on the selected language and compiler, and some tools are disabled when the current language or compiler does not support them.

Core output views

These are the outputs most users start with, and they are available across many language/compiler combinations.

View What it shows Typical use
Assembly The generated machine/assembly instructions Checking codegen, instruction selection, register use
Compiler output Diagnostics, warnings, and errors Debugging build failures
Preprocessor Source after macro/preprocessor expansion (C/C++) Tracing macro behavior
AST The parsed abstract syntax tree Understanding how the frontend parsed your code
Control Flow Graph Basic blocks and their edges Reasoning about branches and loops

The output pane also supports options such as demangling identifiers, filtering unused labels, library functions, directives, and comments, and toggling Intel asm syntax. These filters matter because raw compiler output is noisy; hiding library functions and directives usually makes the relevant codegen easier to read.

Rust-specific intermediate representations

Rust has its own pipeline stages that sit between source and machine code, and Compiler Explorer exposes them directly.

  • Rust HIR (High-level IR): A desugared but still fairly source-like representation. Useful for seeing how syntactic constructs are lowered before type checking and borrow checking.
  • Rust MIR (Mid-level IR): The representation used for borrow checking and many optimizations. This is the most informative view for understanding why the borrow checker accepts or rejects code, and how control flow is modeled.
  • Rust macro expansion: Shows the result of expanding macros, which is essential when a macro-generated error or unexpected codegen appears.

A practical example: if a match or ? operator produces surprising assembly, checking MIR first shows how the control flow was lowered, and macro expansion shows whether a macro introduced the extra branches. That sequence — macro expansion → HIR → MIR → assembly — lets you localize a problem to a specific compiler stage instead of guessing from the final output.

LLVM and Clang views

For compilers backed by LLVM, additional views are available:

  • LLVM IR: The target-independent intermediate representation. Useful for seeing optimizations that happen before machine code generation.
  • ClangIR: A newer Clang IR, available where supported.
  • Opt Pipeline / optimization remarks: Shows which optimization passes ran and what they did, including missed and passed optimization remarks. This is the view to use when you expect an optimization (inlining, vectorization, constant folding) but it did not happen.

LLVM IR options include demangling symbols, -fno-discard-value-names for readable value names, and filters for debug info and instruction metadata. Enabling value names makes IR far easier to follow.

GCC views

When a GCC-based compiler is selected, the output options include GCC-specific dumps:

  • GCC Tree/RTL: Tree and register-transfer language dumps.
  • GIMPLE: GCC's mid-level representation, with options for raw or slim dumps, addresses, alias info, basic blocks, line numbers, pass details, pass stats, unique IDs, and virtual operands.
  • Passes / Passes Tree / RTL Pass / IPA Pass: Views of individual optimization passes.

These are the GCC equivalents of LLVM's opt pipeline and are the right place to look when GCC performs (or fails to perform) an optimization.

Other representations and tools

The interface also lists views such as GHC Core, GHC STG, GHC Cmm (Haskell), Lean C output, Clojure macro expansion, Yul (Solidity IR), GNAT debug trees (Ada), and a control flow graph. Availability is compiler-dependent, and the UI explicitly notes when the current language or compiler does not support a given tool.

How to choose a view

  1. Start with assembly to confirm the behavior you care about.
  2. If the assembly is surprising, move one stage up: MIR for Rust, LLVM IR for LLVM compilers, GIMPLE for GCC.
  3. If the IR looks wrong at the source level, check macro expansion (Rust) or the preprocessor (C/C++).
  4. If an optimization is missing, open the optimization remarks / pass view to see whether the pass ran and why it was skipped.

The main constraint to keep in mind is that not every view exists for every compiler, so the available list changes with your language and compiler selection.