Skip to content

Core IR

Core IR is the compiler-owned representation passed from typed Gleam syntax to WebAssembly code generation. It keeps evaluation order, locals, calls, managed values, and failure paths explicit.

Module structure

An IR module records:

  • source span
  • imports and declarations
  • constants
  • module initialization metadata
  • references and exports
  • functions

Functions record parameters, locals, return type, call ABI, body, and source span. Locals use stable IDs so backend emission does not repeat name lookup.

Expression forms

The IR represents current executable and backend-facing forms:

  • typed literals
  • local reads and writes
  • direct calls
  • indirect calls through function values
  • function values and anonymous functions
  • blocks with ordered instructions and a result
  • branch expressions with clauses, patterns, and guards
  • tuples, lists, records, custom constructors, and list cons
  • strings and bit arrays as runtime-managed values
  • field and tuple-element access
  • runtime equality and comparison metadata
  • memory allocation, loads, and stores
  • failure paths for panic, todo, assert, and match failure

Unsupported source forms should fail during lowering with source-spanned diagnostics, unless they are intentionally represented for a later backend pass.

ABI metadata

Calls carry ABI metadata so code generation can distinguish internal calls, module imports, host imports, and exports. ABI values preserve representation hints for scalar and managed values.

Pattern lowering

Source-level pattern syntax lowers into explicit IR branch clauses. Pattern tests and bindings remain structured enough for the backend to emit WAT deterministically, while no longer depending on raw Gleam syntax.

Debug output

IR debug output is deterministic. Tests use snapshots to make changes to lowering, locals, call ABI data, and managed-value forms easy to inspect.