---
gap_intake_report: true
intake_model: claude-opus-5[1m]
intake_at: 2026-08-11T16:38:07Z
target_doc: pipeline/overview.md
target_doc_source_commit_before: 53b76e6d3009b8e6434d41573524c7ce5c499d23
target_doc_source_commit_after: ec47ea72b6aa5fefc3b36f8a780dbd3ecf5b1f6e
gap_count: 8
actions:
  fixed: 4
  rejected_bogus: 2
  rejected_out_of_scope: 1
  deferred: 1
  escalated_to_finding: 0
---

# Gap-intake report for pipeline/overview.md

## Summary

Nothing was escalated: no observation in this queue contradicted what
the watched source says the compiler should do. Four gaps were fixed,
two rejected as bogus, one rejected as out of scope, and one deferred.
The most consequential finding is that the block-parameter gap's
suggested addition was wrong: `constructSSA` sits in the mandatory
pass block of `generateIRForTranslationUnit` and runs at every
optimization level, so block parameters are *not* established by an
optimization pass; what the test actually observed is that
`eliminatePhis` takes the IR back out of SSA form before every
back-end, and that an `OpPhi` in emitted SPIR-V is reconstructed by
the downstream SPIR-V optimizer, which runs only above optimization
level `None`. The document now says that instead of the hypothesis.
The two `cascading-only-mention` gaps asked for "tested in" pointers
that the document already carries, and the `#include` example belongs
to the per-stage page.

## Actions

| Gap ID | Action | Evidence | Fix summary |
| --- | --- | --- | --- |
| ec552f809731 | fixed | `source/slang/slang-lower-to-ir.cpp:7113-7130` and `:7136-7175` (lowering emits a join-block `emitParam` directly for `?:` and for short-circuiting `&&` / `\|\|`), `:15602-15605` (`constructSSA` is in the mandatory pass block, unconditional; only `simplifyCFG` / `peepholeOptimize` at `:15609-15614` are gated, and on `MinimumSlangOptimization` — `source/slang/slang-compiler-options.h:363-366` — not on `-O`), `source/slang/slang-emit.cpp:2547-2551,2579` (`eliminatePhis` moves the IR back out of SSA form for every target before emit), `:3388-3393` (spirv-opt runs only when the optimization level is not `None`); printed forms in `docs/generated/tests/design/pipeline/overview/ssa-block-params-across-branch.slang` | added a paragraph under AST → IR lowering stating where block parameters come from (direct at lowering for short-circuit forms, via mandatory `constructSSA` for local variables) and that `eliminatePhis` removes them before emit, so SPIR-V `OpPhi` is the downstream optimizer's work — the gap's premise that an optimization pass establishes the form is not what the source says |
| 01340fd96350 | fixed | `source/slang/slang-emit.cpp:2536-2539` (`legalizeModesOfNonCopyableOpaqueTypedParamsForGLSL` under `isKhronosTarget && !emitSpirvDirectly`), `:2574-2578` and `:2615-2618` (direct-SPIR-V-only pass options and passes), `:1521-1537` (PyTorch-binding-only and CUDA-only pass groups) for the pass-list branching; `source/slang/slang-emit-hlsl.cpp:449`, `slang-emit-glsl.cpp:1504`, `slang-emit-wgsl.cpp:204`, `slang-emit-cpp.cpp:939` and the absence of any `NumThreads` handling in `slang-emit-metal.cpp` / `slang-emit-cuda.cpp` for the emitter-side spelling; verified printed forms in `docs/generated/tests/design/pipeline/overview/pipeline-is-target-sensitive.slang` | added a paragraph under IR passes answering the gap's own question — the pass list branches on target, and the `[numthreads(16, 1, 1)]` per-target spellings are settled in the emitter, not here — with the minimal example the gap asked for |
| f5121a986fd4 | fixed | `source/slang/core.meta.slang:4795-4798` (`[TorchEntryPoint]`, "Mark a function as a pytorch kernel entrypoint") and `:4830-4833` (`[AutoPyBindCUDA]`); `source/slang/slang-emit.cpp:1521-1528` (the `PyTorchCppBinding` target runs a Torch-only pass group) and `:2851-2852` (`TorchCppSourceEmitter`). The decisive gate is `source/slang/slang-ir-pytorch-cpp-binding.cpp:1257-1287`, which builds its work list only from functions carrying `IRTorchEntryPointDecoration` / `IRCudaKernelDecoration` and strips the export decorations from every other function — that file is outside the watched paths | qualified the Torch entry in the emitter list: wrappers are generated only for `[TorchEntryPoint]` / `[AutoPyBindCUDA]` functions, so `-target torch` on an ordinary compute entry point has nothing to bind |
| c70735963289 | fixed | `source/slang/slang-compile-request.cpp:508-522` — `checkTranslationUnit` runs once per unchecked unit under the `isChecked` guard, and `loadedModules.add(...)` happens only *after* that unit is checked, so `findOrImportModule` sees it for subsequent `import` decls; the `TODO` at `:517-520` states explicitly that a unit added later is not discoverable | attached the user-visible consequence to the `checkAllTranslationUnits` bullet: an `import` resolves against a sibling translation unit only when that unit precedes it in the request |
| 790ed2af8eab | rejected-bogus | The pointer the gap asks for is already in the sentence it anchors to: "actual control flow weaves checking and parsing together (see [02-parse-ast.md](02-parse-ast.md) for the two-stage parser)". The parse-stage document is named at the exact point of the remark | — |
| e46af18a3cbc | rejected-bogus | The `### Semantic check` section already ends with "Detail: [03-semantic-check.md](03-semantic-check.md).", and every other stage subsection carries the same `Detail:` line — that is the document's established form for "coverage lives in the per-stage page" | — |
| 8753c4dc1e36 | rejected-out-of-scope | Owned by the per-stage page: `docs/generated/design/pipeline/01-lex-preprocess.md` has a dedicated `### #include resolution` section (line 338) plus the include-stack / `InputFile` material at lines 243-257 and 321-358. The overview's generation contract forbids the duplication — `docs/generated/design/_meta/prompts/pipeline-overview.md:43-44`, "No section duplicates content from a per-stage doc; the per-stage docs do the deep dive, this one is purely a roadmap" | — |
| 15db1575c895 | deferred | Blocked on watched-path coverage. `source/slang/slang-code-gen.cpp:1216-1217` confirms only the dispatch (`CodeGenTarget::HostVM` → `emitHostVMCode`, defined at `source/slang/slang-emit.cpp:3570`); neither the tool name nor the `-target` spelling appears in any watched path. Both live outside them: the spelling is `slang-vm` / `slangvm` per the target-name table at `source/core/slang-type-text-util.cpp:101`, and the interpreter is `source/slangi/`. Follow-up: add `source/core/slang-type-text-util.cpp` (and, if the tool is to be named, `source/slangi/`) to this document's `watched_paths`, then name `slangi` and `-target slang-vm` next to the VM-bytecode mention | — |
