Skip to content

feat(fuzzer): generate device static operands - #1245

Closed
uurl wants to merge 1 commit into
NVIDIA:mainfrom
uurl:feat/rustlantis-device-statics
Closed

uurl wants to merge 1 commit into
NVIDIA:mainfrom
uurl:feat/rustlantis-device-statics

Conversation

@uurl

@uurl uurl commented Sep 6, 2026 •

Copy link
Copy Markdown
Contributor

What this adds

Rustlantis can generate scalar static and static mut declarations and use the custom-MIR Static / StaticMut operands. The production adapter preserves those declarations in generated CPU/GPU cases.

before: generated programs cannot obtain pointers to static allocations
after:  generated programs can read, write and dump scalar static values

static_count defaults to zero. Enabled statics use persistent allocations and global-root provenance in the place graph.

Alias model

Static reacquisition reuses persistent global-root provenance rather than creating an independent tag.

References and raw pointers derived through existing static-derived pointers preserve their source provenance restrictions across:

  • reference creation;
  • pointer/reference copies;
  • local overwrite;
  • function arguments;
  • call/return cleanup.

Mutable references now require write permission on the selected pointee path, so &mut (*shared) cannot be created from read-only shared provenance.

Retiring the original graph alias therefore cannot grant stronger permissions to surviving derived aliases. Direct StaticMut raw-pointer paths remain writable.

Verification

Rebased onto NVIDIA/cuda-rust main (1691162ab920).

Current commit: 838c14b754.

All nine modified files are now under cuda-oxide/. The commit retains its DCO sign-off, and GitHub reports the PR as mergeable.

Post-rebase validation

Validated at 838c14b754:

  • git diff --check upstream/main...HEAD: passed.
  • cargo fmt --all -- --check: passed.
  • cargo check --workspace: passed.
  • cargo test -p generate: 38/38 passed.
  • cargo test --workspace: 61/61 passed.

Regression coverage includes:

  • mutable-reference selection requiring write permission;
  • rejecting mutable reborrows from shared static provenance;
  • preserving inherited permissions across reference and pointer copies;
  • preserving inherited permissions across call/return cleanup;
  • shared-derived raw pointers remaining non-writable after source overwrite;
  • shared-derived raw pointers remaining restricted across call/return;
  • direct StaticMut raw-pointer returns remaining writable.

Previous generation and GPU validation

The following checks were completed at 182694a80 against the pre-monorepo main (66ff93c1). They have not been rerun after the monorepo rebase:

  • With static_count = 0, full-config seeds 0–19 were byte-identical to the previous main.
  • With static_count = 8, seeds 0–499 generated successfully.
  • Seed 0 with statics enabled completed with matching CPU/GPU traces.
  • Generated PTX contained .global device symbols and ld.global / st.global operations.

Partially addresses #1162.
Supersedes #1163.

@nihalpasham nihalpasham added fuzzer Fuzzing infrastructure (rustlantis, difftest) needs-changes Review found changes required before this PR can land safety Memory safety, soundness, or undefined behavior tests Adds or improves test coverage labels Sep 15, 2026

@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 878a0bcf: changes requested.

  • The scalar workload works: seed 0 matches CPU/GPU traces, and the zero-static-count control preserves the old seed output.
  • Static reacquisition needs a consistent alias rule. It currently creates a fresh tag that bypasses an existing exclusive borrow:
live &mut global passed into a call
  +-- independent StaticMut(global) -> graph permits read/write
  • Model global-root provenance across calls and derived aliases, and reject unsupported combinations. Add graph controls for repeated acquisition, live reference arguments and frame exit.
  • Rebase onto current main and sign the revision.

This is needed before generated differences can be trusted as compiler findings. #1162 remains partial.

@uurl

uurl commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

@nihalpasham updated in 078845f64 and rebased onto current main.

The static aliasing model now keeps stable global-root provenance across reacquisition and calls, with coverage for repeated acquisition, live reference arguments, and frame exit.

generate passes 26/26, seed 0 still matches CPU/GPU, and seed 33 with static_count = 0 remains byte-identical to main.

Ready for re-review.

@uurl
uurl requested a review from nihalpasham September 15, 2026 08:43

@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.

The persistent global-root provenance addresses the earlier reacquisition problem, but 078845f6 still needs changes before the generated programs can be trusted.

  • A write through the static root removes a shared alias's memory tag, but is_ref_valid() still accepts that alias because its pointee is initialized. The argument selector can then copy it into a call, where protect_tag() panics with tag has registered pointee ranges.
  • This also affects the default path: with the checked-in config and static_count = 0, main completes seeds 0–19; this revision panics on 15, and the five successful outputs all change. The tiny seed-33 control misses the call paths.

Please make reference validity and tag invalidation agree across copies, arguments and frame exit, and add regressions for invalidated aliases and the full zero-static configuration. Removing the assertion alone would hide the inconsistent state.

#1162 remains partially addressed.

@uurl
uurl force-pushed the feat/rustlantis-device-statics branch from 078845f to d1b2adc Compare September 18, 2026 06:24
@uurl

uurl commented Sep 18, 2026 •

Copy link
Copy Markdown
Contributor Author

@nihalpasham updated in d1b2adca7.

Reference validity now follows memory-tag invalidation, with regressions for the invalidated-alias and argument-selection paths.

I also reran the full-config controls: seeds 0–19 with static_count = 0 are byte-identical to main, including seed 15, and 200/200 seeds with static_count = 8 generate without the call-protection panic.

