---
generated: true
model: claude-opus-4-7
generated_at: 2026-05-22T00:00:00+00:00
source_commit: 6e923e2c0fe3cae4e7cf40e25a96569df5b9f009
watched_paths_digest: 9929a933b7e23daa2d56e2d0c08666ee4781a53381b498c723250e39826823db
source_doc: docs/generated/design/target-pipelines/cuda.md
source_doc_digest: f3067b9f2ce32537355b651dfeef65895e40ee6f911d553c5cf02a6415cdd130
warning: "Auto-generated. May drift from source. Do not edit by hand."
---

# Tests for target-pipelines/cuda

## Intent
Tests verify the CUDA target pipeline described in
[`docs/generated/design/target-pipelines/cuda.md`](../../../design/target-pipelines/cuda.md):
the ordered IR-pass sequence run by `linkAndOptimizeIR` and
`emitEntryPointsSourceFromIR` when `CodeGenTarget::CUDASource`
is requested, and the CUDA C++ text the Phase D emit produces.
The bundle exercises Phase A / B / C / D observable claims:
the `#include "slang-cuda-prelude.h"` prelude marker, the
`extern "C" __global__ void` kernel wrapping, the
`extern "C" __constant__ GlobalParams_0` resource collection
(`moveEntryPointUniformParamsToGlobalScope` is skipped), the
`legalizeEntryPointVaryingParamsForCUDA` rewrite of
`SV_DispatchThreadID` into `blockIdx * blockDim + threadIdx`,
`lowerImmutableBufferLoadForCUDA`'s `__ldg(...)` injection
(scalar and per-field struct variants), the
`atomicAdd` lowering of `InterlockedAdd`, `lowerEnumType`'s
collapse of enums to integer literals,
`transformParamsToConstRef` and `undoParameterCopy`'s
pointer-form lowering, the default
`legalizeByteAddressBufferOps` keeping `Load<T>(...)` as a
templated call, `lowerAppendConsumeStructuredBuffers` for
CUDA (target != HLSL), `legalizeArrayReturnType` producing a
`FixedArray<T, N> *` out-parameter, `eliminatePhis` default
options yielding named locals, `inlineGlobalConstantsForLegalization`
inlining static constants at use sites, the
`lowerBuiltinTypesForKernelEntryPoints` replacement of
`Texture2D` with `CUtexObject`, `groupshared` becoming
`__device__ __shared__` with `__syncthreads()` for barriers,
`SourceWriter` `#line` directives, the non-D3D / non-Khronos
contrast (no `register(uN)` annotations), and the
`__device__` decoration for non-entry-point functions.
The bundle stops at CUDA C++ text — nvrtc / PTX downstream and
OptiX-specific arms are out of scope on the no-GPU runner.

Coverage strategy: one test per concrete claim in the doc's
Phase A/B/C/D tables that can be observed in
`slangc -target cuda` text. Default directive is
`//TEST:SIMPLE(filecheck=CHECK):-target cuda -entry main -stage compute`.


