Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Solve IR and Execution

Solve Lowering (rumoca-phase-solve)

Solve lowering converts the structurally prepared DAE into the Solve IR: a register-machine format that execution backends consume directly. The MLS B.1 functions become ComputeBlock graphs mixing two kinds of nodes:

NodeContents
ScalarProgramBlockFlat register programs (Vec<LinearOp>), one scalar output per program
Tensor program nodes (ComputeNode::MatMul, LinSolve, …)Tensor kernels with explicit shape/layout metadata and a scalar fallback

Solve adds no mathematics; it changes format. Keeping tensor structure explicit above the scalar layer is what lets a backend choose between scalar expansion (embedded C) and native kernels (BLAS/faer, CUDA, MLIR linalg) without re-deriving structure.

SolveProblem is the base lowered problem. Expensive or non-canonical products (mass-matrix form, output projections) are separate artifacts requested by the backends that need them.

Execution Adapters

Execution adapters wrap toolchains and runtime APIs around generated or lowered code. They must not own semantics — no DAE lowering, no structural rewrites, no template policy:

CrateRole
rumoca-exec-craneliftIn-process JIT via Cranelift
rumoca-exec-mlirMLIR-based compilation path
rumoca-exec-wasmWASM execution backend

The generated-code targets (rust-solve, c-solve, embedded-c, cuda-c, cuda-nvrtc-solve-jit, fmi2/fmi3) consume Solve through the codegen engine instead — see Code Generation Engine.

Adding a New Backend

The pathway for a new execution backend (the same one a future WebGPU/WGSL backend would take):

  1. Decide the consumption model: a codegen target (templates rendering kernels, like cuda-c) or an execution adapter (an API wrapper, like rumoca-exec-cranelift) — or both, like the NVRTC JIT.
  2. Consume Solve IR. If the backend needs tensor structure, use the tensor program nodes; every node guarantees a scalar fallback, so a backend can start scalar-only and specialize incrementally.
  3. Declare capabilities honestly in the target manifest — readiness level and per-feature support columns are what rumoca targets reports.
  4. Keep language/toolchain specifics in the target’s target.toml and templates, never in phase logic (SPEC_0029).