generate is 28/28 and the Rustlantis workspace checks/tests pass.

Ready for re-review.

@uurl
uurl requested a review from nihalpasham September 18, 2026 06:27

@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.

I rechecked d1b2adca7. The invalidated-reference and full-config zero-static regressions from the last review are fixed.

The new tag cleanup still allows a write through a raw pointer derived from a shared reference. For scalar statics static mut S: i32 and static T: i32, this custom-MIR sequence is enough:

p = StaticMut(S);
s = &(*p);
q = core::ptr::addr_of_mut!(*s);
s = Static(T);
*q = 9;
  • Before reassigning s, the model correctly rejects writes through q. Afterwards, remove_edge removes the shared tag because its final direct graph alias disappeared. The derived raw pointer survives, becomes writable, and is selectable by the ordinary assignment generator.
  • The same permission change occurs when a callee returns such a raw pointer and frame cleanup removes its shared local. Returning a raw pointer obtained directly from StaticMut works and needs to remain supported.

Creating a mutable raw pointer in custom MIR does not give it permission to write through shared-derived provenance. Reassigning the shared local or ending its frame cannot grant that permission. See Rust's pointer provenance contract.

Please preserve inherited permissions when retiring graph aliases, consistently across pointer derivation, copies, overwrites and calls/returns. Add regressions for both cases above and retain the direct-StaticMut return control. Keeping every old tag indefinitely would also retain obsolete exclusive borrows, so that alone is not a complete repair.

The broader generation sweep passed 3,290 configuration/seed cases; zero-static output matches both baselines. After local mechanical integration with current main, 46 Rustlantis tests pass, but both new alias regressions still fail. This is the generator accepting an invalid write, not evidence of a CUDA backend miscompile.

Please also rebase onto current main, adapt the new calls to the checked Place API, and sign the revision. #1162 remains partially addressed.

@uurl
uurl force-pushed the feat/rustlantis-device-statics branch 2 times, most recently from 2ab9a89 to 99b2ca4 Compare September 18, 2026 09:06
@uurl

uurl commented Sep 18, 2026

Copy link
Copy Markdown
Contributor Author

@nihalpasham updated in 99b2ca4ec and rebased onto main b9847e95.

Raw pointers derived through shared static references now preserve the inherited provenance across overwrites and call/return cleanup. I added regressions for both cases, plus a positive control confirming that a raw pointer returned directly from StaticMut remains writable.

generate is 34/34 and the Rustlantis workspace checks/tests pass. Full-config static_count = 0 seeds 0–19 remain byte-identical to main, including seed 15; static_count = 8 generates 200/200 seeds successfully; and seed 0 still matches CPU/GPU with the expected PTX global-memory operations.

Ready for re-review.

@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.

The persistent static roots and adapter preservation are useful, but the shared-reference permissions still have a hole in the Ref path.

  • generate_ref can select &mut (*shared) using only read permission. set_ref gives it a fresh exclusive tag.
  • Overwriting shared then removes its shared tag, so the derived &mut becomes writable. Overwriting a local cannot grant write permission to a reference derived through shared access.
  • I added an isolated graph check for that sequence; it fails on this head. The same custom-MIR sequence fails Miri Tree Borrows at the write. All 500 generation seeds completed, which does not establish that their programs are valid.

Please carry the source permissions through reference creation, copies and call/return cleanup, with regressions for each. This partially addresses #1162; the alias model needs fixing before it can land.

@uurl
uurl force-pushed the feat/rustlantis-device-statics branch from 99b2ca4 to 182694a Compare September 23, 2026 08:29
@uurl
uurl requested a review from nihalpasham September 23, 2026 08:32
Signed-off-by: Raul Estrada <raulestradaa@gmail.com>
@uurl
uurl force-pushed the feat/rustlantis-device-statics branch from 182694a to 838c14b Compare October 8, 2026 04:48
@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.

@uurl

uurl commented Oct 8, 2026

Copy link
Copy Markdown
Contributor Author

@nihalpasham I've rebased this PR onto the new NVIDIA/cuda-rust monorepo (838c14b). All nine files are now under cuda-oxide/, and the PR is mergeable.

The latest revision addresses the shared-reference provenance issue from your last review, with regressions covering mutable reborrows, inherited permissions, copies, and call/return cleanup.

Post-rebase validation passed: formatting, workspace check, and all 61 Rustlantis workspace tests.

Ready for re-review when you have time.

Thank you.

@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

Closing this one for now:

  • It has been open since August and is on its fifth round. The alias model still lets the generator write through a reference that Miri Tree Borrows rejects: a reference moved, copied or passed into a call from a static keeps the source tag instead of getting a fresh child tag.
  • The head is still on the August nightly, and the new tests cover the graph API rather than generated programs.

Statics in the fuzzer are still worth having. When this is picked up again, start from fresh tags for moved and passed references and use a Miri sweep as the oracle. A new PR against current main is the cleaner path than reviving this one. #1162 stays open.

@nihalpasham nihalpasham added declined PR intentionally not merged (closed without merging) and removed needs-changes Review found changes required before this PR can land labels Oct 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cuda-oxide SIMT programming model: rustc backend, cargo oxide, cuda-device, cuda-host, book declined PR intentionally not merged (closed without merging) fuzzer Fuzzing infrastructure (rustlantis, difftest) safety Memory safety, soundness, or undefined behavior tests Adds or improves test coverage

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants