Intermediate Representations (HIR & MIR)
Relevant source files
The following files were used as context for generating this wiki page:
Intermediate Representations (IRs) in Pop Lang serve as backend-neutral stages between high-level source code and final machine code. The compiler utilizes two primary stages: High-Level Intermediate Representation (HIR) and Mid-Level Intermediate Representation (MIR). These stages ensure that language semantics are strictly preserved and verified before being lowered to specific backends like LLVM or the MIR interpreter.
HIR preserves typed language concepts and resolved stable IDs, acting as the last layer where source-level structures are directly modeled. MIR makes control flow, evaluation order, calls, and runtime operations explicit, serving as the semantic contract for all backends.
Sources: architecture/11-compiler-component-architecture.md, AGENTS.md:329-335
Compiler Pipeline Overview
The Pop Lang semantic pipeline follows a strict sequence to ensure correctness and type safety. HIR and MIR are critical late-stage representations within this flow.
The semantic pipeline ensures that every stage is verified before moving to the next representation.
Sources: AGENTS.md:322-327, architecture/11-compiler-component-architecture.md:5-25
High-Level Intermediate Representation (HIR)
HIR is the representation where high-level source language concepts, such as records, classes, and namespaces, are still explicitly preserved. It is constructed after type checking and resolution are complete.
Core Responsibilities
- Source Concept Preservation: HIR maintains language-specific structures like
HirFunction,HirMethod, andHirDeclaration. - Verification: The HIR verifier ensures that every ID, type, and member dispatch decision is valid based on the semantic model.
- Backend Neutrality: HIR contains no backend-specific opcodes, layouts, or LLVM objects.
Sources: architecture/11-compiler-component-architecture.md:88-92, crates/compiler/driver/src/front_end.rs:20-25
Implementation Structures
The analyze_bubble function orchestrates the creation of the HirBubble, which serves as the container for all HIR-level declarations within a compilation unit.
| Structure | Description |
|---|---|
HirBubble | Represents the complete HIR for an independently compiled Bubble. |
HirFunction | A typed function representation in HIR. |
HirMethod | A class or interface method representation in HIR. |
HirDeclaration | High-level declarations including records, unions, and classes. |
Sources: crates/compiler/driver/src/front_end.rs:163-176, architecture/21-cli-tooling-and-code-units.md:46-56
Mid-Level Intermediate Representation (MIR)
MIR is a Control-Flow Graph (CFG) based representation. It lowers high-level constructs into explicit executable semantics, making it the primary contract for backends.
Key Characteristics
- Explicit Control Flow: MIR makes evaluation order, calls, effects, and GC safe points explicit.
- Portable Optimization: MIR is used for portable analysis and transformations that apply to all backends.
- Stability: No source symbol lookup occurs during MIR lowering; all information is encoded as typed inputs or explicit runtime-interface operations.
Sources: architecture/11-compiler-component-architecture.md:94-100, AGENTS.md:330-335
MIR Analysis and Verification
Every transformation within MIR is subject to analysis and verification to prevent regressions.
The MIR stage acts as the final semantic check before backend emission.
Sources: architecture/11-compiler-component-architecture.md:94-100, AGENTS.md:336-337
Architecture Constraints
Both HIR and MIR are governed by strict architectural invariants to prevent "Lua regressions" (the reintroduction of dynamic behavior).
- No Dynamic Escape Hatches: Neither IR may introduce
Any,Dynamic, or unchecked string-based resolution. - Backend Neutrality: Backend semantic disagreement is considered a bug. Backends (LLVM/C/VM) are not permitted to call back into parsing or typing; they must consume the verified IR provided.
- Strong Typing: Every runtime operation in HIR and MIR must have a compiler-proven type.
Sources: AGENTS.md:28-35, architecture/19-architecture-conformance-and-regression-policy.md:65-80
Inspecting IRs via CLI
The unified pop toolchain allows developers to inspect these representations directly during development through the pop check command.
| Command Option | Effect |
|---|---|
pop check --dump hir | Prints the HIR after successful verification. |
pop check --dump mir | Prints the canonical MIR after successful verification. |
Dumps are deterministic for a specific compiler version but are intended for debugging rather than stable serialization.
Sources: architecture/decisions/0017-bubbles-packages-workspaces-and-cli.md:21-30, architecture/21-cli-tooling-and-code-units.md:185-195
Summary
The Intermediate Representations in Pop Lang provide a structured, verified pathway from high-level source code to executable machine code. HIR maintains the semantic richness of the language, while MIR provides a stable, control-flow-explicit contract for multiple backends. This separation ensures backend portability and prevents the introduction of dynamic typing regressions at the compiler level.