diff --git a/.github/workflows/examples-compile.yml b/.github/workflows/examples-compile.yml index 86db9f489b..2b4ff38602 100644 --- a/.github/workflows/examples-compile.yml +++ b/.github/workflows/examples-compile.yml @@ -4,7 +4,7 @@ name: examples-compile # Path-filtered SIMT lane (same roots as ci.yml). on: push: - branches: [main] + branches: [main, bloomery] paths: - 'cuda-oxide/**' - 'cuda-bindings/**' @@ -15,7 +15,7 @@ on: - 'Cargo.lock' - '.github/workflows/**' pull_request: - branches: [main] + branches: [main, bloomery] paths: - 'cuda-oxide/**' - 'cuda-bindings/**' @@ -129,6 +129,25 @@ jobs: cuda-oxide/scripts/smoketest.sh --compile-only --no-color + - name: Compile shared-memory helper calls + timeout-minutes: 10 + working-directory: cuda-oxide + env: + CUDA_TOOLKIT_PATH: ${{ steps.cuda-toolkit.outputs.CUDA_PATH }} + CUDA_OXIDE_LLC: /usr/bin/llc-22 + CARGO_TARGET_DIR: ${{ runner.temp }}/examples-shared-target + CARGO_INCREMENTAL: "0" + run: | + set -euo pipefail + sysroot="$(rustc --print sysroot)" + export LIBRARY_PATH="${sysroot}/lib:${LIBRARY_PATH:-}" + export LD_LIBRARY_PATH="${sysroot}/lib:${LD_LIBRARY_PATH:-}" + + for features in local-helper cross-crate-helper; do + cargo oxide build shared_memory_helper --arch sm_90 --features "$features" \ + 2>&1 | tee "${RUNNER_TEMP}/shared-memory-${features}-build.log" + done + - name: Artifact modes keep shared Cargo dependencies fresh timeout-minutes: 10 working-directory: cuda-oxide @@ -266,6 +285,7 @@ jobs: # `if-no-files-found: ignore` below made that silent. path: | ${{ runner.temp }}/smoketest-logs/ + ${{ runner.temp }}/shared-memory-*-build.log ${{ runner.temp }}/vecadd-*-build.log ${{ runner.temp }}/iket-trace-*-build.log ${{ runner.temp }}/cross-crate-*-build.log diff --git a/cuda-oxide/crates/mir-importer/src/translator/terminator/helpers.rs b/cuda-oxide/crates/mir-importer/src/translator/terminator/helpers.rs index a85b623374..d9d45fef48 100644 --- a/cuda-oxide/crates/mir-importer/src/translator/terminator/helpers.rs +++ b/cuda-oxide/crates/mir-importer/src/translator/terminator/helpers.rs @@ -383,6 +383,45 @@ pub fn emit_function_call( } } + // Ordinary Rust helper signatures also expose generic pointers. Resolve + // the monomorphized operand type (not an unresolved trait signature), and + // adapt only address space. All other type/provenance mismatches still + // reach the independently typed callee's verifier unchanged. + if external_callee_type.is_none() { + for (argument, operand) in arg_values.iter_mut().zip(args) { + if argument + .get_type(ctx) + .deref(ctx) + .downcast_ref::() + .is_none() + { + continue; + } + let rust_type = match operand.ty(body.locals()) { + Ok(ty) => ty, + Err(error) => { + return input_err!( + loc.clone(), + TranslationErr::unsupported(format!( + "failed to resolve Rust call argument type: {error:?}" + )) + ); + } + }; + let declared = crate::translator::types::translate_type(ctx, &rust_type)?; + let (normalized, tail) = normalize_foreign_pointer_argument( + ctx, + *argument, + declared, + block_ptr, + last_op, + loc.clone(), + ); + *argument = normalized; + last_op = tail; + } + } + let (prepared_destination, prepared_last_op) = prepare_destination_write( ctx, body, @@ -445,8 +484,8 @@ pub fn emit_function_call( } } -/// Adapt a foreign-call pointer argument only when the address space is the -/// sole difference from its declared ABI parameter type. +/// Adapt a foreign or Rust call pointer argument only when the address space +/// is the sole difference from its declared parameter type. fn normalize_foreign_pointer_argument( ctx: &mut Context, value: Value, diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_memory_helper/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_memory_helper/README.md index 8947f5a809..b9d5039ec9 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_memory_helper/README.md +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_memory_helper/README.md @@ -51,9 +51,8 @@ cargo oxide build shared_memory_helper --arch sm_120a crates/rustc-codegen-cuda/examples/shared_memory_helper/target/release/shared_memory_helper ``` -Build each helper variant separately; these currently fail as described below. -Do not run a binary left over from the successful control build as evidence -that a failed helper build worked. +Build each helper variant separately, then run its binary with the same +sanitizer commands. Stop on a failed build to avoid running a stale binary. ```bash cargo oxide build shared_memory_helper \ @@ -67,49 +66,18 @@ Repeat with `--features local-helper,force-inline`, `cross-crate-helper,heuristic-inline` to compare inlining policies. Set `CUDA_OXIDE_DUMP_MIR=1` to inspect the imported helper definition and call. -## Observed results +## Expected results -Tested on 2026-09-17 against `main` at -`7ce30ec798c490e6ed772dfcbad193b3733fe55a`, with this example added, on an -RTX 5090, NVIDIA driver 580.173.02, and CUDA tools 13.3. +The direct control and both helper variants must build and report a `PASS` +marker after checking the data and barrier results. The `examples-compile` +workflow builds both helper variants on `main` and `bloomery` with their +default `#[inline(never)]` policy. -| Variant | Result | -| --- | --- | -| Direct control | Builds; GPU checks pass | -| Local helper, all three inline policies | MIR verification rejects the call | -| Dependency helper, all three inline policies | Same rejection | - -Both Compute Sanitizer runs of the direct control reported: - -```text -PASS direct: 9 launches, 36 CTA data/barrier checks -========= ERROR SUMMARY: 0 errors -``` +The imported argument has address space 3 (shared memory), while the helper +parameter has address space 0 (generic memory). The importer adapts that +address-space difference before call verification. Pointee, mutability and +pointer kind must still match. -All six helper builds failed with: - -```text -MirCallOp argument 0 type does not match callee signature -``` - -The imported call passes `mir.ptr` -(shared memory), while the helper parameter is -`mir.ptr` (generic memory). The -helper body is present in the imported module, including for the dependency -crate. Ordinary Rust calls do not receive the address-space adaptation that -the importer applies to foreign calls. Strict call verification rejects the -mismatch before backend code generation. Requesting `inline(always)` did not -remove the call before this verification in the tested builds. - -This reproduces a compile-time rejection of this raw-byte-pointer boundary. -It does not demonstrate silent miscompilation or prove runtime correctness -of a surviving helper call, because no helper variant reached GPU execution. -The dependency test imports available MIR across crates; it does not test an -opaque, separately linked device binary. The runtime control checks one-thread +The dependency variant imports available MIR across crates; it does not test +an opaque, separately linked device binary. The runtime checks one-thread barrier behavior, not synchronization between multiple threads or TMA traffic. - -The diagnostic currently exposes an internal MIR mismatch. This reproducer -does not change the diagnostic or implement the missing call conversion. -Pointers whose pointee is `Barrier` or `SharedArray` already receive a shared -address space, so this result should not be generalized to every helper that -accepts shared memory.