Walking Skeleton
Goal
Prove the thinnest real end-to-end seam: ori_codegen owns the pure
CodegenBackend/input/artifact contract, a single-variant
CodegenBackendChoice::Llvm enum in oric wraps the existing LLVM compile and
finalization path with no behavior change, and both compile_common.rs entry points
route through the one dispatch module. Build the
backend_stub_conformance integration test fixture this plan’s north-star gate
probes.
Context
Research (compiler_repo/compiler/oric/src/commands/compile_common.rs) confirmed
exactly two production entry points (compile_to_llvm_with_imported_monos,
compile_to_llvm_with_imports) both terminating in
codegen_pipeline::run_codegen_pipeline. This section proves the final dependency
direction and typed input/artifact shape while delegating to the shipped LLVM
implementation before any deeper migration.
Implementation sketch
- Create the narrow
ori_codegencrate. Define immutableCodegenInput<'a> { program: &'a ExecutableProgram, target: &'a TargetSpec, layout: &'a CompiledLayoutPlan }, typedArtifactRequest, backend-neutralEmittedArtifact, andBackendError. Construction validates program/target/layout fingerprints before a backend is entered. - Define
CodegenBackendwith a backend-private associatedModule,compile(&CodegenInput), andfinalize(Module, &ArtifactRequest) -> EmittedArtifact. The associated module is visible only inside a genericcompile_and_finalize<B: CodegenBackend>helper; no backend-private IR reachesoricorchestration. - Define
enum CodegenBackendChoice { Llvm }inoricand one exhaustive dispatch module. The LLVM implementation delegates compilation to the existingrun_codegen_pipelineand delegates finalization to the existing LLVM object/WASM emission path. - Route both
compile_common.rsentry points throughCodegenBackendChoice::Llvmand the generic compile/finalize helper. Linking and execution consume only the returned typed native-object or complete-WASM artifact. - Create a
backend_stub_conformanceCargo feature and integration-test backend implementing the contract with a private dummy module and deterministic emitted artifact. Add negative pins for mismatched target/layout fingerprints and an artifact request the stub does not support. - Verify
ori buildandori test --backend=llvmpreserve shipped LLVM IR, native object/WASM bytes where deterministic, linking, diagnostics, and observable behavior.
Narrowed contract and deferral anchors
Source-verified at HEAD: TargetSpec and CompiledLayoutPlan do not exist as
types anywhere in compiler_repo/compiler/ (doc-comment prose only), and
ExecutableProgram is constructed inside run_codegen_pipeline
(codegen_pipeline/pipeline.rs), downstream of the dispatch boundary. This
section therefore ships ori_codegen::CodegenInput over the inputs the seam
carries today and defers the richer contract to its named owners:
TargetSpec+CompiledLayoutPlanfields onCodegenInput— owner:plans/repr-opt/section-13-multi-backend-layouts.md(declaresCompiledLayoutPlan/VmLayoutPlanover shared immutable evidence) and this plan’s “ incodegen-backend-trait-and-dispatch--s-90024726.md(which ownsori_targetand fleshes outCodegenInput). Inventing either type here would forkrepr-opt§13’s SSOT, and naming today’sReprPlanasCompiledLayoutPlanwould misname a transitional carrier.ExecutableProgramas theCodegenInputpayload — owner: “ inshared-pre-codegen-orchestration--s-30e3c9a6.md, which routes the driver throughrealize_closed_program()before dispatch. Hoisting it here would also relocate the liveregister_resolved_collection_burdenstypeck call the walking skeleton must route around, not through.finalize()/ArtifactRequest/EmittedArtifactand the mismatched target/layout + unsupported-artifact negative pins — owner: “, which names all five verbatim.
Shipped in this section instead: the ori_codegen crate owning the moved
contract, the CodegenBackendChoice rename, and a negative pin that is
expressible today (a refusing stub backend proving BackendError crosses the
closed-enum dispatch intact).
Spec references
.claude/rules/canon.md §1 (pipeline phase 8, sub-layer 7a ori_repr); .claude/rules/compiler.md §Dispatch (enum for fixed sets).
Work items
- Define the pure
ori_codegencontract overExecutableProgram + explicit TargetSpec + matching CompiledLayoutPlan; add private-module compile plus typed artifact finalization; add single-variantCodegenBackendChoicedispatch inoric; route bothcompile_common.rsentry points through it; and build the positive/negativebackend_stub_conformancefixture.
Historical Intel Snapshot (Superseded by the Current Contract)
The folded snapshot below predates ExecutableProgram, TargetSpec,
CompiledLayoutPlan, ori_codegen, and the compile/finalize artifact boundary. Its
RealizedProgram, ori_repr::CodegenBackend, and BackendChoice prescriptions are
research history only; the normative goal, sketch, and work item above replace them.
The walking-skeleton is a genuinely thin, low-risk stub — but the graph surfaces two facts the section body does not state that change how narrow “thin” can actually be:
- The trait boundary cannot be a pure realized-IR-in/artifact-out contract.
run_codegen_pipeline— the exact function the newLlvmBackend::compile()wraps unchanged — reaches directly intoori_types::infer::expr::calls::monomorphization::burden::register_resolved_collection_burdens(§3.1, §3.4 surprise edge 2.64, corroborated by callees list). Codegen is not typeck-independent today.RealizedProgram(defined in THIS section) either bundles enough typeck-registry state to satisfy that call, or the call moves before the trait boundary in §02 (shared-pre-codegen-orchestration). Either way, the walking-skeleton’sRealizedProgramshape is a real design decision, not a rename exercise —[JOIN]typeck-into-codegen coupling + the plan’s own step 2 (“no field changes yet — §02 does the real orchestration unification”). - The graph cannot see the two call sites this section routes through
BackendChoice.run_codegen_pipelineshows ZERO callers in the CALLS graph (§3.1, §3.3) despite two confirmed real call sites incompile_common.rs(verified by direct source read). This is asuper::-qualified, multi-line-argument call the tree-sitter/SCIP extractor fails to resolve; the extractor gap is only partially closed (§9). Do not trust graph-only “0 callers” as evidence of dead code anywhere in this crate; verify by source read. - The MISSING_ABSTRACTION signal directly validates the fix.
compile_to_llvm_with_imported_monos~compile_to_llvm_with_importsscores 0.933 similarity (§5) — the graph independently flags the exact pair this section’s trait boundary collapses.run_codegen_pipelineand the JIT evaluator’scompile_all_functionssit in the SAME community (900, size 203; §3.6) — corroborating the mission’s “Known bugs folded into scope”LEAK:algorithmic-duplication(SSOT-18), which §02 (not this section) fixes. - The scope-decision boundary is empirically large and well-drawn.
ori_llvm::aot::carries 943 symbols reached directly from ~15+oric::commands::build::*call sites (linking, mangling, object emission, incremental cache; §3.3). The mission’s decision to keep AOT/link machinery OUT ofCodegenBackend::compile()is not a convenience cut — it is the only way to keep this section’s stub genuinely thin. Do not letcompile()’s signature grow to reach any of these 943 symbols. run_codegen_pipelineitself ispub(super)(source-verified), explicitly commented “private pipeline helper — params match the data flow from both public compile functions.”LlvmBackend’s impl must live wherepub(super)visibility resolves (insideoric::commandsor a submodule) — a detail the section’s sketch does not spell out but the visibility constraint forces.
Historical decisions from that snapshot, retained only as evidence:
- The typeck-to-codegen burden-registration edge had to move before the closed artifact boundary; the current
ExecutableProgramcontract owns that resolution. - Verify the two
compile_common.rs->run_codegen_pipelinecall sites BY SOURCE READ, not by graph query — the graph shows zero callers for this specific symbol (finding 2). - Keep platform linking, sysroot discovery, packaging, and process launch outside the backend interface; backend-local object/module emission is now deliberately covered by typed
finalize(). - Place the LLVM adapter where it can reach the private pipeline helper while implementing the
ori_codegencontract without widening helper visibility.
DIG DEEPER
scripts/intel-query.sh dag-ascii backend-boundary --human
scripts/intel-query.sh plan-status backend-boundary --human
(full dossier: walking-skeleton—s-fdca8921.intel.md)