Section 09: Layout Caching via Salsa Query
Status: Not Started
Goal: Move type layout computation from an imperative pass with manual caching to a Salsa-tracked query that any phase can call. This is the aspirational pattern from impl-hygiene.md — “A Salsa-tracked layout_of(TypeId) -> Layout query that any phase can call.”
Success Criteria:
-
layout_of()Salsa query exists — satisfies mission criterion “all consumers call layout_of()” - No manual
RefCell<FxHashMap>cache remains — satisfies mission criterion “Salsa memoization” - All codegen tests pass with Salsa-cached layout — behavior identical to imperative pass
-
impl-hygiene.mdupdated — aspirational pattern marked as implemented
Context: Research found a two-layer layout system:
ori_repr(compiler/ori_repr/src/layout/, 285+ lines): Pure Rust layout computation (repr_size(),repr_align(),compute_field_layout(),reorder_fields()) operating onMachineReprenum. ProducesReprPlan. NOT a Salsa query — computed imperatively once per compilation.ori_llvmTypeLayoutResolver(compiler/ori_llvm/src/codegen/type_info/layout_resolver.rs, 394 lines):Idx → BasicTypeEnumwithRefCell<FxHashMap<Idx, BasicTypeEnum>>cache and cycle detection viaFxHashSet<Idx>+MAX_RESOLVE_DEPTH = 32.
The gap: layout is computed imperatively and cached manually. Moving to Salsa gives:
- Automatic invalidation when types change (incremental correctness)
- Cross-phase availability (ARC can query layout for alignment-aware optimization)
- Determinism guarantee from Salsa’s purity requirement
- Cache eviction handled by Salsa revision tracking
Design challenge: ReprPlan currently carries Idx references, not LLVM handles (repr.md §RP-4). The Salsa query should return a ReprPlan-like type that derives all Salsa-required traits (Clone, Eq, PartialEq, Hash, Debug). ReprPlan already derives these per repr.md §RP-4.
Reference implementations:
- Rust
TyCtxt::layout_of(): memoized layout query on the type context. Lazily computed on first access, cached, never recomputed.
Depends on: Section 01 (policy language). Benefits from Section 07 (TypeFolder patterns for type traversal in layout computation).
09.1 Design Layout Query Interface
File(s): design document (not code yet)
-
Design the Salsa query interface:
layout_of(db: &dyn CompilerDb, idx: Idx) -> ReprPlan— tracked query- Input: fully-resolved
Idx(perCG:TR-2— noTag::Varin codegen input) - Output:
ReprPlan(alreadyClone, Eq, Hash, Debugperrepr.md §RP-4) - The query lives in a shared location accessible to both
ori_arc(for alignment-aware optimization) andori_llvm(for emission)
-
Decide the hosting crate:
- Option A:
ori_types— closest to the pool, but adds layout dependency to the type crate - Option B:
ori_repr— already owns layout computation, just needs Salsa wiring - Option C: new
ori_layoutcrate — cleanest separation but adds a crate - Recommendation: Option B (
ori_repr) — it already owns the computation; adding Salsa tracking is the minimal change
- Option A:
-
Design the migration path:
- Phase 1: Add
layout_of()query toori_repralongside existing imperative computation - Phase 2: Migrate
TypeLayoutResolverinori_llvmto calllayout_of()instead of maintaining its own cache - Phase 3: Remove the
RefCell<FxHashMap>manual cache
- Phase 1: Add
-
Validate design against
/tp-help -
Subsection close-out (09.1) — MANDATORY before starting 09.2:
- All tasks above are
[x] - Update this subsection’s
statusin section frontmatter tocomplete - Run
/improve-toolingretrospectively on THIS subsection - Run
/sync-claudeto check if code changes affect CLAUDE.md or rules files
- All tasks above are
09.2 Implement Salsa-Tracked Layout Query
File(s): compiler/ori_repr/src/, compiler/oric/src/query/
-
Write failing tests:
- Query
layout_of()for primitive types — verify sizes matchCG:TR-1 - Query for struct types — verify field ordering matches
RP-20 - Query twice for same
Idx— verify same result (Salsa caching) - Query after type pool mutation — verify invalidation (new Salsa revision)
- Query
-
Add Salsa tracked query:
- Wire
layout_ofas a#[salsa::tracked]function in the compiler’s query group - Implementation calls existing
ori_reprlayout computation functions - Result is
ReprPlan(already Salsa-compatible: derives Clone, Eq, Hash, Debug; no Arc, no fn pointers, no LLVM handles per repr.md §RP-4) - Cycle detection: if
layout_of(A)recursively callslayout_of(A)(recursive type), produce a clear error — Salsa’s cycle detection should handle this but verify
- Wire
-
Verify determinism: same input pool → same
ReprPlanoutput across multiple calls and revisions -
Subsection close-out (09.2) — MANDATORY before starting 09.3:
- All tasks above are
[x] - Update this subsection’s
statusin section frontmatter tocomplete - Run
/improve-toolingretrospectively on THIS subsection - Run
/sync-claudeto check if code changes affect CLAUDE.md or rules files
- All tasks above are
09.3 Migrate Codegen Consumers
File(s): compiler/ori_llvm/src/codegen/type_info/layout_resolver.rs, compiler/ori_llvm/src/codegen/
-
Replace
TypeLayoutResolver’s manualRefCell<FxHashMap<Idx, BasicTypeEnum>>cache:- Instead of caching layout in a local HashMap, call
layout_of(db, idx)to get theReprPlan - The LLVM type construction (
Idx → BasicTypeEnum) still happens inori_llvm— but the layout DATA comes from the Salsa query - The
TypeLayoutResolverbecomes a thin wrapper:layout_of()→ReprPlan→ construct LLVM type
- Instead of caching layout in a local HashMap, call
-
Migrate all codegen sites listed in
repr.md §RP-5 Consumers:CG:TR-1canonical type mapping: calllayout_of()for layout dataCG:TR-3aggregate field ordering: useFieldEntryfromlayout_of()CG:AB-1ABI threshold: useabi_sizefromlayout_of()CG:NR-2/NR-6narrowing: usestorage_widthfromlayout_of()
-
Remove the cycle detection
FxHashSet<Idx>fromTypeLayoutResolver— Salsa’s cycle detection handles this -
Verify:
timeout 150 ./test-all.sh— all codegen tests, FileCheck tests, AOT tests pass -
Subsection close-out (09.3) — MANDATORY before starting 09.4:
- All tasks above are
[x] - Update this subsection’s
statusin section frontmatter tocomplete - Run
/improve-toolingretrospectively on THIS subsection - Run
/sync-claudeto check if code changes affect CLAUDE.md or rules files
- All tasks above are
09.4 Remove Manual Cache & Documentation
File(s): compiler/ori_llvm/src/codegen/type_info/layout_resolver.rs, .claude/rules/impl-hygiene.md, .claude/rules/repr.md
-
Remove the
RefCell<FxHashMap>manual cache fromTypeLayoutResolver— all layout data now comes from Salsa -
Update
impl-hygiene.md§Aspirational Patterns → Layout Caching: change from “aspirational” to “implemented” -
Update
repr.md§RP-4:- Change “NOT a Salsa tracked struct. Computed imperatively” to “Salsa-tracked query via
layout_of(). Computed on demand and memoized.” - Update the consumers table to reference the Salsa query
- Change “NOT a Salsa tracked struct. Computed imperatively” to “Salsa-tracked query via
-
Update
canon.md§6 SSOTs table — addlayout_of()as the canonical home for layout computation -
Subsection close-out (09.4) — MANDATORY before completing section:
- All tasks above are
[x] - Update this subsection’s
statusin section frontmatter tocomplete - Run
/improve-toolingretrospectively on THIS subsection - Run
/sync-claudeto check if code changes affect CLAUDE.md or rules files
- All tasks above are
09.R Third Party Review Findings
- None.
09.N Completion Checklist
- All subsections (09.1-09.4) complete
-
layout_of()Salsa query exists and is the sole layout entry point - Manual
RefCell<FxHashMap>cache removed - All codegen tests, FileCheck tests, AOT tests pass
- Layout is deterministic across Salsa revisions (tested)
- Debug AND release builds pass
-
timeout 150 ./test-all.shpasses -
/tpr-review— independent dual-source review clean -
/impl-hygiene-review— implementation hygiene clean -
/improve-tooling— section-close sweep -
/sync-claude— section-close doc sync