Skip to content

fix(mir-lower): support recursive packed AS3 carrier local projections - #1330

Open
uurl wants to merge 3 commits into
NVIDIA:mainfrom
uurl:fix/recursive-packed-as3-local-projections
Open

uurl wants to merge 3 commits into
NVIDIA:mainfrom
uurl:fix/recursive-packed-as3-local-projections

Conversation

@uurl

@uurl uurl commented Sep 25, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1094

Summary

Extend the packed-AS3 carrier-local contract introduced by #1327 to support:

  • multiple direct AS3 pointer leaves;
  • AS3 leaves nested inside structs and tuples;
  • bounded fixed arrays containing AS3 leaves;
  • recursive field projections;
  • array-element projections.

The implementation preserves #1327's closed-world model: the complete MIR address-use graph is validated before dialect conversion, and lowering-private physical type facts are attached only after the whole graph succeeds.

Carrier identity is never reconstructed from LLVM defining operations, OperandsInfo, or converted GEP history.

Representation and projection contract

Semantic values retain AS3 pointers while compiler-owned local storage uses the target-stable generic-pointer carrier:

semantic: <{ ..., p3, nested { p3 }, [p3; N], ... }>
storage:  <{ ..., p0, nested { p0 }, [p0; N], ... }>

Conversions remain explicit at load/store boundaries.

The verified address graph now admits:

carrier alloca
    |
    +-- field_addr
    |      +-- field_addr -> ...
    |      `-- array_element_addr -> ...
    |
    +-- load
    `-- store

Each projection derives its physical pointee from the already-proven parent carrier type.

mir.field_addr supports recursive struct/tuple projections, and mir.array_element_addr uses the verified physical carrier element type. Ordinary non-carrier addressing is unchanged.

Bounds and fail-closed behavior

The existing 16-leaf array rewrite budget is reused. Local-storage shape admission remains independently classified, so future internal-ABI shape widening cannot implicitly widen carrier-local support.

Carrier addresses still fail closed across:

  • calls;
  • casts;
  • block arguments;
  • returns;
  • arbitrary pointer offsets;
  • unknown or unmodelled uses.

AS3 pointer vectors and arbitrary packed-AS3 memory remain unsupported.

Tests

Added focused coverage for:

  • recursive/multi-leaf admission;
  • bounded arrays, including exact-bound acceptance and above-bound rejection;
  • vector rejection;
  • nested struct and tuple projections;
  • array-element projections;
  • recursive zero-sized projections;
  • exact physical carrier child types;
  • existing call/cast/block-argument rejection.

packed_aggregate_abi now exercises multiple direct leaves, nested structs, nested tuples, and bounded AS3 pointer arrays through carrier-local projections.

Validation

cargo fmt --all
cargo fmt --all -- --check
git diff --check

cargo test -p mir-lower packed_shared_local_storage -- --nocapture
cargo test -p mir-lower packed_shared_internal_abi -- --nocapture
cargo test -p mir-lower --all-targets
cargo clippy -p mir-lower --all-targets -- -D warnings

cargo oxide build packed_aggregate_abi
cargo oxide run packed_aggregate_abi
CUDA_OXIDE_NO_OPT=1 cargo oxide run packed_aggregate_abi
cargo oxide run addressof_sharedarray

Results:

packed-AS3 carrier-local tests: 12 passed
packed-AS3 internal ABI tests:  9 passed
mir-lower unit tests:           308 passed
lowering tests:                 147 passed
clippy -D warnings:             pass

Both optimized and CUDA_OXIDE_NO_OPT=1 packed_aggregate_abi executions pass. addressof_sharedarray also continues to pass.

Out of scope

This PR does not add carrier-address transport through calls, block arguments, casts, returns, or arbitrary pointer arithmetic, nor support for AS3 pointer vectors, arbitrary/device-global/kernel-entry packed-AS3 carrier storage, or AS3-containing enum locals.

Signed-off-by: Raul Estrada <raulestradaa@gmail.com>
@uurl
uurl force-pushed the fix/recursive-packed-as3-local-projections branch from f210339 to 818c88d Compare October 8, 2026 04:51
@uurl
uurl requested a review from nihalpasham as a code owner October 8, 2026 04:51
@copy-pr-bot

copy-pr-bot Bot commented Oct 8, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@nihalpasham nihalpasham added the cuda-oxide SIMT programming model: rustc backend, cargo oxide, cuda-device, cuda-host, book label Oct 11, 2026
@nihalpasham

Copy link
Copy Markdown
Collaborator

The nested and array cases this adds read and write with the wrong alignment, and the kernel faults:

%v22 = load ptr, ptr %v21, align 8    ; %v21 is byte offset 1 of an align-1 alloca
  • On an RTX 5090 this faults with misaligned address: a runtime-indexed [[p3; 2]; 2] at -O2 and under libNVVM, a nested read split from its store by a branch under CUDA_OXIDE_NO_OPT=1, and packed_aggregate_abi itself under CUDA_OXIDE_DEBUG=full.
  • The CUDA_OXIDE_NO_OPT=1 run in the description does not catch it: llc forwards the stores to the loads, so no local load executes. No test asserts an alignment.
  • The admission classifier and the array alignment helpers are copies of code in func_abi.rs and addressing.rs; the bug came along with the copy.

To land this: stamp every carrier projection with the alignment it really has (gcd of the root alignment and the byte offset, 8-byte carrier stride for array elements); unit tests asserting align 1 on nested and array-element loads and stores; kernels in packed_aggregate_abi that keep the slot alive (runtime index, branch between store and read) passing at -O2, NO_OPT, DEBUG=full and --emit-nvvm-ir under memcheck; share the classifier and helpers instead of copying them; merge main in before I vet CI.

@nihalpasham nihalpasham left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed 818c88dc: changes requested. The landing list is in #1330 (comment).

@nihalpasham nihalpasham added needs-changes Review found changes required before this PR can land IR-lowering Lowering between dialects (dialect-mir to LLVM dialect) codegen Device code-generation pipeline (Rust MIR to IR to PTX) enhancement New feature or request soundness-audit Correctness case under active maintainer audit; not cleared for merge yet labels Oct 15, 2026
@uurl

uurl commented Oct 16, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the requested changes in 3ea241f after merging main.

  • Propagated proven alignment through recursive carrier field and array projections.
  • Added LLVM load/store alignment assertions and runtime-indexed regression coverage.
  • Consolidated the shared shape classifier and alignment helpers.
  • Validated 309 unit tests, 147 integration tests, and Clippy with -D warnings.
  • Compute Sanitizer reports 0 errors on RTX 5090 (sm_120a) across optimized PTX, CUDA_OXIDE_NO_OPT=1,
    CUDA_OXIDE_DEBUG=full, and NVVM IR.

The branch is ready for CI vetting and re-review.

@uurl
uurl requested a review from nihalpasham October 16, 2026 04:34

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

codegen Device code-generation pipeline (Rust MIR to IR to PTX) cuda-oxide SIMT programming model: rustc backend, cargo oxide, cuda-device, cuda-host, book enhancement New feature or request IR-lowering Lowering between dialects (dialect-mir to LLVM dialect) needs-changes Review found changes required before this PR can land soundness-audit Correctness case under active maintainer audit; not cleared for merge yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support recursive and multi-leaf packed AS3 carrier locals

3 participants