## Functional coverage
| Claim | Intent | Anchor | Tests |
| --- | --- | --- | --- |
| collectOptiXEntryPointUniformParams replaces collectEntryPointUniformParams for raygeneration entry points so a CUDA raygeneration shader emits as an extern "C" __global__ void __raygen__<name> kernel through the OptiX SBT pathway. | expansion | [#collectoptixentrypointuniformparams](../../../design/target-pipelines/cuda.md#collectoptixentrypointuniformparams) | [`collect-optix-entry-point-uniforms-raygen.slang`](collect-optix-entry-point-uniforms-raygen.slang) |
| CUDA is not isD3DTarget and is non-Khronos so HLSL register(uN) bindings do not appear in CUDA emit; resources are reached through GlobalParams_0. | functional | [#cuda-specific-runtime-predicates](../../../design/target-pipelines/cuda.md#cuda-specific-runtime-predicates) | [`no-register-binding-on-cuda.slang`](no-register-binding-on-cuda.slang) |
| -target ptx triggers the downstream nvrtc invocation that translates the CUDA C++ text into PTX assembly with a .version header and a .visible .entry kernel symbol. | expansion | [#downstream-nvrtc](../../../design/target-pipelines/cuda.md#downstream-nvrtc) | [`ptx-downstream-nvrtc-emit.slang`](ptx-downstream-nvrtc-emit.slang) |
| CUDA uses eliminatePhis with default options so an if/else-merged value becomes a named local temporary assigned in each branch. | functional | [#eliminatephis-with-default-options](../../../design/target-pipelines/cuda.md#eliminatephis-with-default-options) | [`eliminate-phis-default-options.slang`](eliminate-phis-default-options.slang) |
| Stress: six levels of nested if/else still resolve through eliminatePhis default options into a single named local with branch-wise assignments. | stress | [#eliminatephis-with-default-options](../../../design/target-pipelines/cuda.md#eliminatephis-with-default-options) | [`stress-deeply-nested-control-flow.slang`](stress-deeply-nested-control-flow.slang) |
| CUDA always runs inlineGlobalConstantsForLegalization so a static module-scope constant is inlined at its use sites as the literal value because nvrtc rejects dynamic __device__ initialization. | functional | [#inlineglobalconstantsforlegalization-for-cuda](../../../design/target-pipelines/cuda.md#inlineglobalconstantsforlegalization-for-cuda) | [`static-global-init-moved.slang`](static-global-init-moved.slang) |
| legalizeEntryPointVaryingParamsForCUDA rewrites SV_DispatchThreadID into the CUDA builtin expression blockIdx * blockDim + threadIdx. | functional | [#legalizeentrypointvaryingparamsforcuda](../../../design/target-pipelines/cuda.md#legalizeentrypointvaryingparamsforcuda) | [`dispatch-thread-id-lowered.slang`](dispatch-thread-id-lowered.slang) |
| Verifies lowerImmutableBufferLoadForCUDA emits __ldg for a static index 0 (lower-edge) load of a StructuredBuffer. | boundary | [#lowerimmutablebufferloadforcuda](../../../design/target-pipelines/cuda.md#lowerimmutablebufferloadforcuda) | [`ldg-on-static-index-zero.slang`](ldg-on-static-index-zero.slang) |
| Verifies lowerImmutableBufferLoadForCUDA still emits __ldg when the index is a runtime-bounded value sourced from another buffer. | boundary | [#lowerimmutablebufferloadforcuda](../../../design/target-pipelines/cuda.md#lowerimmutablebufferloadforcuda) | [`ldg-on-runtime-bounded-index.slang`](ldg-on-runtime-bounded-index.slang) |
| Verifies the per-field __ldg(&ptr->field) expansion fires for a three-field struct read at a runtime-bounded index. | boundary | [#lowerimmutablebufferloadforcuda](../../../design/target-pipelines/cuda.md#lowerimmutablebufferloadforcuda) | [`ldg-on-struct-per-field-runtime-bound.slang`](ldg-on-struct-per-field-runtime-bound.slang) |
| lowerImmutableBufferLoadForCUDA expands a struct-typed immutable load into per-field __ldg(&ptr->field) reads through a generated slang_ldg helper. | functional | [#lowerimmutablebufferloadforcuda](../../../design/target-pipelines/cuda.md#lowerimmutablebufferloadforcuda) | [`ldg-on-immutable-struct.slang`](ldg-on-immutable-struct.slang) |
| lowerImmutableBufferLoadForCUDA translates a StructuredBuffer<T> load into a __ldg intrinsic call so the read-only cache path is used. | functional | [#lowerimmutablebufferloadforcuda](../../../design/target-pipelines/cuda.md#lowerimmutablebufferloadforcuda) | [`ldg-on-immutable-buffer.slang`](ldg-on-immutable-buffer.slang) |
| Global uniform parameters are gathered into a GlobalParams_0 struct bound to __constant__ memory because moveEntryPointUniformParamsToGlobalScope is skipped for CUDA. | functional | [#phase-a-link-and-entry-point-prep](../../../design/target-pipelines/cuda.md#phase-a-link-and-entry-point-prep) | [`global-params-constant-memory.slang`](global-params-constant-memory.slang) |
| Stress: eight RWStructuredBuffer parameters all packed into GlobalParams_0 on CUDA emit because moveEntryPointUniformParamsToGlobalScope is skipped. | stress | [#phase-a-link-and-entry-point-prep](../../../design/target-pipelines/cuda.md#phase-a-link-and-entry-point-prep) | [`stress-eight-buffer-params.slang`](stress-eight-buffer-params.slang) |
| lowerEnumType collapses an enum to its underlying integer in CUDA emit; the enumerator name does not appear. | functional | [#phase-a-link-and-entry-point-prep](../../../design/target-pipelines/cuda.md#phase-a-link-and-entry-point-prep) | [`enum-lowered-to-integer.slang`](enum-lowered-to-integer.slang) |
| moveEntryPointUniformParamsToGlobalScope is skipped for CUDA so an entry-point uniform parameter is read through the GlobalParams_0 constant struct rather than a kernel argument. | functional | [#phase-a-link-and-entry-point-prep](../../../design/target-pipelines/cuda.md#phase-a-link-and-entry-point-prep) | [`no-uniform-params-to-global-scope.slang`](no-uniform-params-to-global-scope.slang) |
| Multiple texture variants (Texture1D / Texture3D / TextureCube / Texture2DArray) collapse to the same CUtexObject CUDA primitive when packed into GlobalParams; the per-rank Lod helper differs. | expansion | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`texture-variants-globalparams-emit.slang`](texture-variants-globalparams-emit.slang) |
| Negative: a self-recursive function is rejected before CUDA emit with the "recursion not allowed" diagnostic (CUDA target does not allow recursion). | negative | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`stress-recursive-function-rejected.slang`](stress-recursive-function-rejected.slang) |
| RWTexture2D<float4> maps to the CUDA primitive CUsurfObject and subscript-store / subscript-load lower to surf2Dwrite / surf2Dread. | expansion | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`rwtexture2d-emit.slang`](rwtexture2d-emit.slang) |
| RWTexture3D<float4> maps to the CUDA primitive CUsurfObject and subscript-store / subscript-load lower to surf3Dwrite / surf3Dread. | expansion | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`rwtexture3d-emit.slang`](rwtexture3d-emit.slang) |
| Texture1D<float4> maps to the CUDA primitive CUtexObject and SampleLevel lowers to tex1DLod<T>(...). | expansion | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`texture1d-emit.slang`](texture1d-emit.slang) |
| Texture2DArray<float4> maps to the CUDA primitive CUtexObject and SampleLevel lowers to tex2DLayeredLod<T>(...). | expansion | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`texture2darray-emit.slang`](texture2darray-emit.slang) |
| Texture3D<float4> maps to the CUDA primitive CUtexObject and SampleLevel lowers to tex3DLod<T>(...). | expansion | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`texture3d-emit.slang`](texture3d-emit.slang) |
| TextureCube<float4> maps to the CUDA primitive CUtexObject and SampleLevel lowers to texCubemapLod<T>(...). | expansion | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`texturecube-emit.slang`](texturecube-emit.slang) |
| Verifies sampling a Texture2D at a NaN coordinate (gated by tid.x to prevent fold) still lowers through tex2DLod on CUDA emit. | boundary | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`texture-sample-at-nan-nan.slang`](texture-sample-at-nan-nan.slang) |
| Verifies sampling a Texture2D at uv (0.0, 0.0) lowers to tex2DLod with a make_float2(0.0f, 0.0f) coordinate on CUDA emit. | boundary | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`texture-sample-at-zero-zero.slang`](texture-sample-at-zero-zero.slang) |
| Verifies sampling a Texture2D at uv (1.0, 1.0) lowers to tex2DLod with make_float2(1.0f, 1.0f) on CUDA emit (upper-edge UV). | boundary | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`texture-sample-at-one-one.slang`](texture-sample-at-one-one.slang) |
| lowerAppendConsumeStructuredBuffers runs for CUDA (target != HLSL) so AppendStructuredBuffer is replaced with a wrapper struct holding an elements buffer and an atomic counter buffer. | functional | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`lower-append-structured-buffer.slang`](lower-append-structured-buffer.slang) |
| lowerBuiltinTypesForKernelEntryPoints replaces Texture2D with the CUDA primitive CUtexObject in kernel-related signatures. | functional | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`lower-combined-texture-sampler.slang`](lower-combined-texture-sampler.slang) |
| lowerCooperativeVectors fires on CUDA when the target caps do not imply optix_coopvec, so a CoopVec<T,N> is replaced by a fixed-size array form in emit and the OptixCoopVec primitive does not survive. | expansion | [#phase-b-specialization-and-type-legalization](../../../design/target-pipelines/cuda.md#phase-b-specialization-and-type-legalization) | [`lower-coopvec-without-optix-coopvec.slang`](lower-coopvec-without-optix-coopvec.slang) |
| An atomic operation on a UAV passes validateAtomicOperations and emits as the CUDA atomicAdd intrinsic in the CUDA C++ text. | functional | [#phase-c-cuda-legalization-lowering-phi-elimination](../../../design/target-pipelines/cuda.md#phase-c-cuda-legalization-lowering-phi-elimination) | [`atomic-lowered-to-atomicadd.slang`](atomic-lowered-to-atomicadd.slang) |
| collectCooperativeMetadata fires for CUDA when the target caps imply cooperative_vector; an optix_coopvec CoopVec emit preserves the OptixCoopVec primitive in the CUDA C++ text. | expansion | [#phase-c-cuda-legalization-lowering-phi-elimination](../../../design/target-pipelines/cuda.md#phase-c-cuda-legalization-lowering-phi-elimination) | [`collect-cooperative-metadata-coopvec.slang`](collect-cooperative-metadata-coopvec.slang) |
| CUDA uses the default legalizeByteAddressBufferOps options so ByteAddressBuffer.Load<T> survives as a templated method call. | functional | [#phase-c-cuda-legalization-lowering-phi-elimination](../../../design/target-pipelines/cuda.md#phase-c-cuda-legalization-lowering-phi-elimination) | [`byte-address-buffer-load-template.slang`](byte-address-buffer-load-template.slang) |
| Verifies InterlockedAdd with uint MAX (0xFFFFFFFF) operand still lowers to atomicAdd on CUDA emit with the value 4294967295U. | boundary | [#phase-c-cuda-legalization-lowering-phi-elimination](../../../design/target-pipelines/cuda.md#phase-c-cuda-legalization-lowering-phi-elimination) | [`atomic-add-uint-max-wrap.slang`](atomic-add-uint-max-wrap.slang) |
| Verifies an atomic operation at int MAX 2147483647 still lowers to atomicAdd on CUDA emit and the constant is wrapped in int(...). | boundary | [#phase-c-cuda-legalization-lowering-phi-elimination](../../../design/target-pipelines/cuda.md#phase-c-cuda-legalization-lowering-phi-elimination) | [`atomic-add-int-max.slang`](atomic-add-int-max.slang) |
| Verifies an atomic operation under a 64-thread block (contention stress) still emits as a single atomicAdd call on the same buffer slot. | stress | [#phase-c-cuda-legalization-lowering-phi-elimination](../../../design/target-pipelines/cuda.md#phase-c-cuda-legalization-lowering-phi-elimination) | [`atomic-add-contention-64-threads.slang`](atomic-add-contention-64-threads.slang) |
| Verifies legalizeArrayReturnType produces a FixedArray<T,16> * out-parameter for N=16 on CUDA emit (upper-edge array-size sweep). | boundary | [#phase-c-cuda-legalization-lowering-phi-elimination](../../../design/target-pipelines/cuda.md#phase-c-cuda-legalization-lowering-phi-elimination) | [`array-return-rewrite-n-sixteen.slang`](array-return-rewrite-n-sixteen.slang) |
| Verifies legalizeArrayReturnType produces a FixedArray<T,1> * out-parameter for the lower-edge N=1 case on CUDA emit. | boundary | [#phase-c-cuda-legalization-lowering-phi-elimination](../../../design/target-pipelines/cuda.md#phase-c-cuda-legalization-lowering-phi-elimination) | [`array-return-rewrite-n-one.slang`](array-return-rewrite-n-one.slang) |
| legalizeArrayReturnType rewrites T[N] foo() into a void function with an out FixedArray pointer parameter on CUDA. | functional | [#phase-c-cuda-legalization-lowering-phi-elimination](../../../design/target-pipelines/cuda.md#phase-c-cuda-legalization-lowering-phi-elimination) | [`legalize-array-return-type.slang`](legalize-array-return-type.slang) |
| -target cuda-header shares the CUDA IR pipeline with CUDASource and emits CUDA C++ text including the slang-cuda-prelude.h include and an extern "C" __global__ void kernel wrapper. | expansion | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`target-cuda-header-emit-shape.slang`](target-cuda-header-emit-shape.slang) |
| A compute entry point is emitted as an extern "C" __global__ void kernel because CUDA is a valid CUDA kernel. | functional | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`extern-c-global-kernel.slang`](extern-c-global-kernel.slang) |
| A groupshared array becomes a __device__ __shared__ global in CUDA emit and GroupMemoryBarrierWithGroupSync lowers to __syncthreads. | functional | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`groupshared-to-device-shared.slang`](groupshared-to-device-shared.slang) |
| CUDA emit opens with the slang-cuda-prelude.h include so the emitted text compiles under nvrtc. | functional | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`cuda-prelude-include.slang`](cuda-prelude-include.slang) |
| Negative: [numthreads(0,1,1)] is rejected at check time with an "expected a positive integer" diagnostic before CUDA emit can run. | negative | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`numthreads-zero-rejected-diag.slang`](numthreads-zero-rejected-diag.slang) |
| Non-entry-point Slang functions are emitted with __device__ decoration in CUDA emit so nvrtc compiles them as device code. | functional | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`device-function-decoration.slang`](device-function-decoration.slang) |
| The shared SourceWriter emits #line N "<file>" directives in the CUDA C++ text so nvrtc can map errors back to Slang source. | functional | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`line-directive-survives.slang`](line-directive-survives.slang) |
| Verifies a float +inf (1.0/0.0) lowers to the prelude macro SLANG_INFINITY on CUDA emit. | boundary | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`float-infinity-emit.slang`](float-infinity-emit.slang) |
| Verifies a float NaN (0.0/0.0) is emitted on CUDA as the (0.0 / 0.0) expression form so the value is well-defined under nvrtc. | boundary | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`float-nan-emit.slang`](float-nan-emit.slang) |
| Verifies a maximum-per-dim CUDA dispatch [numthreads(1024,1,1)] still emits as a valid extern "C" __global__ void kernel. | boundary | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`numthreads-1024-one-one.slang`](numthreads-1024-one-one.slang) |
| Verifies a scalar groupshared int becomes __device__ __shared__ on CUDA emit (the array-form smoke test already covers the aggregate case). | boundary | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`groupshared-scalar-to-device-shared.slang`](groupshared-scalar-to-device-shared.slang) |
| Verifies a struct-typed groupshared declaration is lowered to __device__ __shared__ with field accesses preserved on CUDA emit. | boundary | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`groupshared-struct-to-device-shared.slang`](groupshared-struct-to-device-shared.slang) |
| Verifies the CUDA emit writes uint(0xFFFFFFFF) as the 4294967295U literal and forms the wrap-add expression with a thread-derived operand. | boundary | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`add-uint32-max-wrap.slang`](add-uint32-max-wrap.slang) |
| Verifies the float positive-zero literal 0.0f survives CUDA emit as 0.0f when guarded behind a thread-id branch (constant-folding cannot remove it). | boundary | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`float-positive-zero-emit.slang`](float-positive-zero-emit.slang) |
| Verifies the half largest-finite value 65504 round-trips through CUDA emit as the __half(...) cast so the value reaches nvrtc as a CUDA half. | boundary | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`half-largest-finite-emit.slang`](half-largest-finite-emit.slang) |
| Verifies the int MAX literal 2147483647 is emitted as int(2147483647) on CUDA. | boundary | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`int-max-emit.slang`](int-max-emit.slang) |
| Verifies the int MIN literal -2147483648 is emitted as int(-2147483648) on CUDA so the value is well-formed under nvrtc. | boundary | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`int-min-emit.slang`](int-min-emit.slang) |
| Verifies the minimum-thread dispatch shape [numthreads(1,1,1)] still produces an extern "C" __global__ void main_0 entry point on CUDA emit. | boundary | [#phase-d-cuda-emit-and-downstream-tools](../../../design/target-pipelines/cuda.md#phase-d-cuda-emit-and-downstream-tools) | [`numthreads-one-one-one.slang`](numthreads-one-one-one.slang) |
| synthesizeActiveMask threads an explicit warp-mask through a wave-active sum so the CUDA emit calls _waveSum with a synthesized mask operand instead of leaving the implicit IR-level active-mask reference. | expansion | [#synthesizeactivemask](../../../design/target-pipelines/cuda.md#synthesizeactivemask) | [`synthesize-active-mask-wavesum.slang`](synthesize-active-mask-wavesum.slang) |
| Verifies an inout int parameter still lowers to pass-by-pointer when the supplied value is int MAX (boundary value does not change the pass shape). | boundary | [#undoparametercopy-and-transformparamstoconstref](../../../design/target-pipelines/cuda.md#undoparametercopy-and-transformparamstoconstref) | [`inout-pointer-at-int-max.slang`](inout-pointer-at-int-max.slang) |
| transformParamsToConstRef converts struct value parameters into pointer-form parameters on CUDA for pass-by-reference. | functional | [#undoparametercopy-and-transformparamstoconstref](../../../design/target-pipelines/cuda.md#undoparametercopy-and-transformparamstoconstref) | [`transform-params-to-constref.slang`](transform-params-to-constref.slang) |
| undoParameterCopy rewrites explicit inout copy-in copy-out wrappers as pass-by-pointer on CUDA emit. | functional | [#undoparametercopy-and-transformparamstoconstref](../../../design/target-pipelines/cuda.md#undoparametercopy-and-transformparamstoconstref) | [`inout-via-pointer.slang`](inout-via-pointer.slang) |


## Untested claims
| Claim | Reason | Anchor | Why untested |
| --- | --- | --- | --- |
| **`PyTorchCppBinding`** adjacent target arm (`#adjacent-targets`). Out of scope: shares some Phase B passes but emits via `TorchCppSourceEmitter`, not `CUDASourceEmitter`. | (unclassified) | [#adjacent-targets](../../../design/target-pipelines/cuda.md#adjacent-targets) | Reason and explanation to be refined by the next regeneration. |
| **`autodiff` / `higherOrderFunc` / `derivativePyBindWrapper` passes** (`checkAutodiffPatterns`, `specializeHigherOrderParameters`, `generateDerivativeWrappers`, `finalizeAutoDiffPass`, etc.). Covered by other bundles; the doc anchors them to Phase B but the emit-stage observable is a downstream language feature. | (unclassified) | [#autodiff](../../../design/target-pipelines/cuda.md#autodiff) | Reason and explanation to be refined by the next regeneration. |
| **`coverageTracing`-gated passes** (`instrumentCoverage`, `finalizeCoverageInstrumentationMetadata`). Coverage instrumentation is a debugging flag, not user-observable through text emit. | (unclassified) | [#coveragetracing](../../../design/target-pipelines/cuda.md#coveragetracing) | Reason and explanation to be refined by the next regeneration. |
| **`dynamicResourceHeap`**, **`meshOutput`**, **`bindingQuery`** Phase C gates. Each requires a feature surface that is not on the compute-test envelope. | (unclassified) | [#dynamicresourceheap](../../../design/target-pipelines/cuda.md#dynamicresourceheap) | Reason and explanation to be refined by the next regeneration. |
| **`validateAndRemoveAssumeAddress` with `validate=false`**. The doc states CUDA passes `validate=false` (line 960) but the consequence (no validation diagnostic on a malformed address-of) requires a deliberately-malformed input that is out of scope here. | (unclassified) | [#validateandremoveassumeaddress](../../../design/target-pipelines/cuda.md#validateandremoveassumeaddress) | Reason and explanation to be refined by the next regeneration. |
| **Pass-ordering claims** (Phase A passes 1-18, Phase B passes 1-62, Phase C passes 1-32). The doc enumerates the ordered list; pass _existence_ is observable through emit side effects, but pass _ordering_ would require `-dump-ir` cross-pass comparison without doc-anchored ordering markers. Covered by `pipeline/05-ir-passes`. | implementation-detail | (unspecified) | Internal compiler choice (pass ordering, hoistability decisions, deduplication) with no test-directive that reveals it. |


## Doc gaps observed
| Anchor | Kind | Gap | Suggested addition |
| --- | --- | --- | --- |
| [#prelude-symbol-emit-shape](../../../design/target-pipelines/cuda.md#prelude-symbol-emit-shape) | undocumented-behavior | The doc does not pin the specific CUDA-prelude macros and helper symbols (`SLANG_INFINITY`, `__half(...)`, `make_float2`, `tex2DLod`, `FixedArray<T, N>`) that the emitter relies on for numeric and texture boundaries. The boundary tests anchor each through its parent claim section, but a single doc table listing "prelude-symbol → emit-shape" would let boundary tests reference the symbols directly. |  |
| [#int8t128](../../../design/target-pipelines/cuda.md#int8t128) | undocumented-behavior | The doc does not state how out-of-range signed-integer literals (e.g. `int8_t(128)`) are handled by the CUDA pipeline: observed behavior is silent two's-complement wrap with no diagnostic, but the source doc does not anchor this. No negative test was added for this boundary; the documented contract is missing. |  |
| [#numthreadsn11](../../../design/target-pipelines/cuda.md#numthreadsn11) | undocumented-behavior | The doc does not specify the upper-bound for `[numthreads(N,1,1)]` on CUDA emit. Observed: N=1024 (CUDA hardware max-per-dim) compiles cleanly; N=0 is rejected at check time (diagnostic `E31102`). The boundary tests anchor the positive ends to the Phase D emit-wrapping claim, but the upper-bound number is not documented. |  |
| [#include](../../../design/target-pipelines/cuda.md#include) | undocumented-behavior | The doc's Phase D table mentions `CUDASourceEmitter` but does not name `#include "slang-cuda-prelude.h"` or `extern "C" __global__ void` as the canonical CUDA emit-prelude markers, or `extern "C" __constant__ GlobalParams_0` as the canonical resource-collection marker. | A one-line statement of these emit-prelude facts would let tests anchor them precisely; this bundle anchors them to the general `#phase-d-cuda-emit-and-downstream-tools` section. |
| [#legalizeentrypointvaryingparamsforcuda](../../../design/target-pipelines/cuda.md#legalizeentrypointvaryingparamsforcuda) | undocumented-behavior | The doc states `legalizeEntryPointVaryingParamsForCUDA` restructures kernel-entry-point parameter shapes but does not give the exact text-emit lowering of `SV_DispatchThreadID` (`blockIdx * blockDim + threadIdx`). Documenting the lowering expression would let a test pin the expression instead of inferring it from the source. |  |
| [#lowerimmutablebufferloadforcuda](../../../design/target-pipelines/cuda.md#lowerimmutablebufferloadforcuda) | undocumented-behavior | The doc's `## lowerImmutableBufferLoadForCUDA` says the pass translates loads to `__ldg(...)` but does not state that struct-typed loads go through a generated `slang_ldg` helper that issues per-field `__ldg(&ptr->field)` reads. Documenting the per-field expansion would let the test pin its shape. |  |
| [#applyvariablescopecorrection](../../../design/target-pipelines/cuda.md#applyvariablescopecorrection) | undocumented-behavior | The doc lists `applyVariableScopeCorrection` as running for CUDA but does not name an observable CUDA-emit pattern. No test. |  |
| [#phase-b-](../../../design/target-pipelines/cuda.md#phase-b-) | undocumented-behavior | The doc's Phase B table lists `lowerBuiltinTypesForKernelEntryPoints` as stripping shader types from kernel signatures and replacing them with CUDA primitives, but does not enumerate the Slang -> CUDA-primitive substitutions (e.g. `Texture2D -> CUtexObject`, `SamplerState` unchanged). | Listing the mapping would let a test pin each substitution. Observed substitutions worth documenting: all read-only `Texture1D` / `Texture2D` / `Texture3D` / `TextureCube` / `Texture2DArray` collapse to `CUtexObject`, while RW textures (`RWTexture2D`, `RWTexture3D`, etc.) collapse to `CUsurfObject`. The per-rank distinction is observable only at the call site (`tex1DLod`, `tex3DLod`, `texCubemapLod`, `tex2DLayeredLod`, `surf2Dwrite`, `surf3Dwrite`, ...). A doc subsection under `#phase-b-...` (or a Texture-types section) with the table would let texture-variant tests anchor each substitution. |
| [#synthesizeactivemask](../../../design/target-pipelines/cuda.md#synthesizeactivemask) | undocumented-behavior | The doc's `## synthesizeActiveMask` describes converting IR-level active-mask references into a synthesized mask parameter but does not name the Slang-language surface (`WaveActiveSum` / `WaveActiveMin` / `__shfl_sync` family) that fires the pass, nor the CUDA emit fingerprint (`_waveSum` / `_waveOpSum` / similar prelude helpers carrying a `WarpMask` operand). The test now anchors on `_waveSum` from `hlsl.meta.slang` line 18378, but the doc itself does not pin the relationship between the Slang intrinsic and the CUDA emit helper. | Add a "Wave-intrinsic to CUDA-emit helper" mapping subsection under `## synthesizeActiveMask` listing the user-level intrinsics (`WaveActiveSum`, `WaveActiveMin`, etc.) and the prelude helper they lower to (`_waveSum`, `_waveMin`, ...). |
| [#collectoptixentrypointuniformparams](../../../design/target-pipelines/cuda.md#collectoptixentrypointuniformparams) | undocumented-behavior | The doc's `## collectOptiXEntryPointUniformParams` describes SBT-bound uniform handling but does not name the observable CUDA-emit symbol prefix per OptiX stage (`__raygen__<name>`, `__closesthit__<name>`, `__anyhit__<name>`, `__miss__<name>`) that the `CUDASourceEmitter` wraps each entry point with (see `slang-emit-cuda.cpp` line ~494). The test anchors on the source-file symbol-prefix table, not on a doc claim. | Add a per-OptiX-stage prefix table to `## collectOptiXEntryPointUniformParams` so tests can anchor each stage's emit symbol shape directly. |
| [#cuda-has-no-iterative-passes-in-linkandoptimizeir](../../../design/target-pipelines/cuda.md#cuda-has-no-iterative-passes-in-linkandoptimizeir) | undocumented-behavior | The doc states "CUDA has no iterative passes in `linkAndOptimizeIR`" but the consequence is not observable through `slangc -target cuda` text. No test. |  |
| [#adddenormalmodedecorations](../../../design/target-pipelines/cuda.md#adddenormalmodedecorations) | undocumented-behavior | The doc lists `addDenormalModeDecorations` as always-on in Phase A but does not name an observable CUDA-emit marker for denormal mode. No test. |  |
| [#codegentarget](../../../design/target-pipelines/cuda.md#codegentarget) | missing-surface | The doc's intro paragraph names `CodeGenTarget::CUDASource`, `CUDAHeader`, and `PTX` as the three sibling CUDA targets but does not give them their own anchorable subsection — the `#codegentarget` fragment does not resolve to a heading in the doc. Tests that want to pin the `-target cuda-header` / `-target ptx` CLI behavior end up anchoring to the most-specific phase section instead (Phase D / `## Downstream nvrtc`). | Promote the `CodeGenTarget` enumeration block from the intro paragraph into a small `## CodeGenTarget values` section so the three sibling targets each have an anchor a test can cite. |
| [#downstream-nvrtc](../../../design/target-pipelines/cuda.md#downstream-nvrtc) | undocumented-behavior | The doc's `## Downstream nvrtc` says PTX is produced via nvrtc but does not name the canonical PTX-text markers (`.version`, `.target`, `.visible .entry`) that a test can fingerprint the output against. Tests for the PTX downstream end up matching prelude-format strings that are nvrtc/PTX-ISA artifacts rather than Slang-documented invariants. | Add a "PTX text fingerprint" sentence to `## Downstream nvrtc` listing the canonical PTX header directives (`.version`, `.target`, `.address_size`) and the `.visible .entry <name>` pattern that wraps each CUDA `__global__` kernel as the test-stable surface. |
| [#processlaterequirecapabilityinsts](../../../design/target-pipelines/cuda.md#processlaterequirecapabilityinsts) | undocumented-behavior | The doc's Phase C table lists `processLateRequireCapabilityInsts` and `cleanUpVoidType` but does not name observable CUDA-emit markers for them. No test. |  |
| [#phase-d](../../../design/target-pipelines/cuda.md#phase-d) | undocumented-behavior | The doc's `## Phase D` table lists `simplifyForEmit` but the effect is observable only as an absence of redundant variables in the emitted text — there is no doc-anchored positive marker. No test. |  |
