Morph IR (NIR) Specification
Status: living document. This tracks the implementation under src/nir/.
Surface syntax (what authors write in .mx files) is not defined here; see language_reference.md and Docs/learnmorph/.
Overview
NIR is the typed SSA IR between semantic analysis and MIR construction.
Current canonical flow:
AST
-> Morph surface semantic resolution
-> NIR
-> Morph-backed optimizer
-> MIR
-> backend host
Key properties:
- typed SSA values
- module / function / block structure
- GPU- and tensor-aware instructions in the core IR
- Morph-owned semantic-family tagging for covered constructs
- Morph-backed optimizer pipeline loaded from manifests
Module Structure
Module
globals[]
classes[]
functions[]
Function
arguments[]
blocks[]
Block
instructions[]
Instruction Metadata
For the current Morph migration, NIR instructions can also carry:
executionHintsemanticFamily
semanticFamily is the bridge used by covered Morph-owned constructs such as core.input and core.add to survive optimization and reach backend route selection.
Type Surface
NIR currently carries the language types needed by lowering and optimization, including:
- integers
- floats and doubles
- bool
- string
- arrays
- tensors
- classes
- enums
- dynamic
- pointer-like storage forms used internally by lowering
The implementation lives in include/morphc/sema/TypeSystem.h and the NIR instruction classes under include/morphc/nir/.
Optimizer Pipeline
The default optimizer pipeline is Morph-backed and loaded from morphs/pipelines.toml.
Current default order:
1. ConstantFolding
2. CopyPropagation
3. AlgebraicSimplification
4. DeadCodeElimination
5. BranchSimplification
6. TensorFusion
7. GpuScopeLifting
8. DeadCodeElimination
The host optimizer executes that sequence while Morph metadata and workspace manifests define the default plan.
Morph Integration
Lowering
Morph-owned lowering currently uses the structural surface host model.
Implemented covered slices include:
Inputroot/chain loweringAddsurface/operator ownership- REPL behavior planning for
InputandPrint
Physical ownership rules:
- root lowering:
morphs/<Domain>/Lowering/<Root>/<Root>.cpp - chain lowering:
morphs/<Domain>/Lowering/<Root>/chain/... - root REPL behavior:
morphs/<Domain>/Lowering/<Root>/repl/... - surface/operator families:
morphs/<Domain>/Surface/<Family>/...
Backend handoff
Covered Morph-owned families mark their NIR instructions with semanticFamily and now reach host.llvm backend route components through MIR and the backend host.
That route host path is implemented for:
core.inputcore.add
Missing configured backend routes are fatal.
MIR boundary
The public backend handoff after NIR is now MIR.
MIRBuilder consumes an optimized NIR module, preserves operationId, structural InstKind, executionHint, and semanticFamilyId, and retains the NIR module as owned backing state for backend hosts.
Validation Expectations
Validate NIR or Morph pipeline changes through morphc:
.\morphc.bat test "mir"
.\morphc.bat test "llvm"
.\morphc.bat build