diff --git a/Cargo.lock b/Cargo.lock index 427b364038..22a56faff3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -498,8 +498,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-core/Cargo.toml b/cuda-core/Cargo.toml index 8eeb103c93..c24bd5dce2 100644 --- a/cuda-core/Cargo.toml +++ b/cuda-core/Cargo.toml @@ -17,7 +17,7 @@ cuda-bindings = { version = "=0.4.0", path = "../cuda-bindings" } cuda-core-derive = { version = "=0.4.0", path = "../cuda-core-derive" } anyhow = "1" half = { version = "2" } -oxide-artifacts = { version = "0.2.1", features = ["object-read"] } +oxide-artifacts = { version = "0.2.1", path = "../cuda-oxide/crates/oxide-artifacts", features = ["object-read"] } [dev-dependencies] trybuild = "1" diff --git a/cuda-core/src/simt/embedded.rs b/cuda-core/src/simt/embedded.rs index c146f58753..d63fed04c4 100644 --- a/cuda-core/src/simt/embedded.rs +++ b/cuda-core/src/simt/embedded.rs @@ -46,8 +46,19 @@ impl EmbeddedModule { pub fn load(&self, ctx: &Arc) -> Result, EmbeddedModuleError> { let image = loadable_payload(&self.bundle).expect("EmbeddedModule always has a loadable payload"); - ctx.load_module_from_image(image) - .map_err(EmbeddedModuleError::Driver) + ctx.load_module_from_image_with_launch_facts( + image, + self.bundle + .entries + .iter() + .filter_map(|entry| { + entry + .launch_facts + .map(|facts| (entry.symbol.clone(), facts)) + }) + .collect(), + ) + .map_err(EmbeddedModuleError::Driver) } } diff --git a/cuda-core/src/simt/launch.rs b/cuda-core/src/simt/launch.rs index ff1f37684b..49503c2974 100644 --- a/cuda-core/src/simt/launch.rs +++ b/cuda-core/src/simt/launch.rs @@ -64,6 +64,9 @@ mod sealed { pub trait KernelLaunchConfig: sealed::Sealed + Copy { #[doc(hidden)] fn __raw(self) -> LaunchConfig; + + #[doc(hidden)] + fn __auto_shared(self) -> bool; } /// A one-dimensional launch configuration. @@ -73,10 +76,20 @@ pub trait KernelLaunchConfig: sealed::Sealed + Copy { pub struct LaunchConfig1D { grid_x: u32, block_x: u32, - shared_mem_bytes: u32, + shared_mem_bytes: Option, } impl LaunchConfig1D { + /// Uses the kernel's prepared resource requirement for dynamic shared memory. + /// A range contract selects its minimum, raised by compiled facts if present. + pub const fn auto_shared(grid_x: u32, block_x: u32) -> Self { + Self { + grid_x, + block_x, + shared_mem_bytes: None, + } + } + /// Creates a one-dimensional launch configuration. /// /// Zero dimensions are reported when the configuration is prepared for a @@ -85,7 +98,7 @@ impl LaunchConfig1D { Self { grid_x, block_x, - shared_mem_bytes, + shared_mem_bytes: Some(shared_mem_bytes), } } } @@ -93,11 +106,15 @@ impl LaunchConfig1D { impl sealed::Sealed for LaunchConfig1D {} impl KernelLaunchConfig for LaunchConfig1D { + fn __auto_shared(self) -> bool { + self.shared_mem_bytes.is_none() + } + fn __raw(self) -> LaunchConfig { LaunchConfig { grid_dim: (self.grid_x, 1, 1), block_dim: (self.block_x, 1, 1), - shared_mem_bytes: self.shared_mem_bytes, + shared_mem_bytes: self.shared_mem_bytes.unwrap_or(0), } } } @@ -109,16 +126,26 @@ impl KernelLaunchConfig for LaunchConfig1D { pub struct LaunchConfig2D { grid: (u32, u32), block: (u32, u32), - shared_mem_bytes: u32, + shared_mem_bytes: Option, } impl LaunchConfig2D { + /// Uses the kernel's prepared resource requirement for dynamic shared memory. + /// A range contract selects its minimum, raised by compiled facts if present. + pub const fn auto_shared(grid: (u32, u32), block: (u32, u32)) -> Self { + Self { + grid, + block, + shared_mem_bytes: None, + } + } + /// Creates a two-dimensional launch configuration. pub const fn new(grid: (u32, u32), block: (u32, u32), shared_mem_bytes: u32) -> Self { Self { grid, block, - shared_mem_bytes, + shared_mem_bytes: Some(shared_mem_bytes), } } } @@ -126,11 +153,15 @@ impl LaunchConfig2D { impl sealed::Sealed for LaunchConfig2D {} impl KernelLaunchConfig for LaunchConfig2D { + fn __auto_shared(self) -> bool { + self.shared_mem_bytes.is_none() + } + fn __raw(self) -> LaunchConfig { LaunchConfig { grid_dim: (self.grid.0, self.grid.1, 1), block_dim: (self.block.0, self.block.1, 1), - shared_mem_bytes: self.shared_mem_bytes, + shared_mem_bytes: self.shared_mem_bytes.unwrap_or(0), } } } @@ -140,16 +171,26 @@ impl KernelLaunchConfig for LaunchConfig2D { pub struct LaunchConfig3D { grid: (u32, u32, u32), block: (u32, u32, u32), - shared_mem_bytes: u32, + shared_mem_bytes: Option, } impl LaunchConfig3D { + /// Uses the kernel's prepared resource requirement for dynamic shared memory. + /// A range contract selects its minimum, raised by compiled facts if present. + pub const fn auto_shared(grid: (u32, u32, u32), block: (u32, u32, u32)) -> Self { + Self { + grid, + block, + shared_mem_bytes: None, + } + } + /// Creates a three-dimensional launch configuration. pub const fn new(grid: (u32, u32, u32), block: (u32, u32, u32), shared_mem_bytes: u32) -> Self { Self { grid, block, - shared_mem_bytes, + shared_mem_bytes: Some(shared_mem_bytes), } } } @@ -157,11 +198,15 @@ impl LaunchConfig3D { impl sealed::Sealed for LaunchConfig3D {} impl KernelLaunchConfig for LaunchConfig3D { + fn __auto_shared(self) -> bool { + self.shared_mem_bytes.is_none() + } + fn __raw(self) -> LaunchConfig { LaunchConfig { grid_dim: self.grid, block_dim: self.block, - shared_mem_bytes: self.shared_mem_bytes, + shared_mem_bytes: self.shared_mem_bytes.unwrap_or(0), } } } @@ -188,6 +233,9 @@ pub enum BlockRequirement { /// The dynamic shared-memory sizes accepted by a kernel. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum DynamicSharedMemoryRequirement { + /// Use the finalized allocation and alignment from this concrete kernel's + /// compiled artifact. Preparation fails when those facts are absent. + Inferred, /// The launch must allocate exactly `bytes` bytes. Exact { /// Required bytes per block. @@ -429,6 +477,11 @@ pub enum LaunchContractError { /// Number of coordinate values required on this axis. positions: u64, }, + /// An inferred contract was loaded without compiled resource facts. + MissingCompiledLaunchFacts { + /// Kernel being prepared. + kernel: &'static str, + }, /// A shared-memory alignment was not a nonzero power of two. InvalidSharedMemoryAlignment { /// Kernel being prepared. @@ -671,6 +724,8 @@ impl Display for LaunchContractError { f, "{kernel}: Grid.{axis:?} {grid} * Block.{axis:?} {block} requires {positions} coordinates, exceeding the u32 range" ), + Self::MissingCompiledLaunchFacts { kernel } => write!(f, + "{kernel}: compiled launch facts are missing; rebuild this kernel with the CUDA compiler"), Self::InvalidSharedMemoryAlignment { kernel, alignment } => write!( f, "{kernel}: dynamic shared-memory alignment {alignment} is not a nonzero power of two" @@ -893,15 +948,25 @@ impl PreparedLaunch { /// /// `C::SPEC` must truthfully describe the compiled device function, /// including its rank, fixed block assumptions, shared-memory layout, and - /// launch mode. cuda-oxide's macros generate that marker and uphold this - /// relationship. + /// launch mode. Any `function.launch_facts()` must truthfully describe this + /// exact loaded image and entry; inferred contracts obtain their allocation + /// from those facts. cuda-oxide's macros and matching artifact loader uphold + /// this relationship. #[doc(hidden)] pub unsafe fn __prepare( function: CudaFunction, config: C::Config, ) -> Result { - let raw = config.__raw(); - validate_static(C::SPEC, raw)?; + let spec = resolve_compiled_spec(C::SPEC, function.launch_facts())?; + let mut raw = config.__raw(); + if config.__auto_shared() { + raw.shared_mem_bytes = match spec.dynamic_shared_memory { + DynamicSharedMemoryRequirement::Exact { bytes, .. } => bytes, + DynamicSharedMemoryRequirement::Range { min_bytes, .. } => min_bytes, + DynamicSharedMemoryRequirement::Inferred => unreachable!("resolved above"), + }; + } + validate_static(spec, raw)?; let context = function.context(); let limits = context.launch_limits()?; @@ -909,17 +974,17 @@ impl PreparedLaunch { let static_shared = function.static_shared_memory_bytes()?; let function_max_dynamic = function.max_dynamic_shared_memory_bytes()?; - validate_live_shape(C::SPEC, raw, limits, function_max_threads)?; + validate_live_shape(spec, raw, limits, function_max_threads)?; // Configure the immutable contract maximum, not this particular // launch's chosen size. Concurrent preparations of two range values // therefore write the same function attribute and cannot lower the // maximum underneath an already prepared launch. - let contract_dynamic_max = dynamic_shared_memory_max(C::SPEC.dynamic_shared_memory); + let contract_dynamic_max = dynamic_shared_memory_max(spec.dynamic_shared_memory); let total_shared = - shared_memory_total(C::SPEC.kernel_name, static_shared, contract_dynamic_max)?; + shared_memory_total(spec.kernel_name, static_shared, contract_dynamic_max)?; if validate_shared_memory_limit( - C::SPEC.kernel_name, + spec.kernel_name, total_shared, limits.max_shared_memory_per_block, false, @@ -927,10 +992,10 @@ impl PreparedLaunch { .is_err() { let opt_in_max = context.max_opt_in_shared_memory_per_block()?; - validate_shared_memory_limit(C::SPEC.kernel_name, total_shared, opt_in_max, true)?; + validate_shared_memory_limit(spec.kernel_name, total_shared, opt_in_max, true)?; } - if let Some(required) = C::SPEC.min_compute_capability { + if let Some(required) = spec.min_compute_capability { let (major, minor) = context.compute_capability()?; let actual = ( u32::try_from(major).map_err(|_| { @@ -940,23 +1005,20 @@ impl PreparedLaunch { DriverError(cuda_bindings::cudaError_enum_CUDA_ERROR_INVALID_VALUE) })?, ); - validate_compute_capability(C::SPEC.kernel_name, required, actual)?; + validate_compute_capability(spec.kernel_name, required, actual)?; } - if let Some(cluster) = C::SPEC.cluster { - validate_cluster_support(C::SPEC.kernel_name, context.supports_cluster_launch()?)?; + if let Some(cluster) = spec.cluster { + validate_cluster_support(spec.kernel_name, context.supports_cluster_launch()?)?; validate_required_cluster( - C::SPEC.kernel_name, + spec.kernel_name, cluster, function.required_cluster_dimensions()?, )?; } - if C::SPEC.cooperative { - validate_cooperative_support( - C::SPEC.kernel_name, - context.supports_cooperative_launch()?, - )?; + if spec.cooperative { + validate_cooperative_support(spec.kernel_name, context.supports_cooperative_launch()?)?; } // Perform the only persistent function mutation after all checks that @@ -973,15 +1035,15 @@ impl PreparedLaunch { // `cuOccupancyMaxActiveClusters`. let mut clustered_resident_blocks: Option = None; - if let Some(cluster) = C::SPEC.cluster { + if let Some(cluster) = spec.cluster { let max_cluster_size = function.max_potential_cluster_size( raw.grid_dim, raw.block_dim, raw.shared_mem_bytes, )?; let cluster_blocks = - shape_product(C::SPEC.kernel_name, LaunchDimension::Cluster, cluster)?; - validate_cluster_size(C::SPEC.kernel_name, cluster_blocks, max_cluster_size)?; + shape_product(spec.kernel_name, LaunchDimension::Cluster, cluster)?; + validate_cluster_size(spec.kernel_name, cluster_blocks, max_cluster_size)?; let active_clusters = match function.max_active_clusters( raw.grid_dim, @@ -994,13 +1056,13 @@ impl PreparedLaunch { if error.0 == cuda_bindings::cudaError_enum_CUDA_ERROR_INVALID_CLUSTER_SIZE => { return Err(LaunchContractError::ClusterShapeUnsupported { - kernel: C::SPEC.kernel_name, + kernel: spec.kernel_name, cluster, }); } Err(error) => return Err(error.into()), }; - validate_cluster_residency(C::SPEC.kernel_name, cluster, active_clusters)?; + validate_cluster_residency(spec.kernel_name, cluster, active_clusters)?; // Deliberate error reuse: `active_clusters * cluster_blocks` is a // device-capacity product over the cluster dimension, and // `DimensionProductOverflow { Cluster }` is the closest existing @@ -1012,19 +1074,19 @@ impl PreparedLaunch { u64::from(active_clusters) .checked_mul(cluster_blocks) .ok_or(LaunchContractError::DimensionProductOverflow { - kernel: C::SPEC.kernel_name, + kernel: spec.kernel_name, dimension: LaunchDimension::Cluster, })?, ); } - if C::SPEC.cooperative { - let blocks = shape_product(C::SPEC.kernel_name, LaunchDimension::Grid, raw.grid_dim)?; + if spec.cooperative { + let blocks = shape_product(spec.kernel_name, LaunchDimension::Grid, raw.grid_dim)?; let resident_capacity = if let Some(capacity) = clustered_resident_blocks { capacity } else { let block_threads = - shape_product(C::SPEC.kernel_name, LaunchDimension::Block, raw.block_dim)?; + shape_product(spec.kernel_name, LaunchDimension::Block, raw.block_dim)?; let active_per_sm = function.max_active_blocks_per_multiprocessor( block_threads as u32, raw.shared_mem_bytes, @@ -1032,7 +1094,7 @@ impl PreparedLaunch { let multiprocessors = context.multiprocessor_count()?; u64::from(active_per_sm) * u64::from(multiprocessors) }; - validate_cooperative_residency(C::SPEC.kernel_name, blocks, resident_capacity)?; + validate_cooperative_residency(spec.kernel_name, blocks, resident_capacity)?; } Ok(Self { @@ -1072,6 +1134,85 @@ impl PreparedLaunch { } } +fn resolve_compiled_spec( + mut spec: LaunchContractSpec, + facts: Option, +) -> Result { + let Some(facts) = facts else { + return if spec.dynamic_shared_memory == DynamicSharedMemoryRequirement::Inferred { + Err(LaunchContractError::MissingCompiledLaunchFacts { + kernel: spec.kernel_name, + }) + } else { + Ok(spec) + }; + }; + if let Some(required) = facts.exact_block { + match spec.block { + BlockRequirement::Exact(declared) if declared != required => { + return Err(LaunchContractError::BlockShapeMismatch { + kernel: spec.kernel_name, + required, + actual: declared, + }); + } + BlockRequirement::MaxThreads(max) => { + let actual = shape_product(spec.kernel_name, LaunchDimension::Block, required)?; + if actual > u64::from(max) { + return Err(LaunchContractError::BlockThreadsExceedContract { + kernel: spec.kernel_name, + actual, + max, + }); + } + } + _ => {} + } + spec.block = BlockRequirement::Exact(required); + } + spec.dynamic_shared_memory = match spec.dynamic_shared_memory { + DynamicSharedMemoryRequirement::Inferred => DynamicSharedMemoryRequirement::Exact { + bytes: facts.dynamic_shared_bytes, + min_alignment: facts.dynamic_shared_alignment, + }, + DynamicSharedMemoryRequirement::Exact { + bytes, + min_alignment, + } => { + if bytes < facts.dynamic_shared_bytes { + return Err(LaunchContractError::DynamicSharedMemoryExactMismatch { + kernel: spec.kernel_name, + required: facts.dynamic_shared_bytes, + actual: bytes, + }); + } + DynamicSharedMemoryRequirement::Exact { + bytes, + min_alignment: min_alignment.max(facts.dynamic_shared_alignment), + } + } + DynamicSharedMemoryRequirement::Range { + min_bytes, + max_bytes, + min_alignment, + } => { + if max_bytes < facts.dynamic_shared_bytes { + return Err(LaunchContractError::DynamicSharedMemoryExactMismatch { + kernel: spec.kernel_name, + required: facts.dynamic_shared_bytes, + actual: max_bytes, + }); + } + DynamicSharedMemoryRequirement::Range { + min_bytes: min_bytes.max(facts.dynamic_shared_bytes), + max_bytes, + min_alignment: min_alignment.max(facts.dynamic_shared_alignment), + } + } + }; + Ok(spec) +} + fn validate_static( spec: LaunchContractSpec, config: LaunchConfig, @@ -1111,6 +1252,11 @@ fn validate_static( } match spec.dynamic_shared_memory { + DynamicSharedMemoryRequirement::Inferred => { + return Err(LaunchContractError::MissingCompiledLaunchFacts { + kernel: spec.kernel_name, + }) + } DynamicSharedMemoryRequirement::Exact { bytes, min_alignment, @@ -1250,6 +1396,9 @@ fn shared_memory_total( const fn dynamic_shared_memory_max(requirement: DynamicSharedMemoryRequirement) -> u32 { match requirement { + DynamicSharedMemoryRequirement::Inferred => { + panic!("inferred requirements must be resolved before validation") + } DynamicSharedMemoryRequirement::Exact { bytes, .. } => bytes, DynamicSharedMemoryRequirement::Range { max_bytes, .. } => max_bytes, } @@ -1482,6 +1631,120 @@ mod tests { } } + #[test] + fn compiled_facts_resolve_inference_and_enforce_shape_and_size() { + let source = LaunchContractSpec::new( + "fixed", + BlockRequirement::MaxThreads(32), + DynamicSharedMemoryRequirement::Inferred, + ); + assert!(matches!( + resolve_compiled_spec(source, None), + Err(LaunchContractError::MissingCompiledLaunchFacts { .. }) + )); + let facts = oxide_artifacts::KernelLaunchFacts { + exact_block: Some((8, 4, 1)), + dynamic_shared_bytes: 512, + dynamic_shared_alignment: 64, + }; + let effective = resolve_compiled_spec(source, Some(facts)).unwrap(); + let config = LaunchConfig { + grid_dim: (1, 1, 1), + block_dim: (8, 4, 1), + shared_mem_bytes: 512, + }; + assert!(validate_static(effective, config).is_ok()); + assert!(matches!( + validate_static( + effective, + LaunchConfig { + block_dim: (32, 1, 1), + ..config + } + ), + Err(LaunchContractError::BlockShapeMismatch { .. }) + )); + assert!(matches!( + validate_static( + effective, + LaunchConfig { + shared_mem_bytes: 511, + ..config + } + ), + Err(LaunchContractError::DynamicSharedMemoryExactMismatch { .. }) + )); + let empty = resolve_compiled_spec( + source, + Some(oxide_artifacts::KernelLaunchFacts { + dynamic_shared_bytes: 0, + ..facts + }), + ) + .unwrap(); + assert!(validate_static( + empty, + LaunchConfig { + shared_mem_bytes: 0, + ..config + } + ) + .is_ok()); + assert!(LaunchConfig2D::auto_shared((1, 1), (8, 4)).__auto_shared()); + assert!(!LaunchConfig2D::new((1, 1), (8, 4), 0).__auto_shared()); + } + + #[test] + fn compiled_facts_strengthen_explicit_contracts() { + let facts = oxide_artifacts::KernelLaunchFacts { + exact_block: Some((8, 4, 1)), + dynamic_shared_bytes: 128, + dynamic_shared_alignment: 64, + }; + let resolve = |block, memory| { + resolve_compiled_spec(LaunchContractSpec::new("fixed", block, memory), Some(facts)) + }; + let block = BlockRequirement::MaxThreads(32); + let exact = |bytes| DynamicSharedMemoryRequirement::Exact { + bytes, + min_alignment: 16, + }; + for bytes in [0, 127] { + assert!(matches!( + resolve(block, exact(bytes)), + Err(LaunchContractError::DynamicSharedMemoryExactMismatch { .. }) + )); + } + assert_eq!( + resolve(block, exact(256)).unwrap().dynamic_shared_memory, + DynamicSharedMemoryRequirement::Exact { + bytes: 256, + min_alignment: 64, + } + ); + let range = |max_bytes| DynamicSharedMemoryRequirement::Range { + min_bytes: 32, + max_bytes, + min_alignment: 16, + }; + assert!(matches!( + resolve(block, range(127)), + Err(LaunchContractError::DynamicSharedMemoryExactMismatch { .. }) + )); + assert_eq!( + resolve(block, range(256)).unwrap().dynamic_shared_memory, + DynamicSharedMemoryRequirement::Range { + min_bytes: 128, + max_bytes: 256, + min_alignment: 64, + } + ); + assert!(matches!( + resolve(BlockRequirement::MaxThreads(16), exact(128)), + Err(LaunchContractError::BlockThreadsExceedContract { .. }) + )); + } + #[test] fn typed_configs_fix_trailing_dimensions() { let one = LaunchConfig1D::new(7, 64, 16).__raw(); diff --git a/cuda-core/src/simt/mod.rs b/cuda-core/src/simt/mod.rs index 7f07b4c361..7921737eb7 100644 --- a/cuda-core/src/simt/mod.rs +++ b/cuda-core/src/simt/mod.rs @@ -67,7 +67,7 @@ pub use crate::error::{DriverError, IntoResult}; pub use crate::init; pub use crate::launch_kernel; pub use cuda_bindings as sys; -/// Artifact-bundle metadata, from the published crate cuda-oxide releases. +/// Artifact-bundle metadata shared with the CUDA compiler and loaders. pub use oxide_artifacts as artifacts; /// Launches a CUDA kernel on a specific [`CudaStream`], binding its context first. diff --git a/cuda-core/src/simt/module.rs b/cuda-core/src/simt/module.rs index a2b4cb646f..4ec96999fc 100644 --- a/cuda-core/src/simt/module.rs +++ b/cuda-core/src/simt/module.rs @@ -29,7 +29,9 @@ use crate::error::{DriverError, IntoResult}; use crate::simt::context::CudaContext; +use oxide_artifacts::KernelLaunchFacts; use std::borrow::Cow; +use std::collections::BTreeMap; use std::ffi::{c_void, CString}; use std::mem::MaybeUninit; use std::sync::Arc; @@ -44,6 +46,7 @@ pub struct CudaModule { pub(crate) cu_module: cuda_bindings::CUmodule, /// Owning context. Kept alive for the lifetime of this module. pub(crate) ctx: Arc, + kernel_launch_facts: BTreeMap, } /// # Safety @@ -92,6 +95,7 @@ impl CudaContext { Ok(Arc::new(CudaModule { cu_module, ctx: self.clone(), + kernel_launch_facts: BTreeMap::new(), })) } @@ -104,6 +108,22 @@ impl CudaContext { pub fn load_module_from_image( self: &Arc, image: &[u8], + ) -> Result, DriverError> { + self.load_module_from_image_with_launch_facts(image, BTreeMap::new()) + } + + /// Loads an image together with its compiler-produced per-entry facts. + /// + /// The facts must come from the same artifact bundle as `image`. This is + /// intended for artifact loaders; raw image loading leaves facts absent. + /// Loading does not validate the facts against device instructions. Binding + /// this module to a checked launch API is unsafe and requires truthful facts + /// for the exact loaded image and entry. + #[doc(hidden)] + pub fn load_module_from_image_with_launch_facts( + self: &Arc, + image: &[u8], + kernel_launch_facts: BTreeMap, ) -> Result, DriverError> { self.bind_to_thread()?; let image = null_terminated_image(image); @@ -116,6 +136,7 @@ impl CudaContext { Ok(Arc::new(CudaModule { cu_module, ctx: self.clone(), + kernel_launch_facts, })) } @@ -141,6 +162,7 @@ impl CudaContext { Ok(Arc::new(CudaModule { cu_module, ctx: self.clone(), + kernel_launch_facts: BTreeMap::new(), })) } } @@ -168,6 +190,7 @@ pub struct CudaFunction { /// Owning module. Prevents unloading while this function handle exists. #[allow(unused)] pub(crate) module: Arc, + launch_facts: Option, } /// # Safety @@ -254,6 +277,7 @@ impl CudaModule { Ok(CudaFunction { cu_function, module: self.clone(), + launch_facts: self.kernel_launch_facts.get(fn_name).copied(), }) } } @@ -445,6 +469,11 @@ impl CudaModule { } impl CudaFunction { + /// Returns finalized requirements attached to this concrete kernel artifact. + pub fn launch_facts(&self) -> Option { + self.launch_facts + } + fn attribute( &self, attribute: cuda_bindings::CUfunction_attribute, diff --git a/cuda-oxide/Cargo.lock b/cuda-oxide/Cargo.lock index cdef05af07..8948e1e866 100644 --- a/cuda-oxide/Cargo.lock +++ b/cuda-oxide/Cargo.lock @@ -211,7 +211,7 @@ dependencies = [ "cuda-artifact-finalizer", "libnvvm-sys", "nvjitlink-sys", - "oxide-artifacts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "oxide-artifacts", "oxide-tile-export", "oxide-tilebc", "ptx-parse", @@ -406,7 +406,7 @@ dependencies = [ "cuda-bindings", "cuda-core-derive", "half", - "oxide-artifacts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "oxide-artifacts", ] [[package]] @@ -438,7 +438,7 @@ dependencies = [ "half", "libc", "libloading", - "oxide-artifacts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "oxide-artifacts", "ptx-parse", "sha2", "thiserror 2.0.21", @@ -472,6 +472,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn 2.0.117", "trybuild", ] @@ -996,7 +998,7 @@ dependencies = [ "llvm-export", "mir-lower", "once_cell", - "oxide-artifacts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "oxide-artifacts", "pliron", "pliron-derive", "reserved-oxide-symbols", @@ -1095,15 +1097,6 @@ dependencies = [ "object", ] -[[package]] -name = "oxide-artifacts" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" -dependencies = [ - "object", -] - [[package]] name = "oxide-tile-export" version = "0.2.1" @@ -1223,7 +1216,7 @@ version = "0.1.0" dependencies = [ "clap", "dialect-ptx", - "oxide-artifacts 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "oxide-artifacts", "ptx-parse", "serde", "serde_json", diff --git a/cuda-oxide/Cargo.toml b/cuda-oxide/Cargo.toml index 6aeea9929e..946e51f74c 100644 --- a/cuda-oxide/Cargo.toml +++ b/cuda-oxide/Cargo.toml @@ -92,13 +92,10 @@ cuda-async = { path = "../cuda-async" } libnvvm-sys = { path = "crates/libnvvm-sys" } nvjitlink-sys = { path = "crates/nvjitlink-sys" } reserved-oxide-symbols = { path = "crates/reserved-oxide-symbols" } -# The crates.io release, not the in-tree path: the shared cuda-core (cutile-rs) -# reads artifact bundles through crates.io oxide-artifacts, and a path copy of -# the same version is a second crate to rustc. crates/oxide-artifacts -# stays in the workspace as the source this release is published from; bump, -# publish, then move this line. -# scripts/check-oxide-artifacts-parity.sh keeps them equal. -oxide-artifacts = "0.2.1" +# Keep the compiler, shared host runtime, and tools on the same artifact +# implementation. The shared runtime and isolated backend use this path too; +# scripts/check-oxide-artifacts-parity.sh verifies the source and version. +oxide-artifacts = { version = "0.2.1", path = "crates/oxide-artifacts" } # Tile export descriptions shared by `#[tile_export]`, the backend, and # `cargo oxide tilelib`. oxide-tile-export = { path = "crates/oxide-tile-export" } diff --git a/cuda-oxide/crates/cargo-oxide/README.md b/cuda-oxide/crates/cargo-oxide/README.md index 2ed176b4ed..787124f539 100644 --- a/cuda-oxide/crates/cargo-oxide/README.md +++ b/cuda-oxide/crates/cargo-oxide/README.md @@ -52,6 +52,7 @@ cargo oxide update --force # inside the workspace, run setup via update | Flag | Applies to | Description | |------------------------------|----------------------------------|-------------------------------------------------| +| `--link-ltoir ` | run, sanitize, build, test, pipeline, debug | Add an ordered external LTO-IR file to `--materialize-cubin` (repeatable) | | `--materialize-cubin` | run, sanitize, build, test, pipeline, debug | Finalize and embed target-specific native GPU code during the host build | | `--emit-nvvm-ir` | run, build, pipeline | Generate NVVM IR for libNVVM | | `--arch ` | run, sanitize, build, test, pipeline, emit-ltoir, tilelib, inspect, debug | Target architecture override | @@ -121,9 +122,32 @@ rechecks them inside the backend; use the wrapper flag instead of setting `CUDA_OXIDE_MATERIALIZE_CUBIN` around raw Cargo. That variable is an internal wrapper/backend signal, not a supported user interface: raw Cargo may reuse a previous artifact without running the backend, and a backend invocation without -the wrapper's fingerprint is rejected. Generic `#[cuda_module]` kernels and -`#[device] extern` declarations are rejected because their run-time -multi-artifact linking is not yet represented by this single-cubin path. +the wrapper's fingerprint is rejected. Generic `#[cuda_module]` kernels remain +unsupported by this single-cubin path because they merge PTX bundles at run time. + +For non-generic kernels calling `#[device] extern` functions, pass the definitions +as ordered, repeatable `--link-ltoir ` inputs alongside `--materialize-cubin`. +Inputs must be raw CUDA LTO-IR, not object files or fatbins. Each supplied file +is linked into every materialized device artifact in that Cargo invocation. +Keep these inputs separate from generated artifact paths; an overlap is rejected +before cleanup or device output emission. +Paths are relative to the invocation directory. The wrapper fingerprints their +canonical names and contents, and the backend verifies and owns those bytes +before linking. Changing an input rebuilds the device artifact; a change during +the wrapper/backend handoff is an error. The Rust module is linked first, followed +by the supplied files in command-line order. CUDA reports unresolved symbols, +invalid LTO-IR, and unsupported toolkit/target combinations during the build. +Use compatible CUDA compiler and linker versions when generating the inputs. + +```bash +cargo oxide run --materialize-cubin --arch sm_120 \ + --link-ltoir build/device-libs/scale.ltoir --link-ltoir build/device-libs/add.ltoir +``` + +The [`external_ltoir` example](../rustc-codegen-cuda/examples/external_ltoir/README.md) +includes C++ sources and commands to generate these files and run the ordinary +embedded-artifact loader. Generated binaries are not source dependencies. + Metadata-interop projects keep rejecting this global flag; they can instead request one independently finalized cubin per declared device crate with `artifact-kind = "cubin"`, as described below. Materialization is also a @@ -322,6 +346,18 @@ links against. It builds the crate in NVVM IR mode, then runs the emitted `compute_XX`, or a bare `XX`. The default output path is `/.ltoir`; `-o/--output` overrides it. +For a standalone project, omit `` to use its Cargo target name. The +directory name may differ from the package name, and hyphens in the target name +become underscores in artifact filenames. A package-named target is preferred; +otherwise the package must have one binary or library target, or its target name +must be supplied explicitly. The positional `` is this Cargo target name; +`default-run` does not select artifacts. This also applies when invoked from a +member of a user Cargo workspace: that member supplies the target, and the IR +and default LTO-IR output are placed in the invocation directory. An explicit +`CUDA_OXIDE_PTX_DIR` selects the intermediate IR directory for both writing and +reading; relative values are resolved from the Cargo workspace root. The process +environment takes precedence over project configuration. + ```bash cargo oxide emit-ltoir standalone_device_fn --arch sm_100 cargo oxide emit-ltoir my_simt_crate --arch sm_120 -o build/simt.ltoir diff --git a/cuda-oxide/crates/cargo-oxide/src/commands/artifacts.rs b/cuda-oxide/crates/cargo-oxide/src/commands/artifacts.rs index 94e2caaa36..37b49a0072 100644 --- a/cuda-oxide/crates/cargo-oxide/src/commands/artifacts.rs +++ b/cuda-oxide/crates/cargo-oxide/src/commands/artifacts.rs @@ -134,12 +134,25 @@ pub(super) fn generated_artifact_paths(project_dir: &Path, package_name: &str) - /// Remove stale generated artifacts (`.ptx`, `.ll`, `.ltoir`, `.cubin`) from a /// previous run so we can verify the build produces fresh output. -pub(super) fn clean_generated_files(example_dir: &Path, example: &str) { - for file in generated_artifact_paths(example_dir, example) { +pub(super) fn clean_generated_files( + example_dir: &Path, + example: &str, + external_inputs: &[PathBuf], +) -> Result<(), String> { + let outputs = generated_artifact_paths(example_dir, example); + // Check the whole deletion set before removing even the first file. + for output in &outputs { + for input in external_inputs { + cuda_artifact_finalizer::check_ltoir_input_output(input, output) + .map_err(|error| error.to_string())?; + } + } + for file in outputs { if file.exists() { let _ = std::fs::remove_file(file); } } + Ok(()) } /// Human-readable label for the selected output format. diff --git a/cuda-oxide/crates/cargo-oxide/src/commands/build_run.rs b/cuda-oxide/crates/cargo-oxide/src/commands/build_run.rs index 27e7640d2b..0b74d36daf 100644 --- a/cuda-oxide/crates/cargo-oxide/src/commands/build_run.rs +++ b/cuda-oxide/crates/cargo-oxide/src/commands/build_run.rs @@ -87,7 +87,10 @@ pub fn codegen_run( std::process::exit(2); } - clean_generated_files(&example_dir, example); + clean_generated_files(&example_dir, example, &ctx.link_ltoir).unwrap_or_else(|error| { + eprintln!("Error: {error}"); + std::process::exit(2); + }); println!("========================================="); println!("RUSTC-CODEGEN-CUDA: {}", example); @@ -256,7 +259,10 @@ pub fn codegen_sanitize( return; } - clean_generated_files(&example_dir, example); + clean_generated_files(&example_dir, example, &ctx.link_ltoir).unwrap_or_else(|error| { + eprintln!("Error: {error}"); + std::process::exit(2); + }); println!("========================================="); println!("RUSTC-CODEGEN-CUDA SANITIZE: {}", example); @@ -381,7 +387,10 @@ pub fn codegen_build( std::process::exit(2); } - clean_generated_files(&example_dir, example); + clean_generated_files(&example_dir, example, &ctx.link_ltoir).unwrap_or_else(|error| { + eprintln!("Error: {error}"); + std::process::exit(2); + }); println!("========================================="); println!("RUSTC-CODEGEN-CUDA BUILD: {}", example); diff --git a/cuda-oxide/crates/cargo-oxide/src/commands/context.rs b/cuda-oxide/crates/cargo-oxide/src/commands/context.rs index 66fa592d43..c8c6dab949 100644 --- a/cuda-oxide/crates/cargo-oxide/src/commands/context.rs +++ b/cuda-oxide/crates/cargo-oxide/src/commands/context.rs @@ -25,6 +25,7 @@ pub struct OxideConfig { /// /// Built once at startup by [`resolve_context`] and passed by reference to /// every command handler. Avoids repeated filesystem walks and backend builds. +#[derive(Clone)] pub struct Context { /// Absolute path to the workspace root (contains top-level `Cargo.toml`). pub workspace_root: PathBuf, @@ -39,6 +40,8 @@ pub struct Context { pub is_workspace: bool, /// Project-local cuda-oxide defaults. pub config: OxideConfig, + /// Ordered external LTO-IR inputs from the command line. + pub link_ltoir: Vec, } /// Resolve the workspace root and backend, or exit with a helpful error. @@ -60,6 +63,7 @@ pub fn resolve_context() -> Context { let config = load_oxide_config(&workspace_root); let backend_so = backend::find_or_build_backend(&workspace_root, config.backend.as_deref()); return Context { + link_ltoir: Vec::new(), workspace_root, codegen_crate, examples_dir, @@ -78,6 +82,7 @@ pub fn resolve_context() -> Context { let config = load_oxide_config(&cwd); let backend_so = backend::find_or_build_backend(&cwd, config.backend.as_deref()); return Context { + link_ltoir: Vec::new(), workspace_root: cwd.clone(), codegen_crate: cwd.clone(), examples_dir: cwd.clone(), @@ -110,6 +115,7 @@ pub fn resolve_passive_context() -> Context { let config = load_oxide_config_lenient(&workspace_root); let backend_so = backend::backend_so_candidate(&workspace_root, config.backend.as_deref()); return Context { + link_ltoir: Vec::new(), workspace_root, codegen_crate, examples_dir, @@ -128,6 +134,7 @@ pub fn resolve_passive_context() -> Context { let config = load_oxide_config_lenient(&cwd); let backend_so = backend::backend_so_candidate(&cwd, config.backend.as_deref()); return Context { + link_ltoir: Vec::new(), workspace_root: cwd.clone(), codegen_crate: cwd.clone(), examples_dir: cwd.clone(), diff --git a/cuda-oxide/crates/cargo-oxide/src/commands/fingerprint.rs b/cuda-oxide/crates/cargo-oxide/src/commands/fingerprint.rs index 03a9e4ce24..2a84fc79d1 100644 --- a/cuda-oxide/crates/cargo-oxide/src/commands/fingerprint.rs +++ b/cuda-oxide/crates/cargo-oxide/src/commands/fingerprint.rs @@ -78,6 +78,7 @@ pub(super) fn passthrough_codegen_fingerprint_with_env( // Descriptor identity only accelerates verification; artifact identity is // already represented by the content-derived provenance above. effective_env.remove(MATERIALIZER_HANDSHAKE_ENV); + effective_env.remove(EXTERNAL_LTOIR_ENV); if opts.verbose { effective_env.insert("CUDA_OXIDE_VERBOSE".to_string(), b"1".to_vec()); @@ -95,6 +96,10 @@ pub(super) fn passthrough_codegen_fingerprint_with_env( effective_env.insert("CUDA_OXIDE_EMIT_NVVM_IR".to_string(), b"1".to_vec()); } if let Some(prepared) = &materialization.prepared { + effective_env.insert( + EXTERNAL_LTOIR_ENV.to_string(), + prepared.external_ltoir_json.as_bytes().to_vec(), + ); effective_env.insert(MATERIALIZE_ENV.to_string(), b"1".to_vec()); effective_env.insert( EXPECTED_PROVENANCE_ENV.to_string(), diff --git a/cuda-oxide/crates/cargo-oxide/src/commands/host_cargo.rs b/cuda-oxide/crates/cargo-oxide/src/commands/host_cargo.rs index 36b1f36724..e28ed9e2d7 100644 --- a/cuda-oxide/crates/cargo-oxide/src/commands/host_cargo.rs +++ b/cuda-oxide/crates/cargo-oxide/src/commands/host_cargo.rs @@ -268,6 +268,62 @@ pub(super) struct CargoExecutableArtifact { pub(super) path: PathBuf, } +/// Infer the artifact stem for a standalone project from Cargo's targets. +/// Keep the package-named target when present, as for workspace examples; +/// otherwise a sole binary or library target supplies its own crate name. +pub fn standalone_crate_name(manifest_dir: &Path) -> Result { + let metadata = cargo_metadata(manifest_dir)?; + let manifest_path = manifest_dir.join("Cargo.toml"); + let manifest_path = manifest_path + .canonicalize() + .map_err(|error| format!("could not resolve {}: {error}", manifest_path.display()))?; + let packages = metadata + .get("packages") + .and_then(|packages| packages.as_array()) + .ok_or_else(|| "Cargo metadata did not include packages".to_string())?; + let selected = cargo_selected_packages(&metadata, packages, &manifest_path)?; + let [package] = selected.as_slice() else { + return Err("run from a single Cargo package to select its device artifact".to_string()); + }; + let package_name = cargo_package_name(package)?; + let targets = package + .get("targets") + .and_then(|targets| targets.as_array()) + .ok_or_else(|| "Cargo metadata did not include package targets".to_string())?; + let mut names: Vec<_> = targets + .iter() + .filter(|target| { + target + .get("kind") + .and_then(|kind| kind.as_array()) + .is_some_and(|kinds| { + kinds.iter().any(|kind| { + matches!( + kind.as_str(), + Some("bin" | "lib" | "rlib" | "staticlib" | "cdylib" | "dylib") + ) + }) + }) + }) + .filter_map(|target| target.get("name").and_then(|name| name.as_str())) + .map(artifact_stem) + .collect(); + names.sort(); + names.dedup(); + let package_stem = artifact_stem(package_name); + if names.contains(&package_stem) { + return Ok(package_stem); + } + if let [name] = names.as_slice() { + return Ok(name.clone()); + } + Err(format!( + "could not choose a device artifact for package `{package_name}`; \ + pass the binary or library target name explicitly (available: {})", + names.join(", ") + )) +} + pub(super) fn cargo_executable_selection( manifest_dir: &Path, explicit_bin: Option<&str>, @@ -365,7 +421,7 @@ fn cargo_package_manifest_matches(package: &serde_json::Value, manifest_path: &P .is_some_and(|path| path == manifest_path) } -fn cargo_metadata(manifest_dir: &Path) -> Result { +pub(super) fn cargo_metadata(manifest_dir: &Path) -> Result { let output = Command::new("cargo") .args(["metadata", "--format-version=1", "--no-deps"]) .current_dir(manifest_dir) diff --git a/cuda-oxide/crates/cargo-oxide/src/commands/interop.rs b/cuda-oxide/crates/cargo-oxide/src/commands/interop.rs index 13d8c532ec..4ea4603dbd 100644 --- a/cuda-oxide/crates/cargo-oxide/src/commands/interop.rs +++ b/cuda-oxide/crates/cargo-oxide/src/commands/interop.rs @@ -573,7 +573,10 @@ fn build_interop_device_crate( } let artifact_name = interop_device_artifact_name(&manifest_path, device_crate); - clean_generated_files(&artifact_dir, &artifact_name); + clean_generated_files(&artifact_dir, &artifact_name, &ctx.link_ltoir).unwrap_or_else(|error| { + eprintln!("Error: {error}"); + std::process::exit(2); + }); if let Some(target) = &binary_target { touch_source_file(&target.source_path); } else { diff --git a/cuda-oxide/crates/cargo-oxide/src/commands/ltoir.rs b/cuda-oxide/crates/cargo-oxide/src/commands/ltoir.rs index feecbef80e..de1f612339 100644 --- a/cuda-oxide/crates/cargo-oxide/src/commands/ltoir.rs +++ b/cuda-oxide/crates/cargo-oxide/src/commands/ltoir.rs @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -use std::path::Path; +use std::path::{Path, PathBuf}; use super::*; @@ -56,12 +56,26 @@ pub fn emit_ltoir( }); let sm_arch = parsed_arch.sm(); + // Cargo invokes rustc from its workspace root even when the selected + // package is a member. Pin this command's IR directory explicitly instead + // of deriving it from the compiler's working directory. + let (build_ctx, ir_dir) = + ltoir_build_context(ctx, &example_dir, std::env::var_os("CUDA_OXIDE_PTX_DIR")) + .unwrap_or_else(|error| { + eprintln!("Error: {error}"); + std::process::exit(1); + }); + clean_generated_files(&ir_dir, example, &ctx.link_ltoir).unwrap_or_else(|error| { + eprintln!("Error: {error}"); + std::process::exit(2); + }); + // Step 1: build in NVVM IR mode so the backend writes `.ll` as // libNVVM-ready NVVM IR. codegen_build exits on build failure. Pass // quiet=true so the intermediate "✓ Build succeeded" line is suppressed; // emit_ltoir prints its own unified summary at the end. codegen_build( - ctx, + &build_ctx, example, verbose, true, @@ -76,7 +90,7 @@ pub fn emit_ltoir( ); // Step 2: compile that NVVM IR to LTOIR via libNVVM -gen-lto. - let ll_path = emitted_ll_path(&example_dir, example); + let ll_path = emitted_ll_path(&ir_dir, example); let ir = std::fs::read(&ll_path).unwrap_or_else(|e| { eprintln!( "Error: could not read emitted NVVM IR at {}: {e}", @@ -165,6 +179,51 @@ pub fn emit_ltoir( ); } +/// Select the same IR directory for the build and subsequent reader. Keep an +/// inherited override strongest, followed by project config. Relative explicit +/// paths are relative to rustc's Cargo workspace cwd, matching existing backend +/// semantics. Without an override, emit-ltoir owns its invocation directory. +pub(super) fn ltoir_build_context( + ctx: &Context, + example_dir: &Path, + inherited_dir: Option, +) -> Result<(Context, PathBuf), String> { + let configured = inherited_dir + .or_else(|| project_config_env(ctx, "CUDA_OXIDE_PTX_DIR").map(std::ffi::OsString::from)); + let ir_dir = match configured { + None => example_dir.to_path_buf(), + Some(path) => { + let path = PathBuf::from(path); + if path.is_absolute() { + path + } else { + let metadata = cargo_metadata(example_dir)?; + let root = metadata + .get("workspace_root") + .and_then(|path| path.as_str()) + .ok_or_else(|| "Cargo metadata did not include workspace_root".to_string())?; + Path::new(root).join(path) + } + } + }; + let value = ir_dir.to_str().ok_or_else(|| { + format!( + "NVVM IR output directory is not Unicode: {}", + ir_dir.display() + ) + })?; + let mut build_ctx = ctx.clone(); + build_ctx + .config + .env + .retain(|(key, _)| key != "CUDA_OXIDE_PTX_DIR"); + build_ctx + .config + .env + .push(("CUDA_OXIDE_PTX_DIR".into(), value.into())); + Ok((build_ctx, ir_dir)) +} + /// Normalize a target architecture to libNVVM's `compute_XX` form. /// /// Accepts `sm_XX` (the form `--arch` and the rest of cargo-oxide use), diff --git a/cuda-oxide/crates/cargo-oxide/src/commands/materialize.rs b/cuda-oxide/crates/cargo-oxide/src/commands/materialize.rs index 80dee3ee40..6b3b5beb56 100644 --- a/cuda-oxide/crates/cargo-oxide/src/commands/materialize.rs +++ b/cuda-oxide/crates/cargo-oxide/src/commands/materialize.rs @@ -9,6 +9,7 @@ use std::process::Command; use super::*; +pub(super) const EXTERNAL_LTOIR_ENV: &str = reserved_oxide_symbols::EXTERNAL_LTOIR_ENV; pub(super) const MATERIALIZE_ENV: &str = reserved_oxide_symbols::MATERIALIZE_CUBIN_ENV; pub(super) const EXPECTED_PROVENANCE_ENV: &str = reserved_oxide_symbols::MATERIALIZER_PROVENANCE_ENV; @@ -31,6 +32,7 @@ pub(super) struct MaterializationMode { pub(super) struct PreparedMaterialization { pub(super) provenance_sha256_hex: String, pub(super) tool_identity_handshake_json: String, + pub(super) external_ltoir_json: String, } impl MaterializationMode { @@ -39,10 +41,13 @@ impl MaterializationMode { } pub(super) fn apply(&self, cmd: &mut Command) { + // Never honor an inherited internal external-input list. + cmd.env_remove(EXTERNAL_LTOIR_ENV); if let Some(prepared) = &self.prepared { // These override inherited/project values: they are a single // wrapper-generated handshake tied to this Cargo invocation. - cmd.env(MATERIALIZE_ENV, "1") + cmd.env(EXTERNAL_LTOIR_ENV, &prepared.external_ltoir_json) + .env(MATERIALIZE_ENV, "1") .env(EXPECTED_PROVENANCE_ENV, &prepared.provenance_sha256_hex) .env( MATERIALIZER_HANDSHAKE_ENV, @@ -205,6 +210,14 @@ fn prepare_materialization_result_with_env( .parse() .map_err(|error| format!("invalid materialization target {arch:?}: {error}"))?; + let external_inputs = ctx + .link_ltoir + .iter() + .map(|path| cuda_artifact_finalizer::LtoirFile::capture(path)) + .collect::, _>>() + .map_err(|error| format!("could not capture external LTO-IR: {error}"))?; + let external_ltoir_json = serde_json::to_string(&external_inputs) + .map_err(|error| format!("could not encode external LTO-IR inputs: {error}"))?; let handshake = discover_materializer_handshake(ctx)?; let handshake_json = serde_json::to_string(&handshake) .map_err(|error| format!("could not encode materializer handshake: {error}"))?; @@ -212,6 +225,7 @@ fn prepare_materialization_result_with_env( prepared: Some(PreparedMaterialization { provenance_sha256_hex: digest_hex(&handshake.provenance_sha256), tool_identity_handshake_json: handshake_json, + external_ltoir_json, }), }) } diff --git a/cuda-oxide/crates/cargo-oxide/src/commands/mod.rs b/cuda-oxide/crates/cargo-oxide/src/commands/mod.rs index 10bc374ee6..81e29f322a 100644 --- a/cuda-oxide/crates/cargo-oxide/src/commands/mod.rs +++ b/cuda-oxide/crates/cargo-oxide/src/commands/mod.rs @@ -40,6 +40,7 @@ pub use doctor::*; pub use examples_list::*; use fingerprint::*; pub use fmt::*; +pub use host_cargo::standalone_crate_name; use host_cargo::*; use interop::*; pub use ltoir::*; diff --git a/cuda-oxide/crates/cargo-oxide/src/commands/pipeline_debug.rs b/cuda-oxide/crates/cargo-oxide/src/commands/pipeline_debug.rs index f84a54f918..43543c2436 100644 --- a/cuda-oxide/crates/cargo-oxide/src/commands/pipeline_debug.rs +++ b/cuda-oxide/crates/cargo-oxide/src/commands/pipeline_debug.rs @@ -41,7 +41,10 @@ pub fn codegen_show_pipeline( reject_interop_output_mode(emit_nvvm_ir, &materialization); } - clean_generated_files(&example_dir, example); + clean_generated_files(&example_dir, example, &ctx.link_ltoir).unwrap_or_else(|error| { + eprintln!("Error: {error}"); + std::process::exit(2); + }); println!("========================================="); println!("RUSTC-CODEGEN-CUDA PIPELINE: {}", example); @@ -196,7 +199,10 @@ pub fn codegen_debug( println!("Detected GPU arch: {dev} (via nvidia-smi)"); } - clean_generated_files(&example_dir, example); + clean_generated_files(&example_dir, example, &ctx.link_ltoir).unwrap_or_else(|error| { + eprintln!("Error: {error}"); + std::process::exit(2); + }); touch_main_rs(&example_dir); diff --git a/cuda-oxide/crates/cargo-oxide/src/commands/tests.rs b/cuda-oxide/crates/cargo-oxide/src/commands/tests.rs index bf0551deb2..babf126ed7 100644 --- a/cuda-oxide/crates/cargo-oxide/src/commands/tests.rs +++ b/cuda-oxide/crates/cargo-oxide/src/commands/tests.rs @@ -142,6 +142,7 @@ fn cargo_artifact_freshness( fn test_context(config: OxideConfig) -> Context { Context { + link_ltoir: Vec::new(), workspace_root: PathBuf::from("/tmp/cargo-oxide-test-workspace"), codegen_crate: PathBuf::from("/tmp/cargo-oxide-test-codegen"), examples_dir: PathBuf::from("/tmp/cargo-oxide-test-examples"), @@ -428,6 +429,127 @@ fn emit_ltoir_paths_use_normalized_crate_stem() { assert_eq!(default_ltoir_path(dir, "vecadd"), dir.join("vecadd.ltoir")); } +#[test] +fn standalone_artifact_name_comes_from_cargo_targets() { + for (target, source, expected) in [ + ("", "src/main.rs", "device_export"), + ( + "[[bin]]\nname = \"custom-bin\"\npath = \"src/main.rs\"\n", + "src/main.rs", + "custom_bin", + ), + ( + "[lib]\nname = \"custom_library\"\n", + "src/lib.rs", + "custom_library", + ), + ] { + let root = unique_temp_dir("directory_unrelated_to_package"); + std::fs::create_dir_all(root.join("src")).unwrap(); + std::fs::write( + root.join("Cargo.toml"), + format!( + "[package]\nname = \"device-export\"\nversion = \"0.1.0\"\n\ + edition = \"2024\"\n[workspace]\n{target}" + ), + ) + .unwrap(); + std::fs::write(root.join(source), "fn main() {}\n").unwrap(); + + let name = standalone_crate_name(&root).unwrap(); + assert_eq!(name, expected); + assert_eq!( + emitted_ll_path(&root, &name), + root.join(format!("{expected}.ll")) + ); + assert_eq!( + default_ltoir_path(&root, &name), + root.join(format!("{expected}.ltoir")) + ); + std::fs::remove_dir_all(root).unwrap(); + } +} + +#[test] +fn standalone_artifact_name_preserves_package_target_and_rejects_ambiguity() { + let root = unique_temp_dir("cargo_oxide_artifact_multi_target"); + std::fs::create_dir_all(root.join("src")).unwrap(); + std::fs::write(root.join("src/main.rs"), "fn main() {}\n").unwrap(); + std::fs::write(root.join("src/other.rs"), "fn main() {}\n").unwrap(); + for name in ["device-export", "other-package"] { + std::fs::write( + root.join("Cargo.toml"), + format!( + "[package]\nname = \"{name}\"\nversion = \"0.1.0\"\n\ + edition = \"2024\"\ndefault-run = \"other\"\n[workspace]\n\ + [[bin]]\nname = \"device-export\"\npath = \"src/main.rs\"\n\ + [[bin]]\nname = \"other\"\npath = \"src/other.rs\"\n" + ), + ) + .unwrap(); + let result = standalone_crate_name(&root); + if name == "device-export" { + // `cargo build` builds both bins; default-run does not select the IR. + assert_eq!(result.unwrap(), "device_export"); + } else { + let error = result.unwrap_err(); + assert!( + error.contains("pass the binary or library target name explicitly"), + "{error}" + ); + } + } + std::fs::remove_dir_all(root).unwrap(); +} + +#[test] +fn standalone_artifact_name_uses_workspace_package_selection() { + let root = unique_temp_dir("cargo_oxide_artifact_workspace"); + std::fs::create_dir_all(&root).unwrap(); + std::fs::write( + root.join("Cargo.toml"), + "[workspace]\nmembers = [\"first\", \"second\"]\ndefault-members = [\"first\"]\nresolver = \"3\"\n", + ) + .unwrap(); + for member in ["first", "second"] { + let dir = root.join(member); + std::fs::create_dir_all(dir.join("src")).unwrap(); + std::fs::write( + dir.join("Cargo.toml"), + format!( + "[package]\nname = \"{member}-package\"\nversion = \"0.1.0\"\nedition = \"2024\"\n" + ), + ) + .unwrap(); + std::fs::write(dir.join("src/main.rs"), "fn main() {}\n").unwrap(); + } + assert_eq!(standalone_crate_name(&root).unwrap(), "first_package"); + let member = root.join("second"); + assert_eq!(standalone_crate_name(&member).unwrap(), "second_package"); + let ctx = test_context(OxideConfig::default()); + let (build_ctx, ir_dir) = ltoir_build_context(&ctx, &member, None).unwrap(); + assert_eq!(ir_dir, member); + assert_eq!( + project_config_env(&build_ctx, "CUDA_OXIDE_PTX_DIR"), + member.to_str() + ); + + // An explicit relative backend override retains Cargo workspace semantics, + // even though this command was invoked from a different selected member. + let mut ctx = ctx; + ctx.config + .env + .push(("CUDA_OXIDE_PTX_DIR".into(), "configured-ir".into())); + let (_, configured) = ltoir_build_context(&ctx, &member, None).unwrap(); + assert_eq!( + configured, + root.canonicalize().unwrap().join("configured-ir") + ); + let (_, inherited) = ltoir_build_context(&ctx, &member, Some("inherited-ir".into())).unwrap(); + assert_eq!(inherited, root.canonicalize().unwrap().join("inherited-ir")); + std::fs::remove_dir_all(root).unwrap(); +} + #[test] fn generated_file_cleanup_preserves_ltoir_cubin_cache() { let unique = std::time::SystemTime::now() @@ -447,7 +569,7 @@ fn generated_file_cleanup_preserves_ltoir_cubin_cache() { std::fs::create_dir_all(cached_cubin.parent().unwrap()).unwrap(); std::fs::write(&cached_cubin, b"persistent cache entry").unwrap(); - clean_generated_files(&root, "my-kernel"); + clean_generated_files(&root, "my-kernel", &[]).unwrap(); for extension in ["ptx", "ll", "ltoir", "cubin", "target"] { assert!(!root.join(format!("my_kernel.{extension}")).exists()); @@ -487,6 +609,7 @@ edition = "2024" std::fs::write(&cached_cubin, b"persistent cache").unwrap(); let ctx = Context { + link_ltoir: Vec::new(), workspace_root: root.clone(), codegen_crate: root.clone(), examples_dir: root.clone(), @@ -540,6 +663,7 @@ edition = "2024" std::fs::write(example_dir.join("demo.ptx"), b"generated").unwrap(); let ctx = Context { + link_ltoir: Vec::new(), workspace_root: root.clone(), codegen_crate: codegen_crate.clone(), examples_dir, @@ -586,6 +710,7 @@ edition = "2024" symlink(&external, root.join("target")).unwrap(); let ctx = Context { + link_ltoir: Vec::new(), workspace_root: root.clone(), codegen_crate: root.clone(), examples_dir: root.clone(), @@ -3097,6 +3222,7 @@ device-owner = { path = "../device-owner" } .unwrap(); let ctx = Context { + link_ltoir: Vec::new(), workspace_root: root.clone(), codegen_crate: root.join("unused-codegen-source"), examples_dir: root.join("unused-examples"), @@ -3260,6 +3386,7 @@ shared-dep = { path = "../shared-dep" } fn scratch_workspace_context(root: &Path) -> Context { Context { + link_ltoir: Vec::new(), workspace_root: root.to_path_buf(), codegen_crate: root.join("unused-codegen-source"), examples_dir: root.join("unused-examples"), @@ -3539,6 +3666,7 @@ fn passthrough_fingerprint_tracks_output_affecting_settings() { let materialized = MaterializationMode { prepared: Some(PreparedMaterialization { provenance_sha256_hex: "ab".repeat(32), + external_ltoir_json: "[]".to_string(), tool_identity_handshake_json: "{\"version\":1}".to_string(), }), }; @@ -3556,6 +3684,96 @@ fn passthrough_fingerprint_tracks_output_affecting_settings() { ); } +#[test] +fn cleanup_preserves_all_artifacts_when_a_link_input_overlaps() { + let root = unique_temp_dir("cargo_oxide_input_output_overlap"); + fs::create_dir_all(&root).unwrap(); + let first_output = root.join("my_kernel.ptx"); + let input = root.join("my_kernel.ltoir"); + fs::write(&first_output, b"previous output").unwrap(); + fs::write(&input, b"external input").unwrap(); + + let error = + clean_generated_files(&root, "my-kernel", std::slice::from_ref(&input)).unwrap_err(); + assert!(error.contains("move the external input"), "{error}"); + assert_eq!(fs::read(&input).unwrap(), b"external input"); + assert_eq!(fs::read(&first_output).unwrap(), b"previous output"); + + #[cfg(unix)] + for hard_link in [false, true] { + let alias = root.join("external.ltoir"); + if hard_link { + fs::hard_link(&input, &alias).unwrap(); + } else { + std::os::unix::fs::symlink(&input, &alias).unwrap(); + } + assert!(clean_generated_files(&root, "my-kernel", std::slice::from_ref(&alias)).is_err()); + assert_eq!(fs::read(&alias).unwrap(), b"external input"); + assert_eq!(fs::read(&first_output).unwrap(), b"previous output"); + fs::remove_file(alias).unwrap(); + } + + let separate = root.join("separate.ltoir"); + fs::rename(&input, &separate).unwrap(); + clean_generated_files(&root, "my-kernel", std::slice::from_ref(&separate)).unwrap(); + assert!(!first_output.exists()); + assert_eq!(fs::read(&separate).unwrap(), b"external input"); + fs::remove_dir_all(root).unwrap(); +} + +#[test] +fn external_ltoir_order_and_contents_change_the_codegen_fingerprint() { + let ctx = test_context(OxideConfig::default()); + let opts = CargoPassthroughOptions { + verbose: false, + emit_nvvm_ir: false, + arch: Some("sm_120"), + features: None, + cargo_target_dir: None, + device_codegen_crate: None, + device_cfgs: &[], + no_fmad: false, + unchecked_indexing: false, + materialize_cubin: true, + device_debug: DeviceDebug::Off, + debug_assertions: false, + }; + let root = unique_temp_dir("cargo_oxide_external_ltoir"); + fs::create_dir_all(&root).unwrap(); + let first = root.join("first.ltoir"); + let second = root.join("second.ltoir"); + fs::write(&first, b"first").unwrap(); + fs::write(&second, b"other").unwrap(); + let fingerprint = |paths: &[&Path]| { + let inputs: Vec<_> = paths + .iter() + .map(|path| cuda_artifact_finalizer::LtoirFile::capture(path).unwrap()) + .collect(); + let mode = MaterializationMode { + prepared: Some(PreparedMaterialization { + provenance_sha256_hex: "ab".repeat(32), + tool_identity_handshake_json: "{}".into(), + external_ltoir_json: serde_json::to_string(&inputs).unwrap(), + }), + }; + passthrough_codegen_fingerprint_with_env( + &ctx, + &opts, + None, + Some("sm_120"), + &mode, + &BTreeMap::new(), + ) + }; + let original = fingerprint(&[&first, &second]); + assert_eq!(original, fingerprint(&[&first, &second])); + assert_ne!(original, fingerprint(&[&second, &first])); + fs::write(&first, b"later").unwrap(); + assert_ne!(original, fingerprint(&[&first, &second])); + assert_ne!(original, fingerprint(&[&second])); + fs::remove_dir_all(root).unwrap(); +} + #[test] fn passthrough_fingerprint_tracks_non_unicode_presence_switch_bytes() { let ctx = test_context(OxideConfig::default()); @@ -3770,6 +3988,7 @@ fn materialization_forces_nvvm_ir_and_exact_provenance_handshake() { let materialization = MaterializationMode { prepared: Some(PreparedMaterialization { provenance_sha256_hex: "42".repeat(32), + external_ltoir_json: "[]".to_string(), tool_identity_handshake_json: "{\"version\":1}".to_string(), }), }; @@ -5213,6 +5432,7 @@ fn read_ptx_artifact_reports_missing_file() { #[test] fn nvvm_ir_requested_reads_project_configuration() { let ctx = Context { + link_ltoir: Vec::new(), workspace_root: PathBuf::from("/tmp/project"), codegen_crate: PathBuf::from("/tmp/project"), examples_dir: PathBuf::from("/tmp/project"), @@ -5230,6 +5450,7 @@ fn nvvm_ir_requested_reads_project_configuration() { #[test] fn nvvm_ir_requested_accepts_disabled_project_configuration() { let ctx = Context { + link_ltoir: Vec::new(), workspace_root: PathBuf::from("/tmp/project"), codegen_crate: PathBuf::from("/tmp/project"), examples_dir: PathBuf::from("/tmp/project"), @@ -5247,6 +5468,7 @@ fn nvvm_ir_requested_accepts_disabled_project_configuration() { #[test] fn nvvm_ir_requested_env_disable_overrides_enabled_project_configuration() { let ctx = Context { + link_ltoir: Vec::new(), workspace_root: PathBuf::from("/tmp/project"), codegen_crate: PathBuf::from("/tmp/project"), examples_dir: PathBuf::from("/tmp/project"), @@ -6382,7 +6604,7 @@ fn tilelib_artifacts_are_cleaned_between_builds() { for file in &files { std::fs::write(file, b"stale").unwrap(); } - clean_generated_files(&root, "my-lib"); + clean_generated_files(&root, "my-lib", &[]).unwrap(); for file in &files { assert!(!file.exists(), "{} survived the clean", file.display()); } diff --git a/cuda-oxide/crates/cargo-oxide/src/main.rs b/cuda-oxide/crates/cargo-oxide/src/main.rs index 9bdef87cfa..aeb951622d 100644 --- a/cuda-oxide/crates/cargo-oxide/src/main.rs +++ b/cuda-oxide/crates/cargo-oxide/src/main.rs @@ -75,6 +75,10 @@ enum Commands { DebugPolicy, /// Build and run an example or project Run { + /// Link an external LTO-IR file, in argument order (repeatable). + /// Requires --materialize-cubin; paths are relative to the invocation directory. + #[arg(long)] + link_ltoir: Vec, /// Example name (required in workspace, optional for standalone projects) example: Option, /// Generate NVVM IR (use with libNVVM -gen-lto) @@ -126,6 +130,10 @@ enum Commands { }, /// Build and run an example or project under NVIDIA Compute Sanitizer Sanitize { + /// Link an external LTO-IR file, in argument order (repeatable). + /// Requires --materialize-cubin; paths are relative to the invocation directory. + #[arg(long)] + link_ltoir: Vec, /// Example name (required in workspace, optional for standalone projects) example: Option, /// Compute Sanitizer tool to run @@ -171,6 +179,10 @@ enum Commands { }, /// Build an example or project (compile only, don't run) Build { + /// Link an external LTO-IR file, in argument order (repeatable). + /// Requires --materialize-cubin; paths are relative to the invocation directory. + #[arg(long)] + link_ltoir: Vec, /// Example name (required in workspace, optional for standalone projects) example: Option, /// Generate NVVM IR (use with libNVVM -gen-lto) @@ -265,6 +277,10 @@ enum Commands { }, /// Run Cargo tests through the cuda-oxide backend Test { + /// Link an external LTO-IR file, in argument order (repeatable). + /// Requires --materialize-cubin; paths are relative to the invocation directory. + #[arg(long)] + link_ltoir: Vec, /// Target architecture (e.g., sm_90, sm_100, sm_120) #[arg(long)] arch: Option, @@ -404,6 +420,10 @@ enum Commands { }, /// Show the full compilation pipeline (MIR -> PTX/NVVM IR) with verbose output Pipeline { + /// Link an external LTO-IR file, in argument order (repeatable). + /// Requires --materialize-cubin; paths are relative to the invocation directory. + #[arg(long)] + link_ltoir: Vec, /// Example name (required in workspace, optional for standalone projects) example: Option, /// Generate NVVM IR (use with libNVVM -gen-lto) @@ -434,6 +454,10 @@ enum Commands { }, /// Build with debug info and launch cuda-gdb Debug { + /// Link an external LTO-IR file, in argument order (repeatable). + /// Requires --materialize-cubin; paths are relative to the invocation directory. + #[arg(long)] + link_ltoir: Vec, /// Example name (required in workspace, optional for standalone projects) example: Option, /// Target architecture (e.g., sm_90, sm_100, sm_120). When omitted, @@ -604,7 +628,22 @@ fn build_passthrough_trigger( } } +fn external_ltoir_inputs(command: &Commands) -> &[PathBuf] { + match command { + Commands::Run { link_ltoir, .. } + | Commands::Sanitize { link_ltoir, .. } + | Commands::Build { link_ltoir, .. } + | Commands::Test { link_ltoir, .. } + | Commands::Pipeline { link_ltoir, .. } + | Commands::Debug { link_ltoir, .. } => link_ltoir, + _ => &[], + } +} + fn validate_materialization_cli(cli: &Cli) -> Result<(), String> { + if !external_ltoir_inputs(&cli.command).is_empty() && !cli.materialize_cubin { + return Err("--link-ltoir requires --materialize-cubin".to_string()); + } if !cli.materialize_cubin { return Ok(()); } @@ -731,6 +770,12 @@ fn main() { .exit(); } let materialize_cubin = cli.materialize_cubin; + let link_ltoir = external_ltoir_inputs(&cli.command).to_vec(); + let resolve_context = || { + let mut ctx = commands::resolve_context(); + ctx.link_ltoir = link_ltoir.clone(); + ctx + }; match cli.command { Commands::MaterializerHandshake => { @@ -740,6 +785,7 @@ fn main() { commands::print_debug_policy(); } Commands::Run { + link_ltoir: _, example, emit_nvvm_ir, arch, @@ -753,7 +799,7 @@ fn main() { device_debug, app_args, } => { - let ctx = commands::resolve_context(); + let ctx = resolve_context(); let example = resolve_example_name(example, &ctx, "run"); validate_output_arch( &ctx, @@ -779,6 +825,7 @@ fn main() { ); } Commands::Sanitize { + link_ltoir: _, example, tool, arch, @@ -791,7 +838,7 @@ fn main() { device_debug, sanitizer_args, } => { - let ctx = commands::resolve_context(); + let ctx = resolve_context(); let example = resolve_example_name(example, &ctx, "sanitize"); validate_output_arch(&ctx, &example, false, materialize_cubin, arch.as_deref()); let (sanitizer_args, application_args) = @@ -813,6 +860,7 @@ fn main() { ); } Commands::Build { + link_ltoir: _, example, emit_nvvm_ir, arch, @@ -829,7 +877,7 @@ fn main() { device_cfgs, cargo_args, } => { - let ctx = commands::resolve_context(); + let ctx = resolve_context(); let passthrough = use_build_passthrough( explicit_passthrough, cargo_target_dir.is_some(), @@ -919,7 +967,7 @@ fn main() { keep_going, fail_on_finding, } => { - let ctx = commands::resolve_context(); + let ctx = resolve_context(); let (seed_start, seed_end) = ptx_schedule::campaign::parse_seed_range(&seeds) .unwrap_or_else(|error| { eprintln!("Error: {error}"); @@ -983,6 +1031,7 @@ fn main() { } } Commands::Test { + link_ltoir: _, arch, cargo_target_dir, device_codegen_crate, @@ -994,7 +1043,7 @@ fn main() { device_debug, cargo_args, } => { - let ctx = commands::resolve_context(); + let ctx = resolve_context(); validate_output_arch( &ctx, "cargo test", @@ -1033,7 +1082,7 @@ fn main() { lineinfo, device_debug, } => { - let ctx = commands::resolve_context(); + let ctx = resolve_context(); let example = resolve_example_name(example, &ctx, "emit-ltoir"); commands::emit_ltoir( &ctx, @@ -1060,7 +1109,7 @@ fn main() { lineinfo, device_debug, } => { - let ctx = commands::resolve_context(); + let ctx = resolve_context(); let example = resolve_example_name(example, &ctx, "tilelib"); commands::tilelib( &ctx, @@ -1077,6 +1126,7 @@ fn main() { ); } Commands::Pipeline { + link_ltoir: _, example, emit_nvvm_ir, arch, @@ -1085,7 +1135,7 @@ fn main() { lineinfo, device_debug, } => { - let ctx = commands::resolve_context(); + let ctx = resolve_context(); let example = resolve_example_name(example, &ctx, "pipeline"); validate_output_arch( &ctx, @@ -1115,7 +1165,7 @@ fn main() { lineinfo, device_debug, } => { - let ctx = commands::resolve_context(); + let ctx = resolve_context(); let example = resolve_example_name(example, &ctx, "inspect"); commands::codegen_inspect_ptx( &ctx, @@ -1129,6 +1179,7 @@ fn main() { ); } Commands::Debug { + link_ltoir: _, example, arch, features, @@ -1136,7 +1187,7 @@ fn main() { cgdb, tui, } => { - let ctx = commands::resolve_context(); + let ctx = resolve_context(); let example = resolve_example_name(example, &ctx, "debug"); validate_output_arch(&ctx, &example, false, materialize_cubin, arch.as_deref()); commands::codegen_debug( @@ -1177,7 +1228,7 @@ fn main() { commands::doctor(&ctx); } Commands::Setup => { - let ctx = commands::resolve_context(); + let ctx = resolve_context(); commands::setup(&ctx); } Commands::Update { force } => { @@ -1203,6 +1254,12 @@ fn resolve_example_name(name: Option, ctx: &commands::Context, subcomman return n; } if !ctx.is_workspace { + if subcommand == "emit-ltoir" { + return commands::standalone_crate_name(&ctx.workspace_root).unwrap_or_else(|error| { + eprintln!("Error: {error}"); + std::process::exit(1); + }); + } return std::env::current_dir() .ok() .and_then(|p| p.file_name().map(|n| n.to_string_lossy().into_owned())) @@ -1374,6 +1431,47 @@ mod tests { assert_eq!(device_features.as_deref(), Some("tensor-cores")); } + #[test] + fn external_ltoir_requires_materialization_and_preserves_order() { + let unmaterialized = + Cli::try_parse_from(["cargo-oxide", "build", "--link-ltoir", "one"]).unwrap(); + assert!(validate_materialization_cli(&unmaterialized).is_err()); + let cli = Cli::try_parse_from([ + "cargo-oxide", + "build", + "--link-ltoir", + "one", + "--materialize-cubin", + "--link-ltoir", + "two", + ]) + .unwrap(); + assert_eq!( + external_ltoir_inputs(&cli.command), + [ + std::path::PathBuf::from("one"), + std::path::PathBuf::from("two") + ] + ); + validate_materialization_cli(&cli).unwrap(); + + let run = Cli::try_parse_from([ + "cargo-oxide", + "run", + "--link-ltoir", + "one", + "external_ltoir", + "--materialize-cubin", + ]) + .unwrap(); + validate_materialization_cli(&run).unwrap(); + assert_eq!(external_ltoir_inputs(&run.command), [PathBuf::from("one")]); + let Commands::Run { example, .. } = run.command else { + panic!("expected run command"); + }; + assert_eq!(example.as_deref(), Some("external_ltoir")); + } + #[test] fn materialize_cubin_is_a_global_codegen_option() { let after_subcommand = Cli::try_parse_from([ diff --git a/cuda-oxide/crates/cuda-artifact-finalizer/src/lib.rs b/cuda-oxide/crates/cuda-artifact-finalizer/src/lib.rs index 6a014422de..6e02f0c34b 100644 --- a/cuda-oxide/crates/cuda-artifact-finalizer/src/lib.rs +++ b/cuda-oxide/crates/cuda-artifact-finalizer/src/lib.rs @@ -12,6 +12,7 @@ mod diagnostics; mod link; +mod ltoir_file; mod nvvm; mod options; mod provenance; @@ -21,6 +22,7 @@ mod validation; pub use diagnostics::KernelResourceUsage; pub use libnvvm_sys::{CudaArch, CudaArchParseError, LibdeviceNotFound, NvvmError, find_libdevice}; pub use link::{LinkReport, LtoLinker}; +pub use ltoir_file::{LtoirFile, check_ltoir_input_output}; pub use nvjitlink_sys::NvJitLinkError; pub use nvvm::NvvmCompiler; pub use options::{DebugPolicy, FinalizationOptions, FinalizerOutput, NamedInput}; @@ -37,6 +39,20 @@ use thiserror::Error; /// Failures while compiling or linking CUDA artifacts. #[derive(Debug, Error)] pub enum FinalizerError { + /// A file path cannot be transported losslessly to the CUDA linker. + #[error("external LTO-IR path is not Unicode: {path:?}")] + InvalidLtoirPath { path: PathBuf }, + + /// A link input changed after the wrapper computed Cargo's fingerprint. + #[error("external LTO-IR input changed after Cargo fingerprinting: {path}; rerun cargo oxide")] + LtoirInputChanged { path: PathBuf }, + + /// An output would delete or overwrite an explicitly supplied link input. + #[error( + "external LTO-IR input {input} overlaps generated artifact {output}; move the external input to a separate directory" + )] + LtoirInputOutputOverlap { input: PathBuf, output: PathBuf }, + /// libNVVM failed to load, validate, or compile. #[error("libnvvm: {0}")] Nvvm(#[from] libnvvm_sys::NvvmError), diff --git a/cuda-oxide/crates/cuda-artifact-finalizer/src/ltoir_file.rs b/cuda-oxide/crates/cuda-artifact-finalizer/src/ltoir_file.rs new file mode 100644 index 0000000000..92aff18147 --- /dev/null +++ b/cuda-oxide/crates/cuda-artifact-finalizer/src/ltoir_file.rs @@ -0,0 +1,163 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! Content-bound external inputs shared by Cargo fingerprinting and finalization. + +use std::path::{Path, PathBuf}; + +use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; + +use crate::FinalizerError; + +/// Identity of an external LTO-IR file captured before Cargo decides freshness. +/// +/// The absolute path is also the linker's diagnostic input name. Preserve the +/// order of these records when fingerprinting and linking a list of inputs. +/// [`Self::read_verified`] returns owned bytes so a later file change cannot +/// alter the data submitted to the linker. +#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)] +#[serde(deny_unknown_fields)] +pub struct LtoirFile { + path: PathBuf, + sha256: [u8; 32], +} + +impl LtoirFile { + /// Capture the canonical path and SHA-256 of a nonempty input file. + /// + /// Input paths must be Unicode so the same name can reach nvJitLink and + /// the compiler process without lossy conversion. CUDA validates the + /// LTO-IR format and target compatibility during finalization. + pub fn capture(path: &Path) -> Result { + let path = path.canonicalize().map_err(|source| FinalizerError::Io { + path: path.to_owned(), + source, + })?; + if path.to_str().is_none() { + return Err(FinalizerError::InvalidLtoirPath { path }); + } + let bytes = read(&path)?; + Ok(Self { + path, + sha256: Sha256::digest(&bytes).into(), + }) + } + + /// Diagnostic name included in the ordered compilation identity. + pub fn name(&self) -> Result<&str, FinalizerError> { + self.path + .to_str() + .ok_or_else(|| FinalizerError::InvalidLtoirPath { + path: self.path.clone(), + }) + } + + /// Read the exact captured content or fail if it changed before codegen. + pub fn read_verified(&self) -> Result, FinalizerError> { + let bytes = read(&self.path)?; + let actual: [u8; 32] = Sha256::digest(&bytes).into(); + if actual != self.sha256 { + return Err(FinalizerError::LtoirInputChanged { + path: self.path.clone(), + }); + } + Ok(bytes) + } +} + +/// Reject a generated output that aliases an existing external link input. +/// +/// Call before deleting or writing outputs. Canonical paths cover symlinks; +/// Unix file identity also covers hard links with different canonical paths. +pub fn check_ltoir_input_output(input: &Path, output: &Path) -> Result<(), FinalizerError> { + let input_path = input.canonicalize().map_err(|source| FinalizerError::Io { + path: input.to_owned(), + source, + })?; + let output_path = match output.canonicalize() { + Ok(path) => path, + Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(()), + Err(source) => { + return Err(FinalizerError::Io { + path: output.to_owned(), + source, + }); + } + }; + if input_path == output_path || same_file(&input_path, &output_path) { + return Err(FinalizerError::LtoirInputOutputOverlap { + input: input.to_owned(), + output: output.to_owned(), + }); + } + Ok(()) +} + +#[cfg(unix)] +fn same_file(a: &Path, b: &Path) -> bool { + use std::os::unix::fs::MetadataExt; + match (std::fs::metadata(a), std::fs::metadata(b)) { + (Ok(a), Ok(b)) => a.dev() == b.dev() && a.ino() == b.ino(), + _ => false, + } +} + +#[cfg(not(unix))] +fn same_file(_a: &Path, _b: &Path) -> bool { + false +} + +fn read(path: &Path) -> Result, FinalizerError> { + let bytes = std::fs::read(path).map_err(|source| FinalizerError::Io { + path: path.to_owned(), + source, + })?; + if bytes.is_empty() { + return Err(FinalizerError::EmptyInput { + name: path.display().to_string(), + }); + } + Ok(bytes) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn captured_input_checks_content_and_owns_verified_bytes() { + let path = std::env::temp_dir().join(format!( + "oxide-ltoir-{}-{}.test", + std::process::id(), + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_nanos() + )); + std::fs::write(&path, b"first").unwrap(); + let identity = LtoirFile::capture(&path).unwrap(); + let json = serde_json::to_string(&identity).unwrap(); + let restored: LtoirFile = serde_json::from_str(&json).unwrap(); + let owned = restored.read_verified().unwrap(); + std::fs::write(&path, b"other").unwrap(); + assert_eq!(owned, b"first"); + assert!(matches!( + restored.read_verified(), + Err(FinalizerError::LtoirInputChanged { .. }) + )); + assert_ne!(identity, LtoirFile::capture(&path).unwrap()); + std::fs::write(&path, []).unwrap(); + assert!(matches!( + LtoirFile::capture(&path), + Err(FinalizerError::EmptyInput { .. }) + )); + std::fs::remove_file(&path).unwrap(); + assert!(matches!( + restored.read_verified(), + Err(FinalizerError::Io { .. }) + )); + } +} diff --git a/cuda-oxide/crates/cuda-device/src/lib.rs b/cuda-oxide/crates/cuda-device/src/lib.rs index 67ee46790e..bdc255bb12 100644 --- a/cuda-oxide/crates/cuda-device/src/lib.rs +++ b/cuda-oxide/crates/cuda-device/src/lib.rs @@ -41,6 +41,8 @@ pub mod grid; pub mod i16x2; pub mod iket; pub mod int; +#[doc(hidden)] +pub mod library; pub mod mma_frag; pub mod prmt; pub mod ptx; diff --git a/cuda-oxide/crates/cuda-device/src/library.rs b/cuda-oxide/crates/cuda-device/src/library.rs new file mode 100644 index 0000000000..fb20b5ec78 --- /dev/null +++ b/cuda-oxide/crates/cuda-device/src/library.rs @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Internal, versioned boundary for native device library calls. +//! +//! This module is an unsafe compiler integration point, not a collective API. + +/// Read a Cargo-provided registration and track its native build dependencies. +/// +/// Pass the environment variable name as a string literal inside the registration +/// getter. Materialized builds query the provider for file, directory and +/// environment dependencies before rustc emits dep-info. Host checks and rustdoc +/// do not query CUDA inputs. Cargo's timestamp freshness rules still apply; +/// replacements with unchanged or older timestamps may not be detected. +/// +/// This snippet requires a build script to set `MY_LIBRARY_REGISTRATION`; the +/// `native_library` example compiles and runs the same registration pattern. +/// +/// ```ignore +/// fn registration() -> &'static str { +/// cuda_device::library::registration!("MY_LIBRARY_REGISTRATION") +/// } +/// ``` +pub use cuda_macros::library_registration as registration; + +/// Invoke a library recipe identified by a constant registration getter. +/// +/// Call this marker directly inside a wrapper; the marker itself is not a +/// device function pointer or callable-trait value. +/// +/// `Registration` must be a function item returning one constant UTF-8 JSON +/// string. The compiler reads its MIR without calling it. `Args` must be a +/// tuple of the exact scalar and raw-pointer types the provider declares. +/// `T` supplies the scalar type, and the const parameters supply the exact +/// one-dimensional block shape `[BLOCK_THREADS, 1, 1]` and per-thread extent. +/// +/// # Safety +/// +/// The caller must meet the provider's pointer, lifetime, initialization, +/// participation, and launch-geometry requirements. Library scratch views in +/// one kernel alias one dynamic shared base; the caller must synchronize before +/// reusing it. This version does not permit mixing native dynamic +/// shared views with library calls. It returns no allocation or ownership token. +#[inline(never)] +pub unsafe fn cuda_oxide_library_v1_246e25db_call< + T: Copy, + Registration: Fn() -> &'static str + Copy, + Args: Copy, + const BLOCK_THREADS: usize, + const ITEMS_PER_THREAD: usize, +>( + _registration: Registration, + _args: Args, +) { + panic!("library::call_v1 called outside device compilation"); +} + +pub use cuda_oxide_library_v1_246e25db_call as call_v1; diff --git a/cuda-oxide/crates/cuda-device/src/shared.rs b/cuda-oxide/crates/cuda-device/src/shared.rs index 790e24078d..78d59dd53b 100644 --- a/cuda-oxide/crates/cuda-device/src/shared.rs +++ b/cuda-oxide/crates/cuda-device/src/shared.rs @@ -496,6 +496,28 @@ impl DynamicSharedArray { unreachable!("DynamicSharedArray::get called outside CUDA kernel context") } + /// Gets the block's dynamic shared-memory base with a fixed `T` extent. + /// + /// The compiler records `size_of::()` and the stronger of `ALIGN` and + /// `align_of::()` for checked launch preparation. Use an array or a + /// structure to describe the complete region. Every call returns the same + /// base address: multiple views share storage, they do not allocate separate + /// regions. Their required extents and alignments combine by maximum. + /// Inference follows Rust views through direct calls. Dynamic-base use in + /// external code, indirect calls, or inline assembly must fit a fixed view + /// declared on that path; the compiler does not inspect those accesses. + /// + /// # Safety + /// + /// Access only the declared `T` region, initialize values before reading, + /// and synchronize conflicting accesses across threads. Concurrent views + /// alias; this function establishes neither exclusive ownership nor a + /// synchronization barrier. Raw launches must allocate sufficient memory. + #[inline(never)] + pub unsafe fn get_fixed() -> *mut T { + unreachable!("DynamicSharedArray::get_fixed called outside CUDA kernel context") + } + /// Get a raw byte pointer to the start of dynamic shared memory. /// /// This is useful for manual memory management or when working @@ -752,3 +774,9 @@ impl SharedPtr { } include!("generated/shared_sreg.rs"); + +/// Selects compiler-produced dynamic shared-memory requirements. +/// Emitted by `#[launch_contract(dynamic_shared = inferred)]`. +#[doc(hidden)] +#[inline(never)] +pub fn __dynamic_shared_inferred() {} diff --git a/cuda-oxide/crates/cuda-host/Cargo.toml b/cuda-oxide/crates/cuda-host/Cargo.toml index e24c5fc2ba..e90f1334f2 100644 --- a/cuda-oxide/crates/cuda-host/Cargo.toml +++ b/cuda-oxide/crates/cuda-host/Cargo.toml @@ -33,6 +33,6 @@ async = ["dep:cuda-async", "cuda-macros/async"] [dev-dependencies] libloading = { workspace = true } cuda-device = { workspace = true } -# The crates.io release cuda-core re-exports bundle types from; tests -# construct payloads with it so they use the same crate instance. +# The same artifact implementation cuda-core re-exports; tests construct +# payloads with it so they use the same crate instance. oxide-artifacts = { workspace = true } diff --git a/cuda-oxide/crates/cuda-host/src/embedded.rs b/cuda-oxide/crates/cuda-host/src/embedded.rs index 48776448f2..e8cc4ff503 100644 --- a/cuda-oxide/crates/cuda-host/src/embedded.rs +++ b/cuda-oxide/crates/cuda-host/src/embedded.rs @@ -12,6 +12,7 @@ pub use cuda_core::embedded::{ embedded_modules_from_current_exe, }; use cuda_core::{CudaContext, CudaModule, DriverError}; +use std::collections::BTreeMap; use std::sync::Arc; use thiserror::Error; @@ -45,6 +46,16 @@ pub enum EmbeddedModuleError { #[error("embedded CUDA module '{name}' contains invalid PTX: {reason}")] InvalidPtx { name: String, reason: String }, + /// Bundles disagree about the requirements of the same concrete entry. + #[error("conflicting compiled launch facts for kernel '{symbol}'")] + ConflictingLaunchFacts { symbol: String }, + + /// Generic loading needs one complete native image or a PTX-only bundle set. + #[error( + "generic CUDA loading requires one complete cubin bundle or only PTX bundles; incompatible embedded bundles: {names:?}" + )] + IncompatibleGenericArtifacts { names: Vec }, + /// NVVM IR or LTOIR payload compilation failed. #[error("failed to build embedded CUDA module: {0}")] Ltoir(#[from] ltoir::LtoirError), @@ -135,9 +146,99 @@ pub fn load_all_ptx_bundles_merged( ctx: &Arc, ) -> Result, EmbeddedModuleError> { let bundles = artifact_bundles_from_current_exe()?; - let merged = merge_ptx_bundles(&bundles)?; + load_merged_ptx(ctx, &bundles) +} + +/// Load generic kernel specializations from the image containing `anchor`. +/// +/// A single materialized cubin contains all required concrete entries and keeps +/// their globals in one CUDA module. Multiple native bundles, or native and PTX +/// bundles together, are rejected because independently loaded images would +/// not preserve shared device globals. A PTX-only set uses the existing merge. +/// Empty anchor-only bundles do not participate in payload selection. +/// +/// `anchor` must belong to the host image whose artifacts are to be loaded. +/// Generated loaders anchor the defining crate's host code; the instantiating +/// crate must be linked into that same image. This applies to PTX builds too. +/// Image discovery has the same platform and file-identity requirements as +/// [`load_embedded_module_from_anchor`]. Entry lookup uses the exact concrete +/// symbol name and retains each entry's compiled launch facts. +pub fn load_generic_embedded_module_from_anchor( + ctx: &Arc, + anchor: &u8, +) -> Result, EmbeddedModuleError> { + let bundles = artifact_bundles_containing(anchor)?; + load_generic_bundles(ctx, &bundles) +} + +/// Load generic kernel specializations from the current executable. +/// +/// Uses the same native-artifact selection and PTX merge as +/// [`load_generic_embedded_module_from_anchor`]. Generated loaders use this +/// executable-only discovery on platforms without mapped-image support. +pub fn load_generic_embedded_module( + ctx: &Arc, +) -> Result, EmbeddedModuleError> { + let bundles = artifact_bundles_from_current_exe()?; + load_generic_bundles(ctx, &bundles) +} - let module = ctx.load_module_from_image(merged.as_bytes())?; +fn load_generic_bundles( + ctx: &Arc, + bundles: &[OwnedArtifactBundle], +) -> Result, EmbeddedModuleError> { + if let Some(bundle) = generic_cubin_bundle(bundles)? { + let module = load_bundle(ctx, bundle)?; + crate::entry_registry::register_module_entries( + &module, + bundle + .entries + .iter() + .filter(|entry| entry.kind == oxide_artifacts::ArtifactEntryKind::Kernel) + .map(|entry| entry.symbol.clone()) + .collect(), + ); + Ok(module) + } else { + load_merged_ptx(ctx, bundles) + } +} + +fn generic_cubin_bundle( + bundles: &[OwnedArtifactBundle], +) -> Result, EmbeddedModuleError> { + let active: Vec<_> = bundles + .iter() + .filter(|bundle| !bundle.payloads.is_empty()) + .collect(); + match active.as_slice() { + [] => Err(EmbeddedModuleError::NoModules), + [bundle] if bundle.payload(ArtifactPayloadKind::Cubin).is_some() => Ok(Some(bundle)), + _ if active.iter().all(|bundle| { + bundle.payload(ArtifactPayloadKind::Cubin).is_none() + && bundle.payload(ArtifactPayloadKind::Ptx).is_some() + }) => + { + Ok(None) + } + _ => Err(EmbeddedModuleError::IncompatibleGenericArtifacts { + names: active.iter().map(|bundle| bundle.name.clone()).collect(), + }), + } +} + +fn load_merged_ptx( + ctx: &Arc, + bundles: &[OwnedArtifactBundle], +) -> Result, EmbeddedModuleError> { + let merged = merge_ptx_bundles(bundles)?; + + let facts = merged_launch_facts( + bundles + .iter() + .filter(|bundle| bundle.payload(ArtifactPayloadKind::Ptx).is_some()), + )?; + let module = ctx.load_module_from_image_with_launch_facts(merged.as_bytes(), facts)?; // Retain the merged module's `.entry` names (a few dozen bytes per // kernel). If a later `_TID_` generic-kernel lookup misses while a // same-base entry exists under a different hash, the launch paths can @@ -147,6 +248,32 @@ pub fn load_all_ptx_bundles_merged( Ok(module) } +fn merged_launch_facts<'a>( + bundles: impl IntoIterator, +) -> Result, EmbeddedModuleError> { + // Keep None in the comparison: absent facts must not silently replace a + // known zero-size plan, or inherit another bundle's contract. + let mut entries = BTreeMap::new(); + for bundle in bundles { + for entry in &bundle.entries { + if entry.kind != oxide_artifacts::ArtifactEntryKind::Kernel { + continue; + } + if let Some(previous) = entries.insert(entry.symbol.clone(), entry.launch_facts) + && previous != entry.launch_facts + { + return Err(EmbeddedModuleError::ConflictingLaunchFacts { + symbol: entry.symbol.clone(), + }); + } + } + } + Ok(entries + .into_iter() + .filter_map(|(symbol, facts)| facts.map(|facts| (symbol, facts))) + .collect()) +} + /// Merge the PTX payloads of `bundles`, in iteration order, into one PTX /// module string: the first PTX bundle keeps its `.version` / `.target` / /// `.address_size` header directives, every later one contributes its body @@ -297,12 +424,13 @@ fn load_bundle( ctx: &Arc, bundle: &OwnedArtifactBundle, ) -> Result, EmbeddedModuleError> { + let facts = merged_launch_facts([bundle])?; if let Some(cubin) = bundle.payload(ArtifactPayloadKind::Cubin) { - return Ok(ctx.load_module_from_image(cubin)?); + return Ok(ctx.load_module_from_image_with_launch_facts(cubin, facts)?); } if let Some(ptx) = bundle.payload(ArtifactPayloadKind::Ptx) { - return Ok(ctx.load_module_from_image(ptx)?); + return Ok(ctx.load_module_from_image_with_launch_facts(ptx, facts)?); } if let Some(nvvm_ir) = bundle.payload(ArtifactPayloadKind::NvvmIr) { @@ -322,7 +450,7 @@ fn load_bundle( bundle.compile_options, )?, }; - return Ok(ctx.load_module_from_image(&image)?); + return Ok(ctx.load_module_from_image_with_launch_facts(&image, facts)?); } if let Some(ltoir) = bundle.payload(ArtifactPayloadKind::Ltoir) { @@ -342,7 +470,7 @@ fn load_bundle( bundle.compile_options, )?, }; - return Ok(ctx.load_module_from_image(&image)?); + return Ok(ctx.load_module_from_image_with_launch_facts(&image, facts)?); } Err(EmbeddedModuleError::UnsupportedPayload { @@ -389,6 +517,59 @@ mod tests { } } + #[test] + fn merged_kernel_facts_preserve_identity_and_reject_conflicts() { + use oxide_artifacts::{ + ArtifactBundleSpec, ArtifactEntryKind, ArtifactEntrySpec, ArtifactPayloadSpec, + KernelLaunchFacts, + }; + let facts = KernelLaunchFacts { + exact_block: Some((32, 1, 1)), + dynamic_shared_bytes: 0, + dynamic_shared_alignment: 16, + }; + let bundle = |symbol: &str, facts| { + let mut entry = ArtifactEntrySpec::new(symbol, ArtifactEntryKind::Kernel); + entry.launch_facts = facts; + let spec = ArtifactBundleSpec::new("test", "sm_120") + .with_payload(ArtifactPayloadSpec::new( + ArtifactPayloadKind::Ptx, + "test.ptx", + b"ptx", + )) + .with_entry(entry); + let bytes = oxide_artifacts::build_artifact_blob(&spec).unwrap(); + OwnedArtifactBundle::from(oxide_artifacts::parse_artifact_blob(&bytes).unwrap()) + }; + let first = bundle("apply_items_1", Some(facts)); + let second = bundle( + "apply_items_4", + Some(KernelLaunchFacts { + dynamic_shared_bytes: 512, + ..facts + }), + ); + let merged = merged_launch_facts([&first, &second]).unwrap(); + assert_eq!(merged["apply_items_1"].dynamic_shared_bytes, 0); + assert_eq!(merged["apply_items_4"].dynamic_shared_bytes, 512); + for conflict in [ + bundle("apply_items_1", None), + bundle( + "apply_items_1", + Some(KernelLaunchFacts { + dynamic_shared_bytes: 128, + ..facts + }), + ), + ] { + assert!(matches!( + merged_launch_facts([&first, &conflict]), + Err(EmbeddedModuleError::ConflictingLaunchFacts { .. }) + )); + } + assert_eq!(merged_launch_facts([&first, &first]).unwrap().len(), 1); + } + #[test] fn target_arch_uses_bundle_sm_target() { assert_eq!( @@ -414,6 +595,49 @@ mod tests { } } + #[test] + fn generic_loading_selects_one_native_image_or_merges_ptx() { + let mut native = ptx_bundle("consumer", "native bytes"); + native.payloads[0].kind = ArtifactPayloadKind::Cubin; + let bundles = [bundle_with_target("sm_120"), native]; + assert!(std::ptr::eq( + generic_cubin_bundle(&bundles).unwrap().unwrap(), + &bundles[1] + )); + assert!( + generic_cubin_bundle(&[ptx_bundle("library", "ptx"), ptx_bundle("consumer", "ptx")]) + .unwrap() + .is_none() + ); + assert!(matches!( + generic_cubin_bundle(&[bundle_with_target("sm_120")]), + Err(EmbeddedModuleError::NoModules) + )); + } + + #[test] + fn generic_loading_rejects_native_ambiguity_and_mixed_payloads() { + for kind in [ + ArtifactPayloadKind::Cubin, + ArtifactPayloadKind::Ptx, + ArtifactPayloadKind::NvvmIr, + ArtifactPayloadKind::Ltoir, + ] { + let mut native = ptx_bundle("consumer", "native bytes"); + native.payloads[0].kind = ArtifactPayloadKind::Cubin; + let mut other = ptx_bundle("library", "other bytes"); + other.payloads[0].kind = kind; + // Entry-free payloads can still define device globals. + assert!(other.entries.is_empty()); + let error = generic_cubin_bundle(&[native, other]).unwrap_err(); + assert!(matches!( + error, + EmbeddedModuleError::IncompatibleGenericArtifacts { names } + if names == ["consumer", "library"] + )); + } + } + /// The merge is order-explicit: exactly one header set (the first PTX /// bundle's), every body present in iteration order, non-PTX bundles /// skipped. #1277's collision-free-namespace example checks the same diff --git a/cuda-oxide/crates/cuda-host/src/entry_registry.rs b/cuda-oxide/crates/cuda-host/src/entry_registry.rs index 657da3159a..933333dbfa 100644 --- a/cuda-oxide/crates/cuda-host/src/entry_registry.rs +++ b/cuda-oxide/crates/cuda-host/src/entry_registry.rs @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -//! Retained PTX entry names for merged modules, and the host/device +//! Retained entry names for loaded artifacts and merged PTX, and the host/device //! type-identity divergence diagnosis built on them. //! //! # Why this exists @@ -20,7 +20,8 @@ //! opaque `DriverError(500, "named symbol not found")`. //! //! To make that failure self-explaining, [`crate::load_all_ptx_bundles_merged`] -//! retains the `.entry` names it already parses out of the merged PTX. When a +//! retains the `.entry` names it already parses out of the merged PTX. Native +//! generic loading retains exact entry names from its artifact metadata. When a //! generic-kernel lookup later misses, the macro-generated launch paths call //! [`diagnose_generic_kernel_load_error`] / //! [`panic_generic_kernel_load_failed`]: if the module holds the same base @@ -61,8 +62,7 @@ const TYPE_ID_HASH_LEN: usize = 32; /// One retained record: the (weakly held) owning module and its entry names. type RetainedEntries = (Weak, Arc>); -/// Process-wide map from a loaded module to the PTX `.entry` names it was -/// built from. +/// Process-wide map from a loaded module to its retained kernel entry names. /// /// Keyed by allocation identity of the owning [`Arc`]: a [`Weak`] pins the /// allocation (not the value), so pointer equality against a live `Arc` is @@ -119,10 +119,15 @@ fn merged_module_entries() -> &'static EntryRegistry { /// driver was happy with. pub(crate) fn register_merged_module_entries(module: &Arc, merged_ptx: &str) { if let Some(entries) = entry_names_from_ptx(merged_ptx) { - merged_module_entries().register(module, entries); + register_module_entries(module, entries); } } +/// Retains exact entry names from a loaded artifact or parsed merged PTX. +pub(crate) fn register_module_entries(module: &Arc, entries: Vec) { + merged_module_entries().register(module, entries); +} + /// Parses PTX text and returns the names of its `.entry` kernels. /// /// `.func` device helpers are excluded: only `.entry` symbols are launchable, @@ -173,7 +178,7 @@ fn divergent_entries_in(entries: &[String], requested: &str) -> Vec { /// name but carry a different `_TID_` type-identity hash. /// /// Empty when `requested` is not a `_TID_` name, when `module` was not loaded -/// through [`crate::load_all_ptx_bundles_merged`], or when no same-base entry +/// through a generic native or merged-PTX loader, or when no same-base entry /// exists; i.e. whenever the miss is an ordinary miss. pub fn divergent_type_id_entries(module: &Arc, requested: &str) -> Vec { match merged_module_entries().entries_for(module) { diff --git a/cuda-oxide/crates/cuda-host/src/lib.rs b/cuda-oxide/crates/cuda-host/src/lib.rs index 1fa90924a7..aaeccdc52f 100644 --- a/cuda-oxide/crates/cuda-host/src/lib.rs +++ b/cuda-oxide/crates/cuda-host/src/lib.rs @@ -135,7 +135,8 @@ pub use cuda_async::simt::launch::{ pub use embedded::{ EmbeddedModuleError, load_all_ptx_bundles_merged, load_embedded_module, - load_embedded_module_from_anchor, load_first_embedded_module, merge_ptx_bundles, + load_embedded_module_from_anchor, load_first_embedded_module, load_generic_embedded_module, + load_generic_embedded_module_from_anchor, merge_ptx_bundles, }; pub use entry_registry::{ diagnose_generic_kernel_load_error, divergent_type_id_entries, panic_generic_kernel_load_failed, diff --git a/cuda-oxide/crates/cuda-macros/Cargo.toml b/cuda-oxide/crates/cuda-macros/Cargo.toml index 16a25c8459..7366e343b8 100644 --- a/cuda-oxide/crates/cuda-macros/Cargo.toml +++ b/cuda-oxide/crates/cuda-macros/Cargo.toml @@ -38,6 +38,8 @@ host = [] [dependencies] quote = { workspace = true } syn = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } proc-macro2 = { workspace = true } reserved-oxide-symbols = { workspace = true } # `#[tile_export]` builds its description with the shared vocabulary and embeds diff --git a/cuda-oxide/crates/cuda-macros/src/cuda_module/contract.rs b/cuda-oxide/crates/cuda-macros/src/cuda_module/contract.rs index 1281fd70d9..b243f8ff3c 100644 --- a/cuda-oxide/crates/cuda-macros/src/cuda_module/contract.rs +++ b/cuda-oxide/crates/cuda-macros/src/cuda_module/contract.rs @@ -22,6 +22,7 @@ use syn::{ #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub(crate) enum DynamicSharedContract { + Inferred, Exact(u32), Range { min_bytes: u32, max_bytes: u32 }, } @@ -95,8 +96,19 @@ impl Parse for LaunchContractArgs { } "dynamic_shared" => { reject_duplicate(&key, dynamic_shared.is_some())?; - let value: syn::LitInt = input.parse()?; - dynamic_shared = Some(value.base10_parse::()?); + dynamic_shared = Some(if input.peek(syn::LitInt) { + let value: syn::LitInt = input.parse()?; + DynamicSharedContract::Exact(value.base10_parse::()?) + } else { + let value: Ident = input.parse()?; + if value != "inferred" { + return Err(syn::Error::new( + value.span(), + "dynamic_shared expects a byte count or `inferred`", + )); + } + DynamicSharedContract::Inferred + }); } "dynamic_shared_range" => { reject_duplicate(&key, dynamic_shared_range.is_some())?; @@ -149,7 +161,7 @@ impl Parse for LaunchContractArgs { )); } let dynamic_shared = match (dynamic_shared, dynamic_shared_range) { - (Some(bytes), None) => DynamicSharedContract::Exact(bytes), + (Some(requirement), None) => requirement, (None, Some((min_bytes, max_bytes))) if min_bytes <= max_bytes => { DynamicSharedContract::Range { min_bytes, @@ -165,6 +177,12 @@ impl Parse for LaunchContractArgs { (None, None) => DynamicSharedContract::Exact(0), (Some(_), Some(_)) => unreachable!(), }; + if dynamic_shared == DynamicSharedContract::Inferred && dynamic_shared_alignment.is_some() { + return Err(syn::Error::new( + input.span(), + "inferred dynamic shared memory obtains alignment from the compiled layout", + )); + } let dynamic_shared_alignment = dynamic_shared_alignment.unwrap_or_else(|| { if dynamic_shared_max(dynamic_shared) == 0 { 1 @@ -216,6 +234,7 @@ fn parse_requires_relations(input: ParseStream) -> syn::Result> { pub(crate) fn dynamic_shared_max(contract: DynamicSharedContract) -> u32 { match contract { + DynamicSharedContract::Inferred => 0, DynamicSharedContract::Exact(bytes) => bytes, DynamicSharedContract::Range { max_bytes, .. } => max_bytes, } diff --git a/cuda-oxide/crates/cuda-macros/src/cuda_module/launchers.rs b/cuda-oxide/crates/cuda-macros/src/cuda_module/launchers.rs index 279a15cce4..5a15350100 100644 --- a/cuda-oxide/crates/cuda-macros/src/cuda_module/launchers.rs +++ b/cuda-oxide/crates/cuda-macros/src/cuda_module/launchers.rs @@ -239,6 +239,9 @@ pub(super) fn generate_cuda_module_launch_contract_impl( }); let alignment = contract.dynamic_shared_alignment; let dynamic_shared = match contract.dynamic_shared { + DynamicSharedContract::Inferred => { + quote! { ::cuda_core::DynamicSharedMemoryRequirement::Inferred } + } DynamicSharedContract::Exact(bytes) => quote! { ::cuda_core::DynamicSharedMemoryRequirement::Exact { bytes: #bytes, diff --git a/cuda-oxide/crates/cuda-macros/src/cuda_module/mod.rs b/cuda-oxide/crates/cuda-macros/src/cuda_module/mod.rs index 58d0902427..43a2ccaa2d 100644 --- a/cuda-oxide/crates/cuda-macros/src/cuda_module/mod.rs +++ b/cuda-oxide/crates/cuda-macros/src/cuda_module/mod.rs @@ -135,9 +135,9 @@ pub(crate) fn expand_cuda_module_inner( let cfg_attrs = &kernel.effective_cfg_attrs; Some(quote! { #(#cfg_attrs)* - // Consumed by the codegen collector. This enabled generic kernel - // requires run-time PTX bundle merging, which ahead-of-time cubin - // materialization cannot represent yet. + // Retain the existing generic-module identity marker consumed by + // the collector. PTX builds merge bundles; materialized builds + // require one complete native artifact at load time. #[doc(hidden)] #[used] #[allow(dead_code, non_upper_case_globals)] @@ -190,8 +190,21 @@ pub(crate) fn expand_cuda_module_inner( let mut __cuda_oxide_has_enabled_generic_kernel = false; #(#enable_generic_loader_statements)* let module = if __cuda_oxide_has_enabled_generic_kernel { - let _ = name; // merged load ignores the crate-name hint - ::cuda_host::load_all_ptx_bundles_merged(ctx)? + let _ = name; // monomorphizations can belong to the consuming crate + // This identifies the host image; artifact object retention is + // still handled by the compiler's existing embedding path. + #[cfg(any(target_os = "linux", target_os = "android"))] + { + static __CUDA_OXIDE_GENERIC_IMAGE: u8 = 0; + ::cuda_host::load_generic_embedded_module_from_anchor( + ctx, + &__CUDA_OXIDE_GENERIC_IMAGE, + )? + } + #[cfg(not(any(target_os = "linux", target_os = "android")))] + { + ::cuda_host::load_generic_embedded_module(ctx)? + } } else { #embedded_module_loader }; @@ -232,8 +245,12 @@ pub(crate) fn expand_cuda_module_inner( /// For a non-generic module, the selected package bundle must be /// the artifact compiled from this `cuda_module`; package names are /// not yet unique across all library and binary targets. For a - /// generic module, the merged PTX set must contain each matching - /// specialization and no conflicting entry definition. + /// generic module, the selected native artifact or merged PTX set + /// must contain each matching specialization and no conflicting + /// entry definition. + /// On Linux, the defining crate's loader and the crate instantiating + /// generic kernels must be linked into the same host image. Native + /// and PTX discovery read that mapped image, with no fallback. pub unsafe fn load_async( device_id: usize, ) -> ::core::result::Result { @@ -285,8 +302,12 @@ pub(crate) fn expand_cuda_module_inner( /// For a non-generic module, the selected package bundle must be /// the artifact compiled from this `cuda_module`; package names are /// not yet unique across all library and binary targets. For a - /// generic module, the merged PTX set must contain each matching - /// specialization and no conflicting entry definition. + /// generic module, the selected native artifact or merged PTX set + /// must contain each matching specialization and no conflicting + /// entry definition. + /// On Linux, the defining crate's loader and the crate instantiating + /// generic kernels must be linked into the same host image. Native + /// and PTX discovery read that mapped image, with no fallback. pub unsafe fn load( ctx: &::std::sync::Arc<::cuda_core::CudaContext>, ) -> ::core::result::Result { @@ -312,6 +333,9 @@ pub(crate) fn expand_cuda_module_inner( /// Every selected kernel must have the exact ABI and resource /// semantics declared by this `cuda_module`. A matching symbol /// name alone is not sufficient. + /// Generic instantiations must share the defining crate's host + /// image. On Linux, discovery reads that mapped image, without + /// falling back to the executable; the name hint is ignored. pub unsafe fn load_named( ctx: &::std::sync::Arc<::cuda_core::CudaContext>, name: &str, @@ -324,6 +348,9 @@ pub(crate) fn expand_cuda_module_inner( } } else { quote! { + /// Generic instantiations must share the defining crate's host + /// image. On Linux, discovery reads that mapped image, without + /// falling back to the executable; the name hint is ignored. pub fn load_named( ctx: &::std::sync::Arc<::cuda_core::CudaContext>, name: &str, @@ -342,7 +369,8 @@ pub(crate) fn expand_cuda_module_inner( /// /// Every loaded kernel must have the exact ABI and resource /// semantics declared by this `cuda_module`. A matching symbol - /// name alone is not sufficient. + /// name alone is not sufficient. Any attached compiled launch facts + /// must truthfully describe that exact loaded image and entry. pub unsafe fn from_module( module: ::std::sync::Arc<::cuda_core::CudaModule>, ) -> ::core::result::Result { diff --git a/cuda-oxide/crates/cuda-macros/src/kernel/scope.rs b/cuda-oxide/crates/cuda-macros/src/kernel/scope.rs index 872e34848a..8fc20d7391 100644 --- a/cuda-oxide/crates/cuda-macros/src/kernel/scope.rs +++ b/cuda-oxide/crates/cuda-macros/src/kernel/scope.rs @@ -584,13 +584,18 @@ pub(crate) fn is_kernel_configuration_marker(statement: &Stmt) -> bool { || segments[0].ident != "cuda_device" || !matches!(segments[0].arguments, PathArguments::None) || !matches!(segments[1].arguments, PathArguments::None) - || !matches!(segments[2].arguments, PathArguments::AngleBracketed(_)) { return false; } let module = &segments[1].ident; let marker = &segments[2].ident; + if module == "shared" && marker == "__dynamic_shared_inferred" { + return !unsafe_wrapped && matches!(segments[2].arguments, PathArguments::None); + } + if !matches!(segments[2].arguments, PathArguments::AngleBracketed(_)) { + return false; + } if unsafe_wrapped { module == "thread" && (marker == "__launch_contract_config" || marker == "__grid_constant_config") diff --git a/cuda-oxide/crates/cuda-macros/src/launch_attrs.rs b/cuda-oxide/crates/cuda-macros/src/launch_attrs.rs index b10f4cd455..411ef20210 100644 --- a/cuda-oxide/crates/cuda-macros/src/launch_attrs.rs +++ b/cuda-oxide/crates/cuda-macros/src/launch_attrs.rs @@ -181,7 +181,14 @@ pub(crate) fn inject_launch_contract_markers(args: &LaunchContractArgs, input: & next += 1; } - if dynamic_shared_max(args.dynamic_shared) != 0 { + if args.dynamic_shared == crate::cuda_module::contract::DynamicSharedContract::Inferred { + input.block.stmts.insert( + next, + parse_quote! { + ::cuda_device::shared::__dynamic_shared_inferred(); + }, + ); + } else if dynamic_shared_max(args.dynamic_shared) != 0 { let alignment = args.dynamic_shared_alignment as usize; let alignment_marker: syn::Stmt = parse_quote! { ::cuda_device::shared::__dynamic_shared_alignment::<#alignment>(); diff --git a/cuda-oxide/crates/cuda-macros/src/lib.rs b/cuda-oxide/crates/cuda-macros/src/lib.rs index 0a3d738b55..3e91b80752 100644 --- a/cuda-oxide/crates/cuda-macros/src/lib.rs +++ b/cuda-oxide/crates/cuda-macros/src/lib.rs @@ -29,7 +29,7 @@ //! so the same switch that turns host emission on also adds the `cuda-host` //! dependency that resolves it. -#![feature(proc_macro_def_site, proc_macro_tracked_env)] +#![feature(proc_macro_def_site, proc_macro_tracked_env, proc_macro_tracked_path)] mod common; mod cuda_module; @@ -37,6 +37,7 @@ mod device; mod kernel; mod launch; mod launch_attrs; +mod library; mod printf; mod ptx_asm; mod tile_export; @@ -649,8 +650,23 @@ pub fn launch_bounds(attr: TokenStream, item: TokenStream) -> TokenStream { /// the rest of the declared contract without preparation. /// /// Dynamic shared memory may be fixed with `dynamic_shared = BYTES` or bounded -/// with `dynamic_shared_range = (MIN, MAX)`. The byte extent remains an author -/// contract because arbitrary pointer arithmetic cannot be inferred. When the +/// with `dynamic_shared_range = (MIN, MAX)`. With `dynamic_shared = inferred`, +/// the compiler records the complete byte extent and alignment of unsafe +/// `DynamicSharedArray::get_fixed` views, including calls through helpers. +/// These views alias one dynamic base region; their extents combine by maximum, +/// not by addition. Mixing inferred views with unconstrained `get`, `get_raw`, +/// or `offset` access is rejected. Prepared launches require the matching +/// compiled artifact facts; `LaunchConfig1D::auto_shared` (and its 2D/3D +/// counterparts) selects the recorded byte count. An explicit byte count is +/// still checked before launch. Inferred alignment comes from the compiled +/// layouts, so it cannot be combined with `dynamic_shared_alignment`. +/// Inference follows Rust views through direct calls. Unsafe external code, +/// indirect calls and inline assembly may use the dynamic base only within a +/// fixed view declared on that path; their accesses are not analyzed. An inferred +/// kernel with no declared views records zero bytes. +/// +/// For raw dynamic pointers, the byte extent remains an author contract because +/// arbitrary pointer arithmetic cannot be inferred. When the /// maximum is non-zero, the macro injects a compiler marker whose call is /// removed before code generation. The declared `dynamic_shared_alignment` /// therefore becomes a minimum alignment in generated PTX without adding @@ -1015,10 +1031,14 @@ pub fn tile_export(attr: TokenStream, item: TokenStream) -> TokenStream { // NVVM Attributes for Device FFI // ============================================================================ -/// Marks a device function as convergent. +/// Marks an external device function declaration as convergent. /// -/// Convergent functions must be called by all threads in a warp/block together. -/// This prevents the optimizer from moving calls across control flow boundaries. +/// LLVM forbids transformations that add control dependencies to the call, +/// including before external device definitions are linked. The annotation +/// does not make threads reach the call or guarantee reconvergence. Callers +/// must satisfy the function's warp or block participation requirements. +/// Every declaration of the same symbol reachable in a device module must +/// agree on this annotation; conflicting declarations are rejected. /// /// # When to Use /// @@ -1039,77 +1059,32 @@ pub fn tile_export(attr: TokenStream, item: TokenStream) -> TokenStream { /// # Generated LLVM IR /// /// ```llvm -/// declare float @cub_block_reduce_sum(float, ptr) #0 -/// attributes #0 = { convergent nounwind } +/// declare float @cub_block_reduce_sum(float, ptr) convergent /// ``` #[proc_macro_attribute] pub fn convergent(_attr: TokenStream, item: TokenStream) -> TokenStream { - // This is a marker attribute - just pass through the item unchanged. - // The collector will read this attribute and apply the LLVM convergent attribute. - item + // The procedural attribute disappears during expansion. A doc alias is + // retained in metadata even for private foreign items, unlike doc comments. + let marker = reserved_oxide_symbols::DEVICE_EXTERN_CONVERGENT_MARKER; + let item = proc_macro2::TokenStream::from(item); + quote::quote!(#[doc(alias = #marker)] #item).into() } -/// Marks a device function as pure (no side effects). -/// -/// Pure functions only depend on their inputs and have no side effects. -/// This enables aggressive optimizations like CSE and dead code elimination. -/// -/// # When to Use -/// -/// - Math functions that don't access memory -/// - Functions that compute results purely from input arguments +/// Compatibility annotation for a pure device function. /// -/// # Example -/// -/// ```ignore -/// #[device] -/// extern "C" { -/// #[pure] -/// fn fast_rsqrt(x: f32) -> f32; -/// } -/// ``` -/// -/// # Generated LLVM IR -/// -/// ```llvm -/// declare float @fast_rsqrt(float) #0 -/// attributes #0 = { nounwind readnone } -/// ``` +/// This annotation is currently inactive: it records no compiler effect and +/// emits no LLVM memory-effect attributes. #[proc_macro_attribute] pub fn pure(_attr: TokenStream, item: TokenStream) -> TokenStream { - // Marker attribute - collector will read and apply LLVM readnone attribute item } -/// Marks a device function as read-only. +/// Compatibility annotation for a read-only device function. /// -/// Read-only functions may read memory but never write to it. -/// This enables optimizations like load hoisting and caching. -/// -/// # When to Use -/// -/// - Lookup table functions -/// - Functions that only read from input arrays -/// -/// # Example -/// -/// ```ignore -/// #[device] -/// extern "C" { -/// #[readonly] -/// fn lookup_table(table: *const f32, idx: i32) -> f32; -/// } -/// ``` -/// -/// # Generated LLVM IR -/// -/// ```llvm -/// declare float @lookup_table(ptr, i32) #0 -/// attributes #0 = { nounwind readonly } -/// ``` +/// This annotation is currently inactive: it records no compiler effect and +/// emits no LLVM memory-effect attributes. #[proc_macro_attribute] pub fn readonly(_attr: TokenStream, item: TokenStream) -> TokenStream { - // Marker attribute - collector will read and apply LLVM readonly attribute item } @@ -1275,3 +1250,16 @@ pub fn cuda_launch_async(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as CudaLaunchAsyncInput); expand_cuda_launch_async(input).into() } + +/// Embed a native library registration from a tracked environment variable. +/// +/// Re-exported as `cuda_device::library::registration!`. Tracks the provider +/// executable and, during CUBIN materialization, its declared native inputs. +/// Ordinary host and documentation builds do not query CUDA toolkit inputs. +#[proc_macro] +pub fn library_registration(input: TokenStream) -> TokenStream { + let variable = parse_macro_input!(input as syn::LitStr); + library::expand(&variable) + .unwrap_or_else(|error| syn::Error::new(variable.span(), error).to_compile_error()) + .into() +} diff --git a/cuda-oxide/crates/cuda-macros/src/library.rs b/cuda-oxide/crates/cuda-macros/src/library.rs new file mode 100644 index 0000000000..3de32d7759 --- /dev/null +++ b/cuda-oxide/crates/cuda-macros/src/library.rs @@ -0,0 +1,239 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Register native inputs during expansion, before rustc writes dep-info. + +use serde::{Deserialize, Serialize}; +use std::collections::BTreeSet; +use std::io::{Read, Write}; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; + +const MAX_JSON: usize = 1024 * 1024; + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct Registration { + version: u32, + provider: String, + executable: PathBuf, + operation: String, + algorithm: String, +} + +#[derive(Serialize)] +struct InputRequest { + version: u32, + cuda_root: PathBuf, + target: String, +} + +#[derive(Deserialize)] +#[serde(deny_unknown_fields)] +struct InputResponse { + version: u32, + paths: Vec, + environment: Vec, +} + +fn environment(name: &str) -> Result, String> { + match proc_macro::tracked::env_var(name) { + Ok(value) => Ok(Some(value)), + Err(std::env::VarError::NotPresent) => Ok(None), + Err(error) => Err(format!("cannot read {name}: {error}")), + } +} + +fn registration(value: &str) -> Result { + if value.len() > MAX_JSON { + return Err("native library registration exceeds 1 MiB".into()); + } + let registration: Registration = serde_json::from_str(value) + .map_err(|error| format!("invalid native library registration: {error}"))?; + if registration.version != 1 + || registration.provider.is_empty() + || registration.operation.is_empty() + || registration.algorithm.is_empty() + || !registration.executable.is_absolute() + { + return Err("native library registration requires version 1, nonempty names and an absolute executable path".into()); + } + Ok(registration) +} + +fn response(bytes: &[u8]) -> Result { + if bytes.len() > MAX_JSON { + return Err("native library input response exceeds 1 MiB".into()); + } + let response: InputResponse = serde_json::from_slice(bytes) + .map_err(|error| format!("invalid native library input response: {error}"))?; + if response.version != 1 { + return Err("native library input response requires version 1".into()); + } + if response.paths.iter().any(|path| !path.is_absolute()) { + return Err("native library input paths must be absolute".into()); + } + if response + .environment + .iter() + .any(|name| name.is_empty() || name.as_bytes().iter().any(|byte| matches!(byte, b'=' | 0))) + { + return Err( + "native library input response has an invalid environment variable name".into(), + ); + } + Ok(response) +} + +fn query(executable: &Path, request: &InputRequest) -> Result { + let bytes = serde_json::to_vec(request).map_err(|error| error.to_string())?; + if bytes.len() > MAX_JSON { + return Err("native library input request exceeds 1 MiB".into()); + } + let mut child = Command::new(executable) + .arg("--oxide-library-inputs-v1") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .spawn() + .map_err(|error| { + format!( + "cannot query native library {}: {error}", + executable.display() + ) + })?; + let read = (|| { + child.stdin.take().unwrap().write_all(&bytes)?; + let mut output = Vec::new(); + child + .stdout + .take() + .unwrap() + .take((MAX_JSON + 1) as u64) + .read_to_end(&mut output)?; + Ok::<_, std::io::Error>(output) + })(); + let output = match read { + Ok(output) if output.len() <= MAX_JSON => output, + other => { + let _ = child.kill(); + let _ = child.wait(); + return Err(match other { + Err(error) => format!("native library input query failed: {error}"), + _ => "native library input response exceeds 1 MiB".into(), + }); + } + }; + let status = child.wait().map_err(|error| error.to_string())?; + if !status.success() { + return Err(format!("native library input query exited with {status}")); + } + response(&output) +} + +fn track_tree( + path: &Path, + directories: &mut BTreeSet, + track: &mut impl FnMut(&Path), +) -> Result<(), String> { + let metadata = path.metadata().map_err(|error| { + format!( + "cannot track native library input {}: {error}", + path.display() + ) + })?; + if !metadata.is_file() && !metadata.is_dir() { + return Err(format!( + "native library input is not a file or directory: {}", + path.display() + )); + } + track(path); + let canonical = path.canonicalize().map_err(|error| error.to_string())?; + if canonical != path { + track(&canonical); + } + if metadata.is_dir() && directories.insert(canonical) { + for entry in std::fs::read_dir(path).map_err(|error| error.to_string())? { + track_tree( + &entry.map_err(|error| error.to_string())?.path(), + directories, + track, + )?; + } + } + Ok(()) +} + +pub(crate) fn expand(variable: &syn::LitStr) -> Result { + crate::common::track_codegen_environment(); + let value = environment(&variable.value())?.ok_or_else(|| { + format!( + "native library registration variable {} is not set", + variable.value() + ) + })?; + let registration = registration(&value)?; + if !registration.executable.is_file() { + return Err(format!( + "native library provider is not a file: {}", + registration.executable.display() + )); + } + let mut directories = BTreeSet::new(); + let mut track = |path: &Path| proc_macro::tracked::path(path); + track_tree(®istration.executable, &mut directories, &mut track)?; + let cuda_home = environment("CUDA_HOME")?; + let cuda_path = environment("CUDA_PATH")?; + let target = environment("CUDA_OXIDE_TARGET")?; + if environment(reserved_oxide_symbols::MATERIALIZE_CUBIN_ENV)? + .is_some_and(|value| matches!(value.as_str(), "1" | "true")) + { + let cuda_root = cuda_home + .or(cuda_path) + .ok_or("native library inputs require CUDA_HOME or CUDA_PATH")?; + let cuda_root = std::path::absolute(cuda_root) + .map_err(|error| format!("cannot resolve CUDA toolkit path: {error}"))?; + let target = target.ok_or("native library inputs require CUDA_OXIDE_TARGET")?; + let target = target + .strip_prefix("sm_") + .map(|value| format!("compute_{value}")) + .unwrap_or(target); + let inputs = query( + ®istration.executable, + &InputRequest { + version: 1, + cuda_root, + target, + }, + )?; + for name in inputs.environment { + environment(&name)?; + } + for path in inputs.paths { + track_tree(&path, &mut directories, &mut track)?; + } + } + let literal = syn::LitStr::new(&value, variable.span()); + Ok(quote::quote!(#literal)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn input_response_rejects_invalid_contracts() { + for value in [ + r#"{"version":2,"paths":[],"environment":[]}"#, + r#"{"version":1,"paths":["relative"],"environment":[]}"#, + r#"{"version":1,"paths":[],"environment":["A=B"]}"#, + r#"{"version":1,"paths":[],"environment":[],"extra":1}"#, + r#"{"version":1,"paths":[],"environment":[]} trailing"#, + ] { + assert!(response(value.as_bytes()).is_err(), "{value}"); + } + assert!(response(&vec![b' '; MAX_JSON + 1]).is_err()); + assert!(response(br#"{"version":1,"paths":[],"environment":[]}"#).is_ok()); + } +} diff --git a/cuda-oxide/crates/cuda-macros/src/tests/cuda_module.rs b/cuda-oxide/crates/cuda-macros/src/tests/cuda_module.rs index be7a69ac79..cbc93b4d40 100644 --- a/cuda-oxide/crates/cuda-macros/src/tests/cuda_module.rs +++ b/cuda-oxide/crates/cuda-macros/src/tests/cuda_module.rs @@ -381,7 +381,7 @@ fn cfg_gated_generic_uses_the_same_gate_for_marker_and_loader() { "loader selection must inherit the generic kernel's cfg:\n{expanded}" ); assert!( - expanded.contains(&format!("if__cuda_oxide_has_enabled_generic_kernel{{let_=name;::cuda_host::load_all_ptx_bundles_merged(ctx)?}}else{{{ANCHORED_EMBEDDED_LOADER}}}")), + expanded.contains(&format!("if__cuda_oxide_has_enabled_generic_kernel{{let_=name;#[cfg(any(target_os=\"linux\",target_os=\"android\"))]{{static__CUDA_OXIDE_GENERIC_IMAGE:u8=0;::cuda_host::load_generic_embedded_module_from_anchor(ctx,&__CUDA_OXIDE_GENERIC_IMAGE,)?}}#[cfg(not(any(target_os=\"linux\",target_os=\"android\")))]{{::cuda_host::load_generic_embedded_module(ctx)?}}}}else{{{ANCHORED_EMBEDDED_LOADER}}}")), "loader must fall back to the embedded artifact when no generic kernel is enabled:\n{expanded}" ); } @@ -1493,3 +1493,18 @@ fn non_generic_kernel_lookups_never_consult_the_divergence_diagnosis() { "non-generic lookups must keep the ordinary error path: {expanded}" ); } + +#[test] +fn inferred_shared_contract_rejects_a_separate_alignment_promise() { + let module: ItemMod = parse_quote! { + mod kernels { + #[kernel] + #[launch_contract(domain = 1, block = (32, 1, 1), dynamic_shared = inferred, + dynamic_shared_alignment = 128)] + pub fn map() {} + } + }; + let error = + expand_cuda_module(module).expect_err("inferred alignment belongs to the compiler layout"); + assert!(error.to_string().contains("inferred")); +} diff --git a/cuda-oxide/crates/cuda-macros/src/tests/kernel.rs b/cuda-oxide/crates/cuda-macros/src/tests/kernel.rs index caaf588b90..3e13600e74 100644 --- a/cuda-oxide/crates/cuda-macros/src/tests/kernel.rs +++ b/cuda-oxide/crates/cuda-macros/src/tests/kernel.rs @@ -689,6 +689,7 @@ fn generic_kernel_forwards_only_exact_top_level_configuration_markers() { ::cuda_device::thread::__launch_contract_block_config::<64, 1, 1>(); ::cuda_device::cluster::__cluster_config::<2, 1, 1>(); ::cuda_device::shared::__dynamic_shared_alignment::<128>(); + ::cuda_device::shared::__dynamic_shared_inferred(); cuda_device::thread::__launch_bounds_config::<4, 1>(); unrelated(); other::cuda_device::thread::__launch_bounds_config::<32, 1>(); @@ -702,12 +703,13 @@ fn generic_kernel_forwards_only_exact_top_level_configuration_markers() { let markers = top_level_kernel_configuration_markers(&kernel); let forwarded = quote!(#(#markers)*).to_string().replace(' ', ""); - assert_eq!(markers.len(), 5); + assert_eq!(markers.len(), 6); assert!(forwarded.contains("__launch_bounds_config::<64,2>()")); assert!(forwarded.contains("__launch_contract_config::<1,true>()")); assert!(forwarded.contains("__launch_contract_block_config::<64,1,1>()")); assert!(forwarded.contains("__cluster_config::<2,1,1>()")); assert!(forwarded.contains("__dynamic_shared_alignment::<128>()")); + assert!(forwarded.contains("__dynamic_shared_inferred()")); assert!(!forwarded.contains("unrelated")); assert!(!forwarded.contains("::<4,1>()")); assert!(!forwarded.contains("other::cuda_device")); diff --git a/cuda-oxide/crates/cuda-macros/tests/device-only/Cargo.lock b/cuda-oxide/crates/cuda-macros/tests/device-only/Cargo.lock index 4a78f429b9..6b95509d84 100644 --- a/cuda-oxide/crates/cuda-macros/tests/device-only/Cargo.lock +++ b/cuda-oxide/crates/cuda-macros/tests/device-only/Cargo.lock @@ -17,6 +17,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn 2.0.119", ] diff --git a/cuda-oxide/crates/cuda-macros/tests/library_registration.rs b/cuda-oxide/crates/cuda-macros/tests/library_registration.rs new file mode 100644 index 0000000000..4388dc66cb --- /dev/null +++ b/cuda-oxide/crates/cuda-macros/tests/library_registration.rs @@ -0,0 +1,157 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Ordinary Cargo freshness across a dependency registration and its consumer. +//! The fake provider is a shell process; no CUDA toolkit or GPU is used. +#![cfg(unix)] + +use std::fs; +use std::os::unix::fs::PermissionsExt; +use std::path::{Path, PathBuf}; +use std::process::Command; + +fn build(root: &Path, materialize: bool, option: Option<&str>, expected: Option<&str>) -> String { + let mut command = Command::new(env!("CARGO")); + command + .args(["build", "-vv", "--offline"]) + .current_dir(root) + .env("CARGO_TARGET_DIR", root.join("target")) + .env("CUDA_HOME", root.join("toolkit")) + .env("CUDA_OXIDE_TARGET", "sm_120") + .env_remove("CARGO_ENCODED_RUSTFLAGS") + .env_remove("RUSTFLAGS"); + if let Some(option) = option { + command.env("NATIVE_INPUT_OPTION", option); + } else { + command.env_remove("NATIVE_INPUT_OPTION"); + } + if materialize { + command.env("CUDA_OXIDE_MATERIALIZE_CUBIN", "1"); + } else { + command.env_remove("CUDA_OXIDE_MATERIALIZE_CUBIN"); + } + let output = command.output().unwrap(); + let log = String::from_utf8_lossy(&output.stderr).into_owned(); + if let Some(error) = expected { + assert!(!output.status.success(), "{log}"); + assert!(log.contains(error), "{log}"); + } else { + assert!(output.status.success(), "{log}"); + } + log +} + +fn provider(root: &Path, response: &str) { + fs::write( + root.join("provider"), + format!("#!/bin/sh\ncat >/dev/null\nprintf '%s' '{response}'\n"), + ) + .unwrap(); + fs::set_permissions(root.join("provider"), fs::Permissions::from_mode(0o755)).unwrap(); +} + +#[test] +fn tracks_native_inputs_before_cargo_dep_info() { + let root = std::env::temp_dir().join(format!( + "oxide-library-inputs-{}-{}", + std::process::id(), + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_nanos() + )); + let device = PathBuf::from(env!("CARGO_MANIFEST_DIR")) + .join("../cuda-device") + .canonicalize() + .unwrap(); + fs::create_dir_all(root.join("api/src")).unwrap(); + fs::create_dir_all(root.join("consumer/src")).unwrap(); + fs::create_dir_all(root.join("headers")).unwrap(); + fs::write(root.join("headers/value.h"), "initial").unwrap(); + fs::write( + root.join("Cargo.toml"), + "[workspace]\nmembers=['api','consumer']\ndefault-members=['consumer']\nresolver='3'\n", + ) + .unwrap(); + fs::write(root.join("api/Cargo.toml"), format!( + "[package]\nname='native-input-api'\nversion='0.0.0'\nedition='2024'\n[dependencies]\ncuda-device={{path={:?}}}\n", device.to_str().unwrap() + )).unwrap(); + fs::write(root.join("consumer/Cargo.toml"), + "[package]\nname='native-input-consumer'\nversion='0.0.0'\nedition='2024'\n[dependencies]\nnative-input-api={path='../api'}\n").unwrap(); + let registration = serde_json::json!({ + "version":1,"provider":"fixture","executable":root.join("provider"), + "operation":"test","algorithm":"direct" + }) + .to_string(); + fs::write(root.join("api/build.rs"), format!( + "fn main() {{ println!(\"cargo::rerun-if-changed=build.rs\"); println!(\"cargo::rustc-env=REG={{}}\", {registration:?}); }}" + )).unwrap(); + fs::write( + root.join("api/src/lib.rs"), + "pub fn registration() -> &'static str { cuda_device::library::registration!(\"REG\") }\n", + ) + .unwrap(); + fs::write( + root.join("consumer/src/main.rs"), + "fn main() { assert!(native_input_api::registration().contains(\"fixture\")); }\n", + ) + .unwrap(); + let response = serde_json::json!({ + "version":1,"paths":[root.join("headers")],"environment":["NATIVE_INPUT_OPTION"] + }) + .to_string(); + provider(&root, &response); + build(&root, true, None, None); + let warm = build(&root, true, None, None); + assert!(warm.contains("Fresh native-input-api"), "{warm}"); + assert!(warm.contains("Fresh native-input-consumer"), "{warm}"); + + fs::write(root.join("headers/value.h"), "changed").unwrap(); + let changed = build(&root, true, None, None); + assert!(changed.contains("Compiling native-input-api"), "{changed}"); + assert!( + changed.contains("Compiling native-input-consumer"), + "{changed}" + ); + fs::write(root.join("headers/new.h"), "added").unwrap(); + let added = build(&root, true, None, None); + assert!(added.contains("Compiling native-input-api"), "{added}"); + + let option = build(&root, true, Some("changed"), None); + assert!(option.contains("Compiling native-input-api"), "{option}"); + assert!( + option.contains("Compiling native-input-consumer"), + "{option}" + ); + let warm = build(&root, true, Some("changed"), None); + assert!(warm.contains("Fresh native-input-api"), "{warm}"); + + provider(&root, r#"{"version":2,"paths":[],"environment":[]}"#); + build( + &root, + true, + Some("changed"), + Some("input response requires version 1"), + ); + provider( + &root, + r#"{"version":1,"paths":["relative"],"environment":[]}"#, + ); + build( + &root, + true, + Some("changed"), + Some("input paths must be absolute"), + ); + provider(&root, "malformed"); + build( + &root, + true, + Some("changed"), + Some("invalid native library input response"), + ); + // A normal host build expands the registration without querying CUDA or + // attempting to consume the deliberately invalid native response. + build(&root, false, None, None); + fs::remove_dir_all(root).unwrap(); +} diff --git a/cuda-oxide/crates/cuda-oxide-codegen/src/export.rs b/cuda-oxide/crates/cuda-oxide-codegen/src/export.rs index 12fe5ecda2..fc1b5521db 100644 --- a/cuda-oxide/crates/cuda-oxide-codegen/src/export.rs +++ b/cuda-oxide/crates/cuda-oxide-codegen/src/export.rs @@ -44,25 +44,19 @@ pub struct DeviceExternDecl { /// NVVM attributes for device extern declarations. /// -/// NOTE: These attributes are currently **not emitted** to the LLVM IR output. -/// When linking LTOIR via nvJitLink, the external library's LTOIR already contains -/// proper attributes (convergent, nounwind, memory, etc.) on the function DEFINITIONS. -/// nvJitLink uses the definition's attributes during LTO, making attributes on our -/// declarations redundant. -/// -/// This struct is retained for the pipeline API but values are not used in code generation. +/// Convergence is emitted on each marked declaration before libNVVM optimization. +/// Memory-effect annotations remain inactive. #[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] pub struct DeviceExternAttrs { - /// Function is convergent (all threads must execute together). - /// NOTE: Not currently emitted to LLVM IR. + /// Function has convergence requirements for its participating threads. pub is_convergent: bool, /// Function is pure (no side effects, result depends only on inputs). - /// NOTE: Not currently emitted to LLVM IR. + /// Inactive; not emitted to LLVM IR. pub is_pure: bool, /// Function is read-only (only reads memory, doesn't write). - /// NOTE: Not currently emitted to LLVM IR. + /// Inactive; not emitted to LLVM IR. pub is_readonly: bool, } diff --git a/cuda-oxide/crates/cuda-oxide-codegen/src/lower.rs b/cuda-oxide/crates/cuda-oxide-codegen/src/lower.rs index 05011e5e58..d08f68f8d5 100644 --- a/cuda-oxide/crates/cuda-oxide-codegen/src/lower.rs +++ b/cuda-oxide/crates/cuda-oxide-codegen/src/lower.rs @@ -84,7 +84,7 @@ pub fn add_device_extern_declarations( region.iter(ctx).next().expect("Module should have a block") }; - let declared_symbols: HashMap<_, _> = block + let mut declared_symbols: HashMap<_, _> = block .deref(ctx) .iter(ctx) .filter_map(|op| { @@ -140,6 +140,7 @@ pub fn add_device_extern_declarations( // Insert at the front of the module (declarations come before definitions) func_op.get_operation().insert_at_front(block, ctx); + declared_symbols.insert(decl.export_name.clone(), func_type); } Ok(()) @@ -196,3 +197,62 @@ fn device_extern_type_to_pliron( } }) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::export::DeviceExternAttrs; + use llvm_export::export::{NvvmExportConfig, export_module_with_externs}; + use pliron::builtin::ops::ModuleOp; + use pliron::common_traits::Verify; + + #[test] + fn repeated_externs_keep_one_operation_and_preserve_conflict_checks() { + let mut ctx = Context::new(); + let module = ModuleOp::new(&mut ctx, "externs".try_into().unwrap()); + let declaration = DeviceExternDecl { + export_name: "external".to_string(), + param_types: vec![DeviceExternType::Integer(32)], + return_type: DeviceExternType::Void, + attrs: DeviceExternAttrs::default(), + }; + let mut externs = [declaration.clone(), declaration]; + add_device_extern_declarations(&mut ctx, module.get_operation(), &externs).unwrap(); + let declarations = { + let region = module.get_operation().deref(&ctx).get_region(0).deref(&ctx); + let block = region.iter(&ctx).next().unwrap(); + block + .deref(&ctx) + .iter(&ctx) + .filter(|&op| { + Operation::get_op::(op, &ctx).is_some_and( + |function| function.get_symbol_name(&ctx).to_string() == "external", + ) + }) + .count() + }; + assert_eq!(declarations, 1); + module.get_operation().deref(&ctx).verify(&ctx).unwrap(); + let ir = export_module_with_externs(&ctx, &module, &externs, &NvvmExportConfig::default()) + .unwrap(); + assert_eq!(ir.matches("declare void @external(i32)").count(), 1); + + // Lowering shares only the FuncOp. The complete declarations still + // reach export, where differing convergence requirements are rejected. + externs[1].attrs.is_convergent = true; + add_device_extern_declarations(&mut ctx, module.get_operation(), &externs).unwrap(); + let error = + export_module_with_externs(&ctx, &module, &externs, &NvvmExportConfig::default()) + .unwrap_err(); + assert!(error.contains("convergent is false versus true"), "{error}"); + + externs[1].param_types[0] = DeviceExternType::Float32; + let error = + add_device_extern_declarations(&mut ctx, module.get_operation(), &externs).unwrap_err(); + assert!( + error + .to_string() + .contains("conflicts with the call-site declaration") + ); + } +} diff --git a/cuda-oxide/crates/llvm-export/src/export/debug.rs b/cuda-oxide/crates/llvm-export/src/export/debug.rs index ca0bfcfc31..4feb86212a 100644 --- a/cuda-oxide/crates/llvm-export/src/export/debug.rs +++ b/cuda-oxide/crates/llvm-export/src/export/debug.rs @@ -177,9 +177,12 @@ impl<'a> ModuleExportState<'a> { "!{dwarf_version_id} = !{{i32 2, !\"Dwarf Version\", i32 2}}" ) .unwrap(); + // NVVM requires Error (1), including when linking native CUDA LTO-IR. + // Ordinary LLVM debug metadata keeps its Warning (2) merge behavior. + let debug_version_behavior = if self.nvvm_ir_dialect.is_some() { 1 } else { 2 }; writeln!( output, - "!{debug_info_version_id} = !{{i32 2, !\"Debug Info Version\", i32 3}}" + "!{debug_info_version_id} = !{{i32 {debug_version_behavior}, !\"Debug Info Version\", i32 3}}" ) .unwrap(); diff --git a/cuda-oxide/crates/llvm-export/src/export/externs.rs b/cuda-oxide/crates/llvm-export/src/export/externs.rs index ceeab494f0..2cea5a5fc0 100644 --- a/cuda-oxide/crates/llvm-export/src/export/externs.rs +++ b/cuda-oxide/crates/llvm-export/src/export/externs.rs @@ -225,22 +225,18 @@ pub struct DeviceExternDecl { /// NVVM attributes for device extern declarations. /// -/// NOTE: These attributes are currently **not emitted** to the LLVM IR output. -/// When linking LTOIR via nvJitLink, the external library's LTOIR already contains -/// proper attributes (convergent, nounwind, memory, etc.) on the function DEFINITIONS. -/// nvJitLink uses the definition's attributes during LTO, making attributes on -/// declarations redundant. -/// -/// This struct is retained for potential future use or for debugging/inspection. +/// Convergence is emitted on the declaration before libNVVM optimization. +/// Memory-effect annotations remain inactive; they are not inferred from external +/// definitions that become available only during LTO. #[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] pub struct DeviceExternAttrs { - /// Function is convergent (all threads must execute together). + /// Function has convergence requirements for its participating threads. pub is_convergent: bool, - /// Function is pure (no side effects). Maps to LLVM `readnone`. + /// Function is pure (no side effects). Inactive for Rust source annotations. pub is_pure: bool, - /// Function is read-only (only reads memory). Maps to LLVM `readonly`. + /// Function is read-only (only reads memory). Inactive for Rust source annotations. pub is_readonly: bool, } diff --git a/cuda-oxide/crates/llvm-export/src/export/module.rs b/cuda-oxide/crates/llvm-export/src/export/module.rs index 1a9e934851..9d425d54c4 100644 --- a/cuda-oxide/crates/llvm-export/src/export/module.rs +++ b/cuda-oxide/crates/llvm-export/src/export/module.rs @@ -487,10 +487,17 @@ fn index_device_externs( validate_device_extern_function_shape(state, decl)?; if let Some(previous) = state.device_externs.get(&decl.export_name) { if previous != decl { - return Err(format!( + let conflict = format!( "conflicting device-extern declarations for `@{}`", decl.export_name - )); + ); + if previous.attrs.is_convergent != decl.attrs.is_convergent { + return Err(format!( + "{conflict}: convergent is {} versus {}", + previous.attrs.is_convergent, decl.attrs.is_convergent + )); + } + return Err(conflict); } continue; } @@ -610,12 +617,9 @@ pub(super) fn export_module_with_externs_impl( // 2. Device extern declarations (before function definitions) // - // NOTE: We intentionally do NOT emit LLVM attributes on these declarations. - // The external LTOIR (from nvcc -dc -dlto) already contains proper attributes - // (convergent, nounwind, memory, etc.) on the function DEFINITIONS. - // When nvJitLink performs LTO linking, it uses the definition's attributes. - // Attributes on declarations are redundant and were causing issues where - // all externs incorrectly got the same attribute group. + // Convergence must be visible before libNVVM optimizes this module, not + // only when external definitions arrive at LTO. Emit it per declaration + // so unrelated externs do not inherit a shared attribute group. if !device_externs.is_empty() { writeln!( &mut output, @@ -643,7 +647,11 @@ pub(super) fn export_module_with_externs_impl( } param.write_llvm_with_attr(&mut output, state.legacy_typed_pointers())?; } - writeln!(&mut output, ")").unwrap(); + write!(&mut output, ")").unwrap(); + if decl.attrs.is_convergent { + write!(&mut output, " convergent").unwrap(); + } + writeln!(&mut output).unwrap(); } writeln!(&mut output).unwrap(); } @@ -711,7 +719,7 @@ pub(super) fn export_module_with_externs_impl( } // 6. Emit attribute groups for convergent intrinsics used by module functions - // Note: Device extern declarations no longer get attribute groups - see section 2 comment. + // Device extern convergence is emitted inline, independently of this group. if state.convergent_used { writeln!(&mut output).unwrap(); writeln!(&mut output, "attributes #0 = {{ convergent }}").unwrap(); diff --git a/cuda-oxide/crates/llvm-export/tests/export_test/debug_info.rs b/cuda-oxide/crates/llvm-export/tests/export_test/debug_info.rs index abc11b7af6..bbb601856c 100644 --- a/cuda-oxide/crates/llvm-export/tests/export_test/debug_info.rs +++ b/cuda-oxide/crates/llvm-export/tests/export_test/debug_info.rs @@ -90,6 +90,20 @@ fn line_table_debug_metadata_emits_function_scope_and_instruction_locations() { let ir = export_module_to_string_with_config(&ctx, &module, &config).expect("debug export succeeds"); + assert!(ir.contains("!{i32 2, !\"Debug Info Version\", i32 3}")); + for debug_kind in [DebugKind::LineTables, DebugKind::Full] { + let nvvm_config = DebugConfig { + inner: NvvmExportConfig::new(NvvmIrDialect::Modern), + debug_kind, + }; + let nvvm_ir = export_module_to_string_with_config(&ctx, &module, &nvvm_config) + .expect("NVVM debug export succeeds"); + assert!( + nvvm_ir.contains("!{i32 1, !\"Debug Info Version\", i32 3}"), + "NVVM requires Error merge behavior for native LTO linkage:\n{nvvm_ir}" + ); + } + let define_line = ir .lines() .find(|line| line.starts_with("define ")) diff --git a/cuda-oxide/crates/llvm-export/tests/export_test/device_externs.rs b/cuda-oxide/crates/llvm-export/tests/export_test/device_externs.rs index ee928c3819..f68a227611 100644 --- a/cuda-oxide/crates/llvm-export/tests/export_test/device_externs.rs +++ b/cuda-oxide/crates/llvm-export/tests/export_test/device_externs.rs @@ -23,6 +23,113 @@ use pliron::{ use crate::common::module_top_block; +fn mixed_convergence_module(ctx: &mut Context) -> (ModuleOp, Vec) { + let module = ModuleOp::new(ctx, "mixed_convergence".try_into().unwrap()); + let module_block = module_top_block(ctx, &module); + let ptr_ty = PointerType::get(ctx, 0); + let void_ty = VoidType::get(ctx); + let external_ty = FuncType::get(ctx, void_ty.into(), vec![ptr_ty.into()], false); + let caller = FuncOp::new(ctx, "caller".try_into().unwrap(), external_ty); + let entry = caller.get_or_create_entry_block(ctx); + let pointer = entry.deref(ctx).get_argument(0); + let mut externs = Vec::new(); + for (name, is_convergent) in [("collective", true), ("ordinary", false)] { + FuncOp::new(ctx, name.try_into().unwrap(), external_ty) + .get_operation() + .insert_at_back(module_block, ctx); + CallOp::new( + ctx, + CallOpCallable::Direct(name.try_into().unwrap()), + external_ty, + vec![pointer], + ) + .get_operation() + .insert_at_back(entry, ctx); + externs.push(DeviceExternDecl { + export_name: name.to_string(), + param_types: vec![DeviceExternType::pointer_to( + DeviceExternType::Integer(32), + 0, + )], + return_type: DeviceExternType::Void, + attrs: DeviceExternAttrs { + is_convergent, + ..DeviceExternAttrs::default() + }, + }); + } + ReturnOp::new(ctx, None) + .get_operation() + .insert_at_back(entry, ctx); + caller.get_operation().insert_at_back(module_block, ctx); + (module, externs) +} + +#[test] +fn device_extern_convergence_is_per_declaration_in_both_dialects() { + let mut ctx = Context::new(); + let (module, mut externs) = mixed_convergence_module(&mut ctx); + // Repeated identical declarations are still emitted exactly once. + externs.push(externs[0].clone()); + for (dialect, pointer) in [ + (NvvmIrDialect::Modern, "ptr"), + (NvvmIrDialect::LegacyLlvm7, "i32*"), + ] { + let ir = + export_module_with_externs(&ctx, &module, &externs, &NvvmExportConfig::new(dialect)) + .unwrap(); + let declarations: Vec<_> = ir + .lines() + .filter(|line| line.starts_with("declare ")) + .collect(); + assert_eq!( + declarations, + [ + format!("declare void @collective({pointer}) convergent"), + format!("declare void @ordinary({pointer})"), + ], + "{ir}" + ); + assert!( + ir.lines().any(|line| { + line.contains(&format!("call void @collective({pointer} ")) && line.ends_with(" #0") + }), + "{ir}" + ); + if dialect == NvvmIrDialect::LegacyLlvm7 { + assert!(ir.contains("bitcast i8* %v0 to i32*"), "{ir}"); + } + } + + externs[2].attrs.is_convergent = false; + let error = export_module_with_externs(&ctx, &module, &externs, &NvvmExportConfig::default()) + .expect_err("conflicting convergence requirements must fail"); + assert!( + error.contains("conflicting device-extern declarations for `@collective`: convergent is true versus false"), + "{error}" + ); +} + +#[test] +#[ignore = "requires an installed CUDA Toolkit with modern and legacy libNVVM"] +fn device_extern_convergence_compiles_with_libnvvm_in_both_dialects() { + let nvvm = libnvvm_sys::LibNvvm::load().expect("CUDA Toolkit with libNVVM required"); + let mut ctx = Context::new(); + let (module, externs) = mixed_convergence_module(&mut ctx); + for (dialect, arch) in [ + (NvvmIrDialect::Modern, "-arch=compute_120"), + (NvvmIrDialect::LegacyLlvm7, "-arch=compute_80"), + ] { + let ir = + export_module_with_externs(&ctx, &module, &externs, &NvvmExportConfig::new(dialect)) + .unwrap(); + let mut program = libnvvm_sys::Program::new(&nvvm).unwrap(); + program.add_module(ir.as_bytes(), "convergence.ll").unwrap(); + let lto = program.compile(&[arch, "-gen-lto"]).unwrap(); + assert!(!lto.is_empty()); + } +} + #[test] fn legacy_device_extern_adapts_exact_pointer_arguments_and_results() { let mut ctx = Context::new(); diff --git a/cuda-oxide/crates/mir-importer/src/kernel_resources.rs b/cuda-oxide/crates/mir-importer/src/kernel_resources.rs new file mode 100644 index 0000000000..5a0c049772 --- /dev/null +++ b/cuda-oxide/crates/mir-importer/src/kernel_resources.rs @@ -0,0 +1,185 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! Finalized requirements for fixed views of the dynamic shared-memory base. +//! This is not an allocator: fixed views alias and combine by maximum extent. + +use dialect_mir::ops::{MirCallOp, MirExternSharedOp, MirFuncOp}; +use oxide_artifacts::KernelLaunchFacts; +use pliron::builtin::{attributes::IntegerAttr, op_interfaces::SymbolOpInterface}; +use pliron::context::{Context, Ptr}; +use pliron::linked_list::ContainsLinkedList; +use pliron::operation::Operation; +use std::collections::{BTreeMap, BTreeSet}; + +pub(crate) const FIXED_SHARED_BYTES: &str = "cuda_oxide_fixed_shared_bytes"; +pub(crate) const INFERRED_SHARED: &str = "cuda_oxide_inferred_shared"; + +fn integer_attr(ctx: &Context, op: Ptr, name: &str) -> Option { + let key: pliron::identifier::Identifier = name.try_into().unwrap(); + op.deref(ctx) + .attributes + .get::(&key) + .map(|value| value.value().to_u64()) +} + +/// Apply the exact geometry required by reachable native library operations. +/// Scratch extents are recorded on their actual shared-memory accesses and +/// collected together with ordinary Rust views below. +pub(crate) fn apply_library_block( + ctx: &mut Context, + entry: Ptr, + plan: &KernelLaunchFacts, +) -> Result<(), String> { + use pliron::builtin::types::{IntegerType, Signedness}; + use pliron::utils::apint::APInt; + + let Some((x, y, z)) = plan.exact_block else { + return Err("native library root is missing its exact block shape".into()); + }; + let required = u64::from(x) * u64::from(y) * u64::from(z); + if let Some(maximum) = integer_attr(ctx, entry, "maxntid") + && required > maximum + { + return Err(format!( + "native library exact block ({x}, {y}, {z}) exceeds launch_bounds maximum {maximum}" + )); + } + let axes = [("reqntid_x", x), ("reqntid_y", y), ("reqntid_z", z)]; + for (name, dimension) in axes { + if let Some(existing) = integer_attr(ctx, entry, name) + && existing != u64::from(dimension) + { + return Err(format!( + "native library exact block ({x}, {y}, {z}) conflicts with kernel launch contract" + )); + } + } + let ty = IntegerType::get(ctx, 64, Signedness::Unsigned); + for (name, dimension) in axes { + entry.deref_mut(ctx).attributes.set( + name.try_into().unwrap(), + IntegerAttr::new( + ty, + APInt::from_u64( + u64::from(dimension), + std::num::NonZeroUsize::new(64).unwrap(), + ), + ), + ); + } + Ok(()) +} + +#[derive(Default)] +struct FunctionResources { + inferred: bool, + fixed: bool, + unconstrained: bool, + bytes: u64, + alignment: u64, + callees: Vec, +} + +fn scan(ctx: &Context, op: Ptr, resources: &mut FunctionResources) { + if let Some(shared) = Operation::get_op::(op, ctx) { + match integer_attr(ctx, op, FIXED_SHARED_BYTES) { + Some(bytes) => { + resources.fixed = true; + resources.bytes = resources.bytes.max(bytes); + resources.alignment = resources.alignment.max(shared.get_alignment_value(ctx)); + } + None => resources.unconstrained = true, + } + } + if let Some(call) = Operation::get_op::(op, ctx) + && let Some(callee) = call.get_attr_callee(ctx) + { + resources.callees.push(String::from((*callee).clone())); + } + for region in op.deref(ctx).regions() { + for block in region.deref(ctx).iter(ctx) { + for child in block.deref(ctx).iter(ctx) { + scan(ctx, child, resources); + } + } + } +} + +pub(crate) fn collect( + ctx: &Context, + module: Ptr, + kernels: impl IntoIterator, +) -> Result, String> { + let mut functions = BTreeMap::new(); + for region in module.deref(ctx).regions() { + for block in region.deref(ctx).iter(ctx) { + for op in block.deref(ctx).iter(ctx) { + if let Some(function) = MirFuncOp::wrap(ctx, op) { + let mut resources = FunctionResources { + inferred: integer_attr(ctx, op, INFERRED_SHARED).is_some(), + alignment: integer_attr(ctx, op, "dynamic_shared_alignment").unwrap_or(1), + ..Default::default() + }; + scan(ctx, op, &mut resources); + functions.insert(function.get_symbol_name(ctx).to_string(), (op, resources)); + } + } + } + } + let mut facts = BTreeMap::new(); + for kernel in kernels { + let Some((entry, _)) = functions.get(&kernel) else { + continue; + }; + let mut visited = BTreeSet::new(); + let mut pending = vec![kernel.clone()]; + let mut combined = FunctionResources { + alignment: 1, + ..Default::default() + }; + while let Some(name) = pending.pop() { + if !visited.insert(name.clone()) { + continue; + } + let Some((_, local)) = functions.get(&name) else { + continue; + }; + combined.inferred |= local.inferred; + combined.fixed |= local.fixed; + combined.unconstrained |= local.unconstrained; + combined.bytes = combined.bytes.max(local.bytes); + combined.alignment = combined.alignment.max(local.alignment); + pending.extend(local.callees.iter().cloned()); + } + if combined.inferred && combined.unconstrained { + return Err(format!( + "{kernel}: inferred dynamic shared memory cannot include unconstrained get/get_raw/offset accesses; describe the complete base region with DynamicSharedArray::get_fixed or declare an explicit launch contract" + )); + } + if combined.unconstrained || !(combined.inferred || combined.fixed) { + continue; + } + let narrow = |value| { + u32::try_from(value) + .map_err(|_| format!("{kernel}: compiled shared-memory layout exceeds u32")) + }; + let exact_block = match ( + integer_attr(ctx, *entry, "reqntid_x"), + integer_attr(ctx, *entry, "reqntid_y"), + integer_attr(ctx, *entry, "reqntid_z"), + ) { + (Some(x), Some(y), Some(z)) => Some((narrow(x)?, narrow(y)?, narrow(z)?)), + _ => None, + }; + let layout = KernelLaunchFacts { + exact_block, + dynamic_shared_bytes: narrow(combined.bytes)?, + dynamic_shared_alignment: narrow(combined.alignment)?, + }; + facts.insert(kernel, layout); + } + Ok(facts) +} diff --git a/cuda-oxide/crates/mir-importer/src/lib.rs b/cuda-oxide/crates/mir-importer/src/lib.rs index 2909011287..ec5b3cad9d 100644 --- a/cuda-oxide/crates/mir-importer/src/lib.rs +++ b/cuda-oxide/crates/mir-importer/src/lib.rs @@ -94,6 +94,7 @@ extern crate rustc_span; pub const DEVICE_RUNTIME_CHECKS_VALUE: bool = false; pub mod error; +mod kernel_resources; pub mod pipeline; // Crate-internal: every caller reaches the translator through `pipeline`, and // the handful of predicates outsiders need are re-exported below. Keeping the @@ -112,3 +113,7 @@ pub use pipeline::{ pub use translator::facts::KnownDefs; pub use translator::terminator::drop_glue::{drop_glue_is_noop, drop_instance_is_noop}; pub use translator::terminator::is_panic_entry_path; + +mod library; +pub use library::LibraryCallPlan; +pub use pipeline::run_pipeline_with_libraries; diff --git a/cuda-oxide/crates/mir-importer/src/library.rs b/cuda-oxide/crates/mir-importer/src/library.rs new file mode 100644 index 0000000000..e9c7a3362a --- /dev/null +++ b/cuda-oxide/crates/mir-importer/src/library.rs @@ -0,0 +1,182 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Lower compiler-validated library calls at an explicit scalar/pointer ABI. + +use std::cell::RefCell; +use std::collections::BTreeMap; + +use crate::error::{TranslationErr, TranslationResult}; +use crate::translator::terminator::helpers; +use crate::translator::values::{ValueMap, establish_declared_pointer_type}; +use crate::translator::{facts, rvalue, types}; +use dialect_mir::attributes::{FieldIndexAttr, MirPointerKindAuthorityAttr}; +use dialect_mir::ops::{MirExternSharedOp, MirExtractFieldOp}; +use dialect_mir::types::{MirPtrType, MirTupleType}; +use pliron::basic_block::BasicBlock; +use pliron::builtin::attributes::IntegerAttr; +use pliron::builtin::types::{FunctionType, IntegerType, Signedness}; +use pliron::context::{Context, Ptr}; +use pliron::input_err; +use pliron::location::Location; +use pliron::op::Op; +use pliron::operation::Operation; +use pliron::r#type::Typed; +use pliron::utils::apint::APInt; +use rustc_public::mir; + +/// One monomorphized call whose Rust tuple and provider ABI already agree. +#[derive(Clone, Debug)] +pub struct LibraryCallPlan { + /// Exact external symbol emitted by the native provider. + pub symbol: String, + /// Size of the assigned shared scratch view in bytes. + pub scratch_bytes: u32, + /// Required alignment of the shared scratch base. + pub scratch_alignment: u32, +} + +thread_local! { + static CALLS: RefCell> = const { RefCell::new(BTreeMap::new()) }; +} + +pub(crate) fn set_calls(calls: BTreeMap) { + CALLS.with(|current| *current.borrow_mut() = calls); +} + +pub(crate) fn get_call(instance: &str) -> Option { + CALLS.with(|calls| calls.borrow().get(instance).cloned()) +} + +#[allow(clippy::too_many_arguments)] +pub(crate) fn translate_call( + ctx: &mut Context, + body: &mir::Body, + plan: &LibraryCallPlan, + args: &[mir::Operand], + destination: &mir::Place, + target: &Option, + block: Ptr, + previous: Option>, + values: &mut ValueMap, + blocks: &[Ptr], + loc: Location, +) -> TranslationResult> { + let [_, tuple] = args else { + return input_err!( + loc, + TranslationErr::unsupported( + "library marker requires a registration and argument tuple" + ) + ); + }; + let tuple_ty = match tuple.ty(body.locals()) { + Ok(ty) => ty, + Err(e) => { + return input_err!( + loc, + TranslationErr::unsupported(format!("invalid library argument tuple: {e:?}")) + ); + } + }; + let rustc_public::ty::TyKind::RigidTy(rustc_public::ty::RigidTy::Tuple(fields)) = + tuple_ty.kind() + else { + return input_err!( + loc, + TranslationErr::unsupported("library arguments must be a tuple") + ); + }; + let mut declared = fields + .iter() + .map(|ty| types::translate_type(ctx, ty)) + .collect::>>()?; + let (tuple_value, mut last) = + rvalue::translate_operand(ctx, body, tuple, values, block, previous, loc.clone())?; + let tuple_handle = tuple_value.get_type(ctx); + let field_types = tuple_handle + .deref(ctx) + .downcast_ref::() + .expect("validated library tuple") + .get_types() + .to_vec(); + let mut arguments = Vec::new(); + for (index, ty) in field_types.into_iter().enumerate() { + let op = Operation::new( + ctx, + MirExtractFieldOp::get_concrete_op_info(), + vec![ty], + vec![tuple_value], + vec![], + 0, + ); + op.deref_mut(ctx).set_loc(loc.clone()); + MirExtractFieldOp::new(op).set_attr_index(ctx, FieldIndexAttr(index as u32)); + helpers::insert_op(ctx, op, block, last); + last = Some(op); + arguments.push(op.deref(ctx).get_result(0)); + } + // The unsafe marker grants a raw scratch address. Keep the internal shared + // pointer through construction, then adapt only its address space at the + // declared generic-pointer ABI boundary, using the ordinary foreign-call path. + let byte = IntegerType::get(ctx, 8, Signedness::Unsigned).into(); + let shared = MirPtrType::get_shared(ctx, byte, true).into(); + let op = Operation::new( + ctx, + MirExternSharedOp::get_concrete_op_info(), + vec![shared], + vec![], + vec![], + 0, + ); + op.deref_mut(ctx).set_loc(loc.clone()); + let scratch = MirExternSharedOp::new(op); + scratch.set_byte_offset_value(ctx, 0); + scratch.set_alignment_value(ctx, u64::from(plan.scratch_alignment)); + let layout_ty = IntegerType::get(ctx, 64, Signedness::Unsigned); + op.deref_mut(ctx).attributes.set( + crate::kernel_resources::FIXED_SHARED_BYTES + .try_into() + .unwrap(), + IntegerAttr::new( + layout_ty, + APInt::from_u64( + u64::from(plan.scratch_bytes), + std::num::NonZeroUsize::new(64).unwrap(), + ), + ), + ); + helpers::insert_op(ctx, op, block, last); + let internal_scratch = op.deref(ctx).get_result(0); + let raw_shared = facts::mint_shared_ptr_type(ctx, byte, facts::abi_library_scratch()).into(); + let (scratch_value, last) = establish_declared_pointer_type( + ctx, + internal_scratch, + raw_shared, + block, + Some(op), + MirPointerKindAuthorityAttr::RawAddress, + ); + arguments.insert(2, scratch_value); + declared.insert( + 2, + facts::mint_generic_ptr_type(ctx, byte, facts::abi_library_scratch()).into(), + ); + let signature = FunctionType::get(ctx, declared, vec![]).into(); + let unit = MirTupleType::get(ctx, vec![]).into(); + helpers::emit_function_call_values( + ctx, + body, + &plan.symbol, + arguments, + destination, + unit, + Some(signature), + target, + block, + last, + values, + blocks, + loc, + ) +} diff --git a/cuda-oxide/crates/mir-importer/src/pipeline.rs b/cuda-oxide/crates/mir-importer/src/pipeline.rs index 12d74984ef..93fe3b11e3 100644 --- a/cuda-oxide/crates/mir-importer/src/pipeline.rs +++ b/cuda-oxide/crates/mir-importer/src/pipeline.rs @@ -181,6 +181,8 @@ pub struct CompilationResult { pub allow_fma_contraction: bool, /// Per-kernel source launch bounds preserved for post-link diagnostics. pub kernel_launch_bounds: BTreeMap, + /// Finalized resource requirements, keyed by concrete exported kernel name. + pub kernel_launch_facts: BTreeMap, } /// Configuration for the compilation pipeline. @@ -492,6 +494,27 @@ pub fn run_pipeline( config: &PipelineConfig, known_defs: crate::translator::facts::KnownDefs, ) -> Result { + run_pipeline_with_libraries( + functions, + device_externs, + config, + known_defs, + BTreeMap::new(), + &BTreeMap::new(), + ) +} + +/// Run the pipeline with compiler-validated, monomorphized library calls. +/// The map keys are resolved instance mangled names, not source spellings. +pub fn run_pipeline_with_libraries( + functions: &[CollectedFunction], + device_externs: &[DeviceExternDecl], + config: &PipelineConfig, + known_defs: crate::translator::facts::KnownDefs, + libraries: BTreeMap, + library_roots: &BTreeMap, +) -> Result { + crate::library::set_calls(libraries); // Install the driver-resolved lang-item ids and emitted-function identities // for this run. Replace (rather than merge) both thread-local sets so // stale state from a previous run on this thread cannot survive. @@ -560,6 +583,12 @@ pub fn run_pipeline( PipelineError::Translation(format!("{}: {}", func.export_name, e.disp(&ctx))) })?; + if let Some(plan) = library_roots.get(&func.export_name) { + crate::kernel_resources::apply_library_block(&mut ctx, func_op_ptr, plan).map_err( + |error| PipelineError::Translation(format!("{}: {error}", func.export_name)), + )?; + } + if config.debug_kind.variables_enabled() { attach_debug_global_variables(&mut ctx, func_op_ptr, &config.debug_global_variables); } @@ -588,6 +617,19 @@ pub fn run_pipeline( append_to_module(&ctx, module_op_ptr, func_op_ptr); } + // Facts need the same helper alignment as lowering. This max-only call-graph + // propagation is idempotent; lowering also runs it for its other callers. + mir_lower::propagate_kernel_dynamic_shared_alignments(&mut ctx, module_op_ptr); + let kernel_launch_facts = crate::kernel_resources::collect( + &ctx, + module_op_ptr, + functions + .iter() + .filter(|function| function.is_kernel) + .map(|function| function.export_name.clone()), + ) + .map_err(PipelineError::Translation)?; + let ll_path = config.output_dir.join(format!("{}.ll", config.output_name)); let ptx_path = config .output_dir @@ -634,6 +676,7 @@ pub fn run_pipeline( target: generated.target, allow_fma_contraction: config.allow_fma_contraction, kernel_launch_bounds, + kernel_launch_facts, }) } ModuleArtifactKind::Ptx => Ok(CompilationResult { @@ -644,6 +687,7 @@ pub fn run_pipeline( target: generated.target, allow_fma_contraction: config.allow_fma_contraction, kernel_launch_bounds, + kernel_launch_facts, }), } } @@ -738,7 +782,9 @@ fn write_nvvm_compile_options_sidecar( }) } -fn stale_compilation_artifact_paths( +/// Paths the pipeline may remove or replace when compiling one module. +/// Callers can preflight these before compilation to protect external inputs. +pub fn stale_compilation_artifact_paths( output_dir: &Path, output_name: &str, ) -> Vec { diff --git a/cuda-oxide/crates/mir-importer/src/translator/body.rs b/cuda-oxide/crates/mir-importer/src/translator/body.rs index cd49e86c91..38c4d3ff8a 100644 --- a/cuda-oxide/crates/mir-importer/src/translator/body.rs +++ b/cuda-oxide/crates/mir-importer/src/translator/body.rs @@ -527,6 +527,27 @@ fn detect_dynamic_shared_alignment( None } +fn has_inferred_dynamic_shared( + body: &mir::Body, + reachable: &std::collections::BTreeSet, +) -> bool { + reachable.iter().any(|&index| { + let mir::TerminatorKind::Call { + func: mir::Operand::Constant(constant), + .. + } = &body.blocks[index].terminator.kind + else { + return false; + }; + let TyKind::RigidTy(RigidTy::FnDef(def_id, _)) = constant.const_.ty().kind() else { + return false; + }; + def_id.krate().name.as_str() == "cuda_device" + && (def_id.name() == "__dynamic_shared_inferred" + || def_id.name().ends_with("::__dynamic_shared_inferred")) + }) +} + /// Return the non-unwind successors of a block's terminator. /// /// [`mir::Terminator::successors`] includes unwind cleanup blocks alongside @@ -2347,6 +2368,22 @@ pub fn translate_body( } } + if has_inferred_dynamic_shared(body, &reachable) { + use pliron::builtin::{ + attributes::IntegerAttr, + types::{IntegerType, Signedness}, + }; + use pliron::utils::apint::APInt; + let ty = IntegerType::get(ctx, 32, Signedness::Unsigned); + mir_func_op.get_operation().deref_mut(ctx).attributes.set( + crate::kernel_resources::INFERRED_SHARED.try_into().unwrap(), + IntegerAttr::new( + ty, + APInt::from_u32(1, std::num::NonZeroUsize::new(32).unwrap()), + ), + ); + } + // Attribute macros may run before `#[kernel]`. Generic expansion forwards // that marker to the entry but also keeps the original in its helper, so // record markers on any function. mir-lower treats every marked local diff --git a/cuda-oxide/crates/mir-importer/src/translator/facts.rs b/cuda-oxide/crates/mir-importer/src/translator/facts.rs index c9542c38ff..22c4304fa7 100644 --- a/cuda-oxide/crates/mir-importer/src/translator/facts.rs +++ b/cuda-oxide/crates/mir-importer/src/translator/facts.rs @@ -417,6 +417,15 @@ mod pointer_origin { } } + /// ABI RULE: the unsafe native library marker supplies scratch as `*mut u8`. + /// Only this declared call boundary turns its internal shared base into RawMut. + pub(crate) fn abi_library_scratch() -> PointerOrigin { + PointerOrigin { + kind: MirPointerKind::RawMut, + mutable: true, + } + } + /// ABI RULE: `cuda_device::SharedPtr` stores a `*mut SharedSlot`, so /// the shared pointer it lowers to is always `RawMut`. pub(crate) fn abi_shared_ptr_field() -> PointerOrigin { 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 301415d0a4..709e0462de 100644 --- a/cuda-oxide/crates/mir-importer/src/translator/terminator/helpers.rs +++ b/cuda-oxide/crates/mir-importer/src/translator/terminator/helpers.rs @@ -350,6 +350,40 @@ pub fn emit_function_call( last_op = arg_last_op; } + emit_function_call_values( + ctx, + body, + callee_name, + arg_values, + destination, + return_type, + external_callee_type, + target, + block_ptr, + last_op, + value_map, + block_map, + loc, + ) +} + +/// Emit already translated arguments at an explicit foreign ABI boundary. +#[allow(clippy::too_many_arguments)] +pub(crate) fn emit_function_call_values( + ctx: &mut Context, + body: &mir::Body, + callee_name: &str, + mut arg_values: Vec, + destination: &mir::Place, + return_type: TypeHandle, + external_callee_type: Option, + target: &Option, + block_ptr: Ptr, + mut last_op: Option>, + value_map: &mut ValueMap, + block_map: &[Ptr], + loc: Location, +) -> TranslationResult> { // A Rust foreign declaration uses generic pointers at its ABI surface, // while an argument may retain a concrete GPU address space internally // (for example, `*mut T` in shared memory). Adapt that representation at diff --git a/cuda-oxide/crates/mir-importer/src/translator/terminator/intrinsics/memory.rs b/cuda-oxide/crates/mir-importer/src/translator/terminator/intrinsics/memory.rs index b8a3643d8c..246f673231 100644 --- a/cuda-oxide/crates/mir-importer/src/translator/terminator/intrinsics/memory.rs +++ b/cuda-oxide/crates/mir-importer/src/translator/terminator/intrinsics/memory.rs @@ -1010,6 +1010,7 @@ pub fn emit_dynamic_shared_get( loc: Location, byte_offset: u64, alignment: u64, + fixed_extent: bool, ) -> TranslationResult> { use dialect_mir::ops::MirExternSharedOp; // Get the destination type to determine the pointer element type @@ -1041,6 +1042,32 @@ pub fn emit_dynamic_shared_get( } }; + let layout = if fixed_extent { + Some( + pointee_ty + .layout() + .map_err(|error| { + pliron::input_error!( + loc.clone(), + TranslationErr::unsupported(format!( + "cannot determine fixed shared layout: {error:?}" + )) + ) + })? + .shape(), + ) + } else { + None + }; + let alignment = layout + .as_ref() + .map_or(alignment, |layout| alignment.max(layout.abi_align)); + if fixed_extent && !alignment.is_power_of_two() { + return input_err!( + loc.clone(), + TranslationErr::invalid_op("fixed shared alignment must be a nonzero power of two") + ); + } let elem_ty = crate::translator::types::translate_type(ctx, &pointee_ty)?; // Create a shared memory pointer type (addrspace 3) @@ -1067,6 +1094,27 @@ pub fn emit_dynamic_shared_get( 0, ); op.deref_mut(ctx).set_loc(loc.clone()); + if let Some(layout) = layout { + use pliron::builtin::attributes::IntegerAttr; + use pliron::utils::apint::APInt; + let ty = pliron::builtin::types::IntegerType::get( + ctx, + 64, + pliron::builtin::types::Signedness::Unsigned, + ); + op.deref_mut(ctx).attributes.set( + crate::kernel_resources::FIXED_SHARED_BYTES + .try_into() + .unwrap(), + IntegerAttr::new( + ty, + APInt::from_u64( + layout.size.bytes() as u64, + std::num::NonZeroUsize::new(64).unwrap(), + ), + ), + ); + } let extern_shared = MirExternSharedOp::new(op); diff --git a/cuda-oxide/crates/mir-importer/src/translator/terminator/mod.rs b/cuda-oxide/crates/mir-importer/src/translator/terminator/mod.rs index d88f37d4b0..adb23cd520 100644 --- a/cuda-oxide/crates/mir-importer/src/translator/terminator/mod.rs +++ b/cuda-oxide/crates/mir-importer/src/translator/terminator/mod.rs @@ -968,6 +968,27 @@ fn translate_call( let (pattern_name, call_name, substs_args, type_substs) = extract_func_info(func, &loc)?; let loc = call_debug_location(pattern_name.as_deref(), loc); + if let mir::Operand::Constant(constant) = func + && let rustc_public::ty::TyKind::RigidTy(rustc_public::ty::RigidTy::FnDef(def, substs)) = + constant.const_.ty().kind() + && let Ok(instance) = rustc_public::mir::mono::Instance::resolve(def, &substs) + && let Some(plan) = crate::library::get_call(instance.mangled_name().as_str()) + { + return crate::library::translate_call( + ctx, + body, + &plan, + args, + destination, + &target_usize, + block_ptr, + prev_op, + value_map, + block_map, + loc, + ); + } + // Is the trait-method Self type SharedArray? Shared with // `values::classify_call` so intrinsic dispatch and destination-slot // classification can't drift. @@ -1150,6 +1171,7 @@ fn translate_call( loc, 0, // byte_offset = 0 for get() and get_raw() alignment, // User-specified or default alignment + name.contains("::get_fixed"), ); } else if name.contains("::offset") { // DynamicSharedArray::offset(byte_offset) - get pointer at byte offset @@ -1477,6 +1499,7 @@ const KERNEL_METADATA_MARKERS: &[&str] = &[ "cuda_device::thread::__unchecked_indexing_config", "cuda_device::cluster::__cluster_config", "cuda_device::shared::__dynamic_shared_alignment", + "cuda_device::shared::__dynamic_shared_inferred", ]; /// Keep the macro-injected launch-context constructor out of user line tables. @@ -3177,7 +3200,8 @@ fn try_dispatch_intrinsic( loc, ))) } - "cuda_device::shared::__dynamic_shared_alignment" => { + "cuda_device::shared::__dynamic_shared_alignment" + | "cuda_device::shared::__dynamic_shared_inferred" => { // Zero-cost marker injected by #[launch_contract]. body.rs records // the const alignment on the kernel; no runtime call survives. let actual_prev_op = match prev_op { diff --git a/cuda-oxide/crates/mir-lower/src/lib.rs b/cuda-oxide/crates/mir-lower/src/lib.rs index 82fa281c4b..0e34ac7ce7 100644 --- a/cuda-oxide/crates/mir-lower/src/lib.rs +++ b/cuda-oxide/crates/mir-lower/src/lib.rs @@ -128,6 +128,7 @@ pub mod conversion_interface; pub mod convert; pub mod helpers; pub mod lowering; +pub use lowering::propagate_kernel_dynamic_shared_alignments; mod packed_shared_local_storage; pub mod scalarize_block_args; pub mod type_conversion_interface; diff --git a/cuda-oxide/crates/mir-lower/src/lowering.rs b/cuda-oxide/crates/mir-lower/src/lowering.rs index b0877b5b7e..f709627221 100644 --- a/cuda-oxide/crates/mir-lower/src/lowering.rs +++ b/cuda-oxide/crates/mir-lower/src/lowering.rs @@ -78,10 +78,7 @@ const RETURN_ABI_ALIGN_ATTR: &str = "cuda_oxide_return_abi_align"; /// shared-memory access can also live in a deeper ordinary helper. Shared /// helpers receive the maximum requirement from every marked root that can /// reach them. -pub(crate) fn propagate_kernel_dynamic_shared_alignments( - ctx: &mut Context, - module_op: Ptr, -) { +pub fn propagate_kernel_dynamic_shared_alignments(ctx: &mut Context, module_op: Ptr) { let mut functions = FxHashMap::default(); for region in module_op.deref(ctx).regions() { for block in region.deref(ctx).iter(ctx) { diff --git a/cuda-oxide/crates/oxide-artifacts/README.md b/cuda-oxide/crates/oxide-artifacts/README.md index d51f218699..98b9c6598f 100644 --- a/cuda-oxide/crates/oxide-artifacts/README.md +++ b/cuda-oxide/crates/oxide-artifacts/README.md @@ -56,7 +56,7 @@ Artifact Blob +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Payload Count | Entry Count | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ - | Compile Options (v2) / Reserved Zero (v1) | + | Compile Options (v2/v3) / Reserved Zero (v1) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Bundle Name ... / @@ -74,14 +74,14 @@ Artifact Blob Header size is currently 32 bytes. The final field occupies bytes 24 through 31 (the half-open range `[24, 32)`) and is a 64-bit compile-options bitset in -version 2. Bit 0 disables FMA contraction; unknown option bits are rejected. +versions 2 and 3. Bit 0 disables FMA contraction; unknown option bits are rejected. Version-1 bundles define the same bytes as reserved zero and use the historical default policy, where FMA contraction is allowed. -Version 2 is the latest supported format. For backward compatibility, the -writer still emits version 1 when the compile-options bitset is zero. It emits -version 2 only when a bundle carries a non-default compile policy, ensuring -that an older reader rejects policy it would otherwise silently ignore. +Version 3 carries finalized kernel launch facts. Bundles without launch facts +retain their existing encoding: version 1 for default compile policy and version +2 for non-default compile policy. A reader that does not support version 3 +rejects those bundles before loading code with unknown launch requirements. ```text Payload Record (24 bytes) @@ -111,7 +111,7 @@ Payload kind values: - `0x0200`: cubin ```text -Entry Record (24 bytes) +Entry Record (24 bytes in v1/v2; 48 bytes in v3) 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 @@ -135,8 +135,31 @@ Entry kind values: - `2`: device function If bit 0 of `Flags` is set, `Metadata` is present and interpreted by the -consumer for that entry kind. No metadata interpretation is currently required -for PTX kernel loading. +consumer for that entry kind. This opaque metadata is independent of typed +launch facts. + +Version 3 adds the following fields to every entry record: + +| Byte offset | Field | Type | +| --- | --- | --- | +| 24 | Exact block X | u32 | +| 28 | Exact block Y | u32 | +| 32 | Exact block Z | u32 | +| 36 | Finalized dynamic shared-memory bytes per block | u32 | +| 40 | Dynamic shared-memory alignment | u32 | +| 44 | Reserved zero | u32 | + +Flag bit 1 indicates that launch facts are present; bit 2 indicates an exact +block shape and requires bit 1. Facts are valid only for kernel entries. Exact +block dimensions must be nonzero and alignment must be a nonzero power of two. +Unknown version-3 entry flags are rejected. Absent fields are written as zero. + +Each record describes its concrete entry symbol, including separate generic +monomorphizations. A zero-byte allocation is distinct from absent facts. The +byte count excludes static shared memory and driver-reserved memory. The +producer supplies a finalized allocation and a matching generated alignment; +the container validates their representation but does not derive requirements +from device code or prove that the producer's claims are true. ## Object Storage @@ -154,11 +177,11 @@ cubin from embedded NVVM IR/LTOIR before loading. ## Constraints -- The latest supported format version is `2`; default-policy bundles are still - emitted as version `1` for backward compatibility. +- The latest supported format version is `3`; bundles without launch facts + retain their version `1` or `2` encoding. - All numeric fields are little-endian. - The blob header is fixed at 32 bytes. -- Payload and entry records are fixed at 24 bytes each. +- Payload records are 24 bytes; entry records are 24 bytes in v1/v2 and 48 in v3. - String and payload offsets are 32-bit, so a single blob must fit in `u32::MAX` bytes. - String lengths and record counts are 16-bit. diff --git a/cuda-oxide/crates/oxide-artifacts/src/lib.rs b/cuda-oxide/crates/oxide-artifacts/src/lib.rs index 99ef56fea2..7f0fc9ae5d 100644 --- a/cuda-oxide/crates/oxide-artifacts/src/lib.rs +++ b/cuda-oxide/crates/oxide-artifacts/src/lib.rs @@ -15,12 +15,20 @@ pub const ARTIFACT_SECTION_NAME: &str = ".oxart"; #[cfg(feature = "object-write")] const ARTIFACT_ANCHOR_SECTION_NAME: &str = ".oxlink"; pub const ARTIFACT_MAGIC: [u8; 8] = *b"OXIDEART"; -pub const ARTIFACT_VERSION: u16 = 2; +pub const ARTIFACT_VERSION: u16 = 3; +const COMPILE_OPTIONS_ARTIFACT_VERSION: u16 = 2; const LEGACY_ARTIFACT_VERSION: u16 = 1; const HEADER_BYTES: usize = 32; const PAYLOAD_RECORD_BYTES: usize = 24; -const ENTRY_RECORD_BYTES: usize = 24; +const LEGACY_ENTRY_RECORD_BYTES: usize = 24; +const ENTRY_RECORD_BYTES: usize = 48; + +const ENTRY_METADATA_PRESENT: u16 = 1; +const ENTRY_LAUNCH_FACTS_PRESENT: u16 = 1 << 1; +const ENTRY_EXACT_BLOCK_PRESENT: u16 = 1 << 2; +const KNOWN_ENTRY_FLAGS: u16 = + ENTRY_METADATA_PRESENT | ENTRY_LAUNCH_FACTS_PRESENT | ENTRY_EXACT_BLOCK_PRESENT; const OPTION_NO_FMA_CONTRACTION: u64 = 1 << 0; const OPTION_DEBUG_LINE_TABLES: u64 = 1 << 1; @@ -223,11 +231,28 @@ impl<'a> ArtifactPayloadSpec<'a> { } } +/// Finalized launch requirements for one concrete kernel entry. +/// +/// These facts describe the allocation selected by the compiler. They do not +/// include static shared memory or driver-reserved memory. An absent record +/// means that the producer did not provide finalized requirements; it is +/// distinct from a record requiring zero dynamic bytes. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct KernelLaunchFacts { + /// Required `(x, y, z)` block dimensions, when the kernel needs an exact shape. + pub exact_block: Option<(u32, u32, u32)>, + /// Finalized dynamic shared-memory allocation in bytes per block. + pub dynamic_shared_bytes: u32, + /// Alignment required by the generated dynamic shared-memory declaration. + pub dynamic_shared_alignment: u32, +} + #[derive(Clone, Debug, PartialEq, Eq)] pub struct ArtifactEntrySpec<'a> { pub symbol: &'a str, pub kind: ArtifactEntryKind, pub metadata: Option, + pub launch_facts: Option, } impl<'a> ArtifactEntrySpec<'a> { @@ -236,6 +261,7 @@ impl<'a> ArtifactEntrySpec<'a> { symbol, kind, metadata: None, + launch_facts: None, } } @@ -243,6 +269,11 @@ impl<'a> ArtifactEntrySpec<'a> { self.metadata = Some(metadata); self } + + pub const fn with_launch_facts(mut self, facts: KernelLaunchFacts) -> Self { + self.launch_facts = Some(facts); + self + } } #[derive(Clone, Debug, PartialEq, Eq)] @@ -293,6 +324,7 @@ pub struct ArtifactEntry<'a> { pub symbol: &'a str, pub kind: ArtifactEntryKind, pub metadata: Option, + pub launch_facts: Option, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -329,6 +361,7 @@ pub struct OwnedArtifactEntry { pub symbol: String, pub kind: ArtifactEntryKind, pub metadata: Option, + pub launch_facts: Option, } #[derive(Clone, Debug, PartialEq, Eq)] @@ -375,6 +408,7 @@ impl<'a> From> for OwnedArtifactBundle { symbol: entry.symbol.to_string(), kind: entry.kind, metadata: entry.metadata, + launch_facts: entry.launch_facts, }) .collect(), } @@ -445,6 +479,15 @@ impl std::error::Error for ArtifactError {} pub fn build_artifact_blob(spec: &ArtifactBundleSpec<'_>) -> Result, ArtifactError> { validate_spec(spec)?; + let has_launch_facts = spec + .entries + .iter() + .any(|entry| entry.launch_facts.is_some()); + let entry_record_bytes = if has_launch_facts { + ENTRY_RECORD_BYTES + } else { + LEGACY_ENTRY_RECORD_BYTES + }; let mut out = vec![0; HEADER_BYTES]; push_bytes(&mut out, spec.name.as_bytes()); push_bytes(&mut out, spec.target.as_bytes()); @@ -452,7 +495,7 @@ pub fn build_artifact_blob(spec: &ArtifactBundleSpec<'_>) -> Result, Art let payload_record_start = out.len(); out.resize(out.len() + spec.payloads.len() * PAYLOAD_RECORD_BYTES, 0); let entry_record_start = out.len(); - out.resize(out.len() + spec.entries.len() * ENTRY_RECORD_BYTES, 0); + out.resize(out.len() + spec.entries.len() * entry_record_bytes, 0); for (index, payload) in spec.payloads.iter().enumerate() { let name_offset = checked_u32(out.len(), "payload name offset")?; @@ -484,9 +527,21 @@ pub fn build_artifact_blob(spec: &ArtifactBundleSpec<'_>) -> Result, Art push_bytes(&mut out, entry.symbol.as_bytes()); align_vec(&mut out, 8); - let record = entry_record_start + index * ENTRY_RECORD_BYTES; + let record = entry_record_start + index * entry_record_bytes; write_u16(&mut out, record, entry.kind.to_u16()); - write_u16(&mut out, record + 2, u16::from(entry.metadata.is_some())); + let mut flags = u16::from(entry.metadata.is_some()); + if let Some(facts) = entry.launch_facts { + flags |= ENTRY_LAUNCH_FACTS_PRESENT; + if let Some((x, y, z)) = facts.exact_block { + flags |= ENTRY_EXACT_BLOCK_PRESENT; + write_u32(&mut out, record + 24, x); + write_u32(&mut out, record + 28, y); + write_u32(&mut out, record + 32, z); + } + write_u32(&mut out, record + 36, facts.dynamic_shared_bytes); + write_u32(&mut out, record + 40, facts.dynamic_shared_alignment); + } + write_u16(&mut out, record + 2, flags); write_u64(&mut out, record + 4, entry.metadata.unwrap_or(0)); write_u32(&mut out, record + 12, symbol_offset); write_u16( @@ -498,13 +553,15 @@ pub fn build_artifact_blob(spec: &ArtifactBundleSpec<'_>) -> Result, Art let total_len = checked_u32(out.len(), "total length")?; out[0..8].copy_from_slice(&ARTIFACT_MAGIC); - // Keep default-policy bundles on v1 for backward compatibility. A bundle - // that carries required compile policy uses v2 so an older reader rejects - // it instead of silently ignoring the semantic flag. - let version = if spec.compile_options == ArtifactCompileOptions::new() { + // Preserve the legacy bytes when no launch facts are supplied. Required + // launch facts use v3 so older readers reject them instead of silently + // ignoring the kernel's resource requirements. + let version = if has_launch_facts { + ARTIFACT_VERSION + } else if spec.compile_options == ArtifactCompileOptions::new() { LEGACY_ARTIFACT_VERSION } else { - ARTIFACT_VERSION + COMPILE_OPTIONS_ARTIFACT_VERSION }; write_u16(&mut out, 8, version); write_u16(&mut out, 10, HEADER_BYTES as u16); @@ -550,7 +607,10 @@ pub fn parse_artifact_blob(bytes: &[u8]) -> Result, ArtifactE return Err(ArtifactError::BadMagic); } let version = read_u16(bytes, 8)?; - if !matches!(version, LEGACY_ARTIFACT_VERSION | ARTIFACT_VERSION) { + if !matches!( + version, + LEGACY_ARTIFACT_VERSION | COMPILE_OPTIONS_ARTIFACT_VERSION | ARTIFACT_VERSION + ) { return Err(ArtifactError::UnsupportedVersion(version)); } let header_len = read_u16(bytes, 10)? as usize; @@ -591,8 +651,13 @@ pub fn parse_artifact_blob(bytes: &[u8]) -> Result, ArtifactE .ok_or(ArtifactError::TooLarge("payload records"))?; require_len(bytes, cursor, "payload records")?; let entry_records = cursor; + let entry_record_bytes = if version == ARTIFACT_VERSION { + ENTRY_RECORD_BYTES + } else { + LEGACY_ENTRY_RECORD_BYTES + }; cursor = cursor - .checked_add(entry_count * ENTRY_RECORD_BYTES) + .checked_add(entry_count * entry_record_bytes) .ok_or(ArtifactError::TooLarge("entry records"))?; require_len(bytes, cursor, "entry records")?; @@ -617,12 +682,12 @@ pub fn parse_artifact_blob(bytes: &[u8]) -> Result, ArtifactE let mut entries = Vec::with_capacity(entry_count); for index in 0..entry_count { - let record = entry_records + index * ENTRY_RECORD_BYTES; + let record = entry_records + index * entry_record_bytes; let kind_raw = read_u16(bytes, record)?; let kind = ArtifactEntryKind::from_u16(kind_raw) .ok_or(ArtifactError::UnsupportedEntryKind(kind_raw))?; let flags = read_u16(bytes, record + 2)?; - let metadata = if flags & 1 != 0 { + let metadata = if flags & ENTRY_METADATA_PRESENT != 0 { Some(read_u64(bytes, record + 4)?) } else { None @@ -630,10 +695,40 @@ pub fn parse_artifact_blob(bytes: &[u8]) -> Result, ArtifactE let symbol_offset = read_u32(bytes, record + 12)? as usize; let symbol_len = read_u16(bytes, record + 16)? as usize; let symbol = read_str(bytes, symbol_offset, symbol_len, "entry symbol")?; + let launch_facts = if version == ARTIFACT_VERSION { + if flags & !KNOWN_ENTRY_FLAGS != 0 + || flags & ENTRY_EXACT_BLOCK_PRESENT != 0 && flags & ENTRY_LAUNCH_FACTS_PRESENT == 0 + { + return Err(ArtifactError::Malformed(format!( + "invalid launch-facts flags {flags:#x} for entry '{symbol}'" + ))); + } + if flags & ENTRY_LAUNCH_FACTS_PRESENT != 0 { + Some(KernelLaunchFacts { + exact_block: if flags & ENTRY_EXACT_BLOCK_PRESENT != 0 { + Some(( + read_u32(bytes, record + 24)?, + read_u32(bytes, record + 28)?, + read_u32(bytes, record + 32)?, + )) + } else { + None + }, + dynamic_shared_bytes: read_u32(bytes, record + 36)?, + dynamic_shared_alignment: read_u32(bytes, record + 40)?, + }) + } else { + None + } + } else { + None + }; + validate_launch_facts(symbol, kind, launch_facts)?; entries.push(ArtifactEntry { symbol, kind, metadata, + launch_facts, }); } @@ -880,10 +975,39 @@ fn validate_spec(spec: &ArtifactBundleSpec<'_>) -> Result<(), ArtifactError> { if entry.symbol.is_empty() { return Err(ArtifactError::EmptyEntrySymbol); } + validate_launch_facts(entry.symbol, entry.kind, entry.launch_facts)?; } Ok(()) } +fn validate_launch_facts( + symbol: &str, + kind: ArtifactEntryKind, + facts: Option, +) -> Result<(), ArtifactError> { + let Some(facts) = facts else { + return Ok(()); + }; + let reason = if kind != ArtifactEntryKind::Kernel { + Some("launch facts require a kernel entry") + } else if facts + .exact_block + .is_some_and(|(x, y, z)| x == 0 || y == 0 || z == 0) + { + Some("exact block dimensions must be nonzero") + } else if !facts.dynamic_shared_alignment.is_power_of_two() { + Some("dynamic shared-memory alignment must be a nonzero power of two") + } else { + None + }; + match reason { + Some(reason) => Err(ArtifactError::Malformed(format!( + "invalid launch facts for entry '{symbol}': {reason}" + ))), + None => Ok(()), + } +} + fn checked_u16(value: usize, field: &'static str) -> Result { u16::try_from(value).map_err(|_| ArtifactError::TooLarge(field)) } @@ -1005,6 +1129,160 @@ mod tests { ); } + #[test] + fn concrete_kernel_launch_facts_survive_borrowed_and_owned_bundles() { + let first = KernelLaunchFacts { + exact_block: Some((32, 1, 1)), + dynamic_shared_bytes: 128, + dynamic_shared_alignment: 16, + }; + let second = KernelLaunchFacts { + exact_block: Some((8, 4, 1)), + dynamic_shared_bytes: 512, + dynamic_shared_alignment: 64, + }; + let empty = KernelLaunchFacts { + exact_block: None, + dynamic_shared_bytes: 0, + dynamic_shared_alignment: 1, + }; + let blob = build_artifact_blob( + &ArtifactBundleSpec::new("demo", "sm_90") + .with_compile_options(ArtifactCompileOptions::new().with_fma_contraction(false)) + .with_payload(ArtifactPayloadSpec::new( + ArtifactPayloadKind::Cubin, + "demo.cubin", + b"cubin", + )) + .with_entry( + ArtifactEntrySpec::new("apply_items_1", ArtifactEntryKind::Kernel) + .with_metadata(7) + .with_launch_facts(first), + ) + .with_entry( + ArtifactEntrySpec::new("apply_items_4", ArtifactEntryKind::Kernel) + .with_launch_facts(second), + ) + .with_entry( + ArtifactEntrySpec::new("no_scratch", ArtifactEntryKind::Kernel) + .with_launch_facts(empty), + ) + .with_entry(ArtifactEntrySpec::new( + "helper", + ArtifactEntryKind::DeviceFunction, + )), + ) + .unwrap(); + assert_eq!(read_u16(&blob, 8).unwrap(), ARTIFACT_VERSION); + let borrowed = parse_artifact_blob(&blob).unwrap(); + assert!(!borrowed.compile_options.fma_contraction_enabled()); + assert_eq!(borrowed.entry("apply_items_1").unwrap().metadata, Some(7)); + assert_eq!( + borrowed.entry("apply_items_1").unwrap().launch_facts, + Some(first) + ); + assert_eq!( + borrowed.entry("apply_items_4").unwrap().launch_facts, + Some(second) + ); + assert_eq!( + borrowed.entry("no_scratch").unwrap().launch_facts, + Some(empty) + ); + assert_eq!(borrowed.entry("helper").unwrap().launch_facts, None); + let owned = OwnedArtifactBundle::from(borrowed.clone()); + for entry in borrowed.entries { + assert_eq!( + owned.entry(entry.symbol).unwrap().launch_facts, + entry.launch_facts + ); + } + } + + #[test] + fn launch_facts_reject_invalid_shape_alignment_and_entry_kind() { + let valid = KernelLaunchFacts { + exact_block: Some((32, 1, 1)), + dynamic_shared_bytes: 128, + dynamic_shared_alignment: 16, + }; + let spec = |kind, facts| { + ArtifactBundleSpec::new("demo", "sm_90") + .with_payload(ArtifactPayloadSpec::new( + ArtifactPayloadKind::Ptx, + "demo.ptx", + b"ptx", + )) + .with_entry(ArtifactEntrySpec::new("hello", kind).with_launch_facts(facts)) + }; + for (kind, facts) in [ + (ArtifactEntryKind::DeviceFunction, valid), + ( + ArtifactEntryKind::Kernel, + KernelLaunchFacts { + exact_block: Some((32, 0, 1)), + ..valid + }, + ), + ( + ArtifactEntryKind::Kernel, + KernelLaunchFacts { + dynamic_shared_alignment: 0, + ..valid + }, + ), + ( + ArtifactEntryKind::Kernel, + KernelLaunchFacts { + dynamic_shared_alignment: 3, + ..valid + }, + ), + ] { + assert!(matches!( + build_artifact_blob(&spec(kind, facts)), + Err(ArtifactError::Malformed(_)) + )); + } + + let blob = build_artifact_blob(&spec(ArtifactEntryKind::Kernel, valid)).unwrap(); + let record = sample_payload_record_start() + PAYLOAD_RECORD_BYTES; + for (offset, value) in [(28, 0), (40, 3)] { + let mut corrupt = blob.clone(); + write_u32(&mut corrupt, record + offset, value); + assert!(matches!( + parse_artifact_blob(&corrupt), + Err(ArtifactError::Malformed(_)) + )); + } + let mut wrong_kind = blob.clone(); + write_u16( + &mut wrong_kind, + record, + ArtifactEntryKind::DeviceFunction.to_u16(), + ); + assert!(matches!( + parse_artifact_blob(&wrong_kind), + Err(ArtifactError::Malformed(_)) + )); + for flags in [ENTRY_EXACT_BLOCK_PRESENT, KNOWN_ENTRY_FLAGS | (1 << 3)] { + let mut corrupt = blob.clone(); + write_u16(&mut corrupt, record + 2, flags); + assert!(matches!( + parse_artifact_blob(&corrupt), + Err(ArtifactError::Malformed(_)) + )); + } + + let mut truncated = blob[..record + ENTRY_RECORD_BYTES - 1].to_vec(); + let len = truncated.len() as u32; + write_u32(&mut truncated, 12, len); + assert_eq!( + parse_artifact_blob(&truncated), + Err(ArtifactError::Truncated("entry records")) + ); + } + #[test] fn artifact_blob_round_trips_non_ptx_payload_kinds() { let blob = build_artifact_blob( @@ -1027,7 +1305,10 @@ mod tests { )), ) .unwrap(); - assert_eq!(read_u16(&blob, 8).unwrap(), ARTIFACT_VERSION); + assert_eq!( + read_u16(&blob, 8).unwrap(), + COMPILE_OPTIONS_ARTIFACT_VERSION + ); let bundles = parse_artifact_section(&blob).unwrap(); assert_eq!(bundles.len(), 1); @@ -1065,7 +1346,7 @@ mod tests { #[test] fn version_2_rejects_unknown_compile_option_bits() { let mut blob = sample_blob(); - write_u16(&mut blob, 8, ARTIFACT_VERSION); + write_u16(&mut blob, 8, COMPILE_OPTIONS_ARTIFACT_VERSION); write_u64(&mut blob, 24, 1 << 63); assert!(matches!( @@ -1110,7 +1391,10 @@ mod tests { ) .unwrap(); - assert_eq!(read_u16(&blob, 8).unwrap(), ARTIFACT_VERSION); + assert_eq!( + read_u16(&blob, 8).unwrap(), + COMPILE_OPTIONS_ARTIFACT_VERSION + ); assert_eq!( parse_artifact_blob(&blob).unwrap().compile_options, expected @@ -1121,7 +1405,7 @@ mod tests { #[test] fn version_2_rejects_conflicting_debug_bits() { let mut blob = sample_blob(); - write_u16(&mut blob, 8, ARTIFACT_VERSION); + write_u16(&mut blob, 8, COMPILE_OPTIONS_ARTIFACT_VERSION); write_u64(&mut blob, 24, OPTION_DEBUG_MASK); assert!(matches!( diff --git a/cuda-oxide/crates/reserved-oxide-symbols/src/lib.rs b/cuda-oxide/crates/reserved-oxide-symbols/src/lib.rs index 010bc715d2..2b0a27b1d4 100644 --- a/cuda-oxide/crates/reserved-oxide-symbols/src/lib.rs +++ b/cuda-oxide/crates/reserved-oxide-symbols/src/lib.rs @@ -72,6 +72,12 @@ pub const MATERIALIZER_PROVENANCE_ENV: &str = "CUDA_OXIDE_INTERNAL_MATERIALIZER_ /// code remains keyed by the content-derived provenance digest. pub const MATERIALIZER_HANDSHAKE_ENV: &str = "CUDA_OXIDE_INTERNAL_MATERIALIZER_HANDSHAKE"; +/// Ordered, content-bound external LTO-IR files supplied by cargo-oxide. +pub const EXTERNAL_LTOIR_ENV: &str = "CUDA_OXIDE_INTERNAL_EXTERNAL_LTOIR_V1"; + +/// Definition name in `cuda_device::library`; consumers resolve its actual DefId. +pub const LIBRARY_CALL_V1: &str = "cuda_oxide_library_v1_246e25db_call"; + /// Optional comma-separated filter selecting crates that may own device code. pub const DEVICE_CODEGEN_CRATE_ENV: &str = "CUDA_OXIDE_DEVICE_CODEGEN_CRATE"; @@ -143,6 +149,11 @@ pub const LEGACY_DEVICE_PREFIX: &str = "cuda_oxide_device_246e25db_"; /// linker resolves against the original (unprefixed) external symbol. pub const DEVICE_EXTERN_PREFIX: &str = "cuda_oxide_device_extern_246e25db_"; +/// Doc-alias marker retained after `#[convergent]` macro expansion. +/// Unlike doc comments, aliases survive dependency metadata even for private +/// externs reached through a downstream generic instantiation. +pub const DEVICE_EXTERN_CONVERGENT_MARKER: &str = "cuda_oxide_device_extern_convergent_246e25db"; + /// Prefix added to closure-monomorphization helper functions generated /// by `#[kernel]` for kernels that take a closure parameter. /// diff --git a/cuda-oxide/crates/rustc-codegen-cuda/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/Cargo.lock index 30afd8262e..1a330d7757 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/Cargo.lock @@ -582,8 +582,6 @@ checksum = "0b61fbf7ec37342ce171d9f5e3b82be74bda6c4e84e3b28338a03d553913e6aa" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] @@ -759,6 +757,7 @@ dependencies = [ "pliron", "pliron-derive", "reserved-oxide-symbols", + "serde", "serde_json", "thiserror", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/Cargo.toml b/cuda-oxide/crates/rustc-codegen-cuda/Cargo.toml index c20211c939..d1c3fb3598 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/Cargo.toml +++ b/cuda-oxide/crates/rustc-codegen-cuda/Cargo.toml @@ -26,7 +26,7 @@ dialect-nvvm = { path = "../dialect-nvvm" } reserved-oxide-symbols = { path = "../reserved-oxide-symbols" } # `#[tile_export]` descriptions, read back out of the metadata functions' MIR. oxide-tile-export = { path = "../oxide-tile-export" } -oxide-artifacts = { version = "0.2.1", features = ["object-write"] } +oxide-artifacts = { version = "0.2.1", path = "../oxide-artifacts", features = ["object-write"] } # Shared driver-independent libNVVM + nvJitLink finalization policy. This # crate loads CUDA compiler libraries at run time and never links libcuda. cuda-artifact-finalizer = { path = "../cuda-artifact-finalizer" } @@ -42,6 +42,7 @@ combine = "4.6.8" # must match workspace; Pliron needs SourcePosition: H once_cell = "1.18" # must match workspace thiserror = "2" # must match workspace serde_json = "1" # must match workspace +serde = { version = "1", features = ["derive"] } # Note: rustc internal crates are NOT listed here. # They're accessed via `extern crate` with #![feature(rustc_private)] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/abi_hmm/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/abi_hmm/Cargo.lock index ce0fdb7a46..ceff10a06d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/abi_hmm/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/abi_hmm/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/addressof_sharedarray/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/addressof_sharedarray/Cargo.lock index 298682ebe7..241d5202bc 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/addressof_sharedarray/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/addressof_sharedarray/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/aligned_field_loads/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/aligned_field_loads/Cargo.lock index f5335376d4..ba6228d6d0 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/aligned_field_loads/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/aligned_field_loads/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/aligned_field_stores/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/aligned_field_stores/Cargo.lock index 4c5f7cb96a..02cb8acf69 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/aligned_field_stores/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/aligned_field_stores/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/array_constants/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/array_constants/Cargo.lock index ef1ecaa2a8..f60fa62a9e 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/array_constants/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/array_constants/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/array_for_loop/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/array_for_loop/Cargo.lock index 3d737175ef..9dcc9d754c 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/array_for_loop/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/array_for_loop/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/array_index/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/array_index/Cargo.lock index d3a3501bfa..db218fe12d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/array_index/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/array_index/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/array_init/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/array_init/Cargo.lock index 86fba05561..372b41eeec 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/array_init/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/array_init/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/asin_acos_smoke/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/asin_acos_smoke/Cargo.lock index 802b3b906e..6f8acb79ef 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/asin_acos_smoke/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/asin_acos_smoke/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/assume_init_uninhabited_trap/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/assume_init_uninhabited_trap/Cargo.lock index 3adf8ffba8..073b2f2db5 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/assume_init_uninhabited_trap/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/assume_init_uninhabited_trap/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/async_mlp/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/async_mlp/Cargo.lock index 7028e34dbe..e04cd63b98 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/async_mlp/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/async_mlp/Cargo.lock @@ -221,6 +221,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -559,8 +561,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/async_vecadd/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/async_vecadd/Cargo.lock index 2174866807..36f22745e7 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/async_vecadd/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/async_vecadd/Cargo.lock @@ -221,6 +221,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -559,8 +561,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/atomic_f16/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/atomic_f16/Cargo.lock index b9a5b8237d..a40ff41ad6 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/atomic_f16/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/atomic_f16/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/atomics/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/atomics/Cargo.lock index 88b7fea84b..fed1ee0d43 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/atomics/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/atomics/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/barrier/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/barrier/Cargo.lock index 8b838a20e4..9fff6bf809 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/barrier/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/barrier/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/bf16x2_arith/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/bf16x2_arith/Cargo.lock index de59e51102..7272533c8e 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/bf16x2_arith/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/bf16x2_arith/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/bf16x2_fma/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/bf16x2_fma/Cargo.lock index 251e9a2a67..5b6fb4a9e9 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/bf16x2_fma/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/bf16x2_fma/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/bool_phi_cmp/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/bool_phi_cmp/Cargo.lock index 670e54de0c..8ff7fadadc 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/bool_phi_cmp/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/bool_phi_cmp/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/carrying_mul_add/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/carrying_mul_add/Cargo.lock index c07608a163..d9466aad2f 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/carrying_mul_add/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/carrying_mul_add/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cast_chunks/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cast_chunks/Cargo.lock index 7354ec93d3..a96720bc4d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cast_chunks/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cast_chunks/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cast_tests/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cast_tests/Cargo.lock index 5a0f4f1248..e24e8115a1 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cast_tests/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cast_tests/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cbrt_smoke/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cbrt_smoke/Cargo.lock index 3dac7b1997..9c82475d4f 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cbrt_smoke/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cbrt_smoke/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/checked_arith/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/checked_arith/Cargo.lock index aef438f58d..6dbdf6601c 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/checked_arith/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/checked_arith/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/clc/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/clc/Cargo.lock index b2358c8f96..7a428424f7 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/clc/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/clc/Cargo.lock @@ -198,6 +198,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cluster/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cluster/Cargo.lock index 428561d84b..fe39613f53 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cluster/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cluster/Cargo.lock @@ -198,6 +198,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/Cargo.lock new file mode 100644 index 0000000000..3b571c5a19 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/Cargo.lock @@ -0,0 +1,965 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "compiled_launch_facts" +version = "0.1.0" +dependencies = [ + "cuda-async", + "cuda-core", + "cuda-device", + "cuda-host", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cuda-artifact-finalizer" +version = "0.2.1" +dependencies = [ + "libnvvm-sys", + "nvjitlink-sys", + "serde", + "sha2", + "thiserror 2.0.18", +] + +[[package]] +name = "cuda-async" +version = "0.4.0" +dependencies = [ + "anyhow", + "cuda-bindings", + "cuda-core", + "dashmap", + "futures", + "half", + "once_cell", + "rustc-hash 2.1.2", + "thiserror 1.0.69", +] + +[[package]] +name = "cuda-bindings" +version = "0.4.0" +dependencies = [ + "bindgen", + "libloading", + "prettyplease", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cuda-core" +version = "0.4.0" +dependencies = [ + "anyhow", + "cuda-bindings", + "cuda-core-derive", + "half", + "oxide-artifacts", +] + +[[package]] +name = "cuda-core-derive" +version = "0.4.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cuda-device" +version = "0.2.1" +dependencies = [ + "cuda-macros", +] + +[[package]] +name = "cuda-host" +version = "0.2.1" +dependencies = [ + "cuda-artifact-finalizer", + "cuda-async", + "cuda-core", + "cuda-macros", + "half", + "libc", + "oxide-artifacts", + "ptx-parse", + "sha2", + "thiserror 2.0.18", +] + +[[package]] +name = "cuda-macros" +version = "0.2.1" +dependencies = [ + "oxide-tile-export", + "proc-macro2", + "quote", + "reserved-oxide-symbols", + "serde", + "serde_json", + "syn", +] + +[[package]] +name = "cuda-target-spec" +version = "0.1.0" + +[[package]] +name = "dashmap" +version = "6.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libnvvm-sys" +version = "0.2.1" +dependencies = [ + "cuda-target-spec", + "libloading", + "thiserror 2.0.18", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nvjitlink-sys" +version = "0.2.1" +dependencies = [ + "libloading", + "thiserror 2.0.18", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "crc32fast", + "hashbrown 0.15.5", + "indexmap", + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "oxide-artifacts" +version = "0.2.1" +dependencies = [ + "object", +] + +[[package]] +name = "oxide-tile-export" +version = "0.2.1" +dependencies = [ + "serde", + "serde_json", + "thiserror 2.0.18", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "ptx-parse" +version = "0.1.0" + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "reserved-oxide-symbols" +version = "0.2.1" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "smallvec" +version = "1.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/Cargo.toml b/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/Cargo.toml new file mode 100644 index 0000000000..5d4e02b884 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "compiled_launch_facts" +version = "0.1.0" +edition = "2024" +license = "Apache-2.0" + +[workspace] + +[features] +generic = [] +invalid-raw = [] + +[dependencies] +cuda-device = { path = "../../../cuda-device" } +cuda-host = { path = "../../../cuda-host", features = ["async"] } +cuda-core = { path = "../../../../../cuda-core" } +cuda-async = { path = "../../../../../cuda-async" } diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/README.md new file mode 100644 index 0000000000..21d9b3e2f9 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/README.md @@ -0,0 +1,36 @@ +# Compiled launch facts + +This example uses `dynamic_shared = inferred` with unsafe fixed views of the +CUDA dynamic shared-memory base. `Scratch<1>` and `Scratch<4>` have different +compiler layouts, reached through the same generic helper. A second view aliases +the base and raises its alignment to 128 bytes. The views combine by maximum +extent and alignment; they do not allocate separate regions. The helper writes +one slot per lane and explicitly synchronizes before reading neighboring slots. + +The generated prepared launch methods read the facts from the selected embedded +artifact. `LaunchConfig2D::auto_shared` selects 128 or 512 bytes. Preparation +rejects an explicit 511-byte allocation for the larger kernel and rejects a +32-by-1 block even though it has the same thread count as the required 8-by-4 +block. The example also checks known-zero scratch and returns an owned output +buffer only after asynchronous launch completion. + +From `cuda-oxide/`, run with an architecture supported by your device: + +```sh +cargo oxide run compiled_launch_facts --arch sm_120 +cargo oxide run compiled_launch_facts --arch sm_120 --features generic +cargo oxide run compiled_launch_facts --arch sm_120 --materialize-cubin +cargo oxide run compiled_launch_facts --arch sm_120 --features generic --materialize-cubin +scripts/check-compiled-launch-facts.sh sm_120 +``` + +The script also checks that an inferred kernel containing an unconstrained raw +dynamic view fails to compile. Generic kernels load either the merged PTX set or a single materialized native +artifact containing their concrete specializations. Multiple native artifacts or +mixed native/PTX bundles are rejected to preserve one module's device globals. Explicit raw pointer access, +initialization, bounds, aliasing, and synchronization remain the responsibility +of the unsafe device code. No synchronization is inserted by `get_fixed`. +Inference follows Rust views through direct calls. Dynamic-base accesses in +external code, indirect calls or inline assembly must fit a fixed view declared +on that path; they are not analyzed. Without declared views, inference records +zero bytes. diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/src/main.rs b/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/src/main.rs new file mode 100644 index 0000000000..fcd6049324 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/compiled_launch_facts/src/main.rs @@ -0,0 +1,162 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +use cuda_device::{DisjointSlice, kernel, launch_contract, shared::DynamicSharedArray, thread}; +use cuda_host::cuda_module; + +#[repr(C, align(64))] +struct Scratch { + slots: [[u32; 32]; ITEMS], +} + +#[cuda_module] +mod kernels { + use super::*; + + #[inline(never)] + fn exchange() -> u32 { + let lane = (thread::threadIdx_y() * 8 + thread::threadIdx_x()) as usize; + // Both views alias the same base. Every lane writes its own slots; + // the explicit barrier completes those writes before neighbor reads. + unsafe { + let scratch = DynamicSharedArray::, 16>::get_fixed().cast::(); + let alias = DynamicSharedArray::<[u32; 32], 128>::get_fixed().cast::(); + for item in 0..ITEMS { + scratch + .add(item * 32 + lane) + .write_volatile((item * 100 + lane) as u32); + } + thread::sync_threads(); + let neighbor = (lane + 1) % 32; + scratch.add((ITEMS - 1) * 32 + neighbor).read_volatile() + + alias.add(neighbor).read_volatile() + } + } + + #[kernel] + #[launch_contract(domain = 2, block = (8, 4, 1), dynamic_shared = inferred)] + pub fn fixed_one(mut output: DisjointSlice>) { + let value = exchange::<1>(); + if let Some(index) = thread::index_2d::<8>() + && let Some(out) = output.get_mut(index) + { + *out = value; + } + } + + #[kernel] + #[launch_contract(domain = 2, block = (8, 4, 1), dynamic_shared = inferred)] + pub fn fixed_four(mut output: DisjointSlice>) { + let value = exchange::<4>(); + if let Some(index) = thread::index_2d::<8>() + && let Some(out) = output.get_mut(index) + { + *out = value; + } + } + + #[kernel] + #[launch_contract(domain = 2, block = (8, 4, 1), dynamic_shared = inferred)] + pub fn zero() {} + + #[cfg(feature = "generic")] + #[launch_contract(domain = 2, block = (8, 4, 1), dynamic_shared = inferred)] + #[kernel] + pub fn generic(mut output: DisjointSlice>) { + let value = exchange::(); + if let Some(index) = thread::index_2d::<8>() + && let Some(out) = output.get_mut(index) + { + *out = value; + } + } + + #[cfg(feature = "invalid-raw")] + #[kernel] + #[launch_contract(domain = 2, block = (8, 4, 1), dynamic_shared = inferred)] + pub fn incomplete() { + unsafe { + DynamicSharedArray::<[u32; 32], 16>::get_fixed() + .cast::() + .write_volatile(1); + DynamicSharedArray::::get() + .add(64) + .write_volatile(2); + } + } +} + +fn verify(buffer: &cuda_core::DeviceBuffer, stream: &cuda_core::CudaStream, items: u32) { + let mut values = [0; 32]; + buffer.copy_to_host(stream, &mut values).unwrap(); + stream.synchronize().unwrap(); + for (lane, value) in values.into_iter().enumerate() { + assert_eq!(value, (items - 1) * 100 + 2 * ((lane as u32 + 1) % 32)); + } +} + +fn main() -> Result<(), Box> { + use cuda_async::simt::device_context::{init_device_contexts, with_cuda_context}; + use cuda_async::simt::device_operation::DeviceOperation; + use cuda_core::{DeviceBuffer, LaunchConfig2D}; + + init_device_contexts(0, 1)?; + let ctx = with_cuda_context(0, |ctx| ctx.clone())?; + let stream = ctx.default_stream(); + // SAFETY: the embedded module is compiled from these kernel declarations. + let module = unsafe { kernels::load_async(0)? }; + let config = LaunchConfig2D::auto_shared((1, 1), (8, 4)); + let one = module.prepare_fixed_one(config)?; + let four = module.prepare_fixed_four(config)?; + let zero = module.prepare_zero(config)?; + assert_eq!(one.__raw_config().shared_mem_bytes, 128); + assert_eq!(four.__raw_config().shared_mem_bytes, 512); + assert_eq!(zero.__raw_config().shared_mem_bytes, 0); + for prepared_facts in [ + one.function().launch_facts(), + four.function().launch_facts(), + ] { + let facts = prepared_facts.unwrap(); + assert_eq!(facts.exact_block, Some((8, 4, 1))); + assert_eq!(facts.dynamic_shared_alignment, 128); + } + assert_eq!( + zero.function().launch_facts().unwrap().dynamic_shared_bytes, + 0 + ); + assert!(matches!( + module.prepare_fixed_four(LaunchConfig2D::auto_shared((1, 1), (32, 1))), + Err(cuda_core::LaunchContractError::BlockShapeMismatch { .. }) + )); + assert!(matches!( + module.prepare_fixed_four(LaunchConfig2D::new((1, 1), (8, 4), 511)), + Err(cuda_core::LaunchContractError::DynamicSharedMemoryExactMismatch { .. }) + )); + let explicit = module.prepare_fixed_four(LaunchConfig2D::new((1, 1), (8, 4), 512))?; + + let output = DeviceBuffer::from_host(&stream, &[0u32; 32])?; + let output = module.fixed_one_async_owned(&one, output).sync()?; + verify(&output, &stream, 1); + let output = module.fixed_four_async_owned(&explicit, output).sync()?; + verify(&output, &stream, 4); + let output = module.fixed_four_async_owned(&four, output).sync()?; + verify(&output, &stream, 4); + + #[cfg(feature = "generic")] + { + let one = module.prepare_generic::<1>(config)?; + let four = module.prepare_generic::<4>(config)?; + assert_eq!(one.__raw_config().shared_mem_bytes, 128); + assert_eq!(four.__raw_config().shared_mem_bytes, 512); + let output = module.generic_async_owned::<1, _>(&one, output).sync()?; + verify(&output, &stream, 1); + let output = module.generic_async_owned::<4, _>(&four, output).sync()?; + verify(&output, &stream, 4); + } + println!( + "PASS: compiled launch facts: helper layouts, exact shape, explicit/automatic bytes, zero, and owned async passed" + ); + Ok(()) +} diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/compiler_features/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/compiler_features/Cargo.lock index 33acd7147e..d6f935bde1 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/compiler_features/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/compiler_features/Cargo.lock @@ -198,6 +198,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/complex_mul/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/complex_mul/Cargo.lock index c4fa3cf464..a58b569b3c 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/complex_mul/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/complex_mul/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/const_aggregate/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/const_aggregate/Cargo.lock index 6ea623f850..269b93125a 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/const_aggregate/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/const_aggregate/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/const_bool_dead_branch/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/const_bool_dead_branch/Cargo.lock index 91b2876e08..540b9c48f1 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/const_bool_dead_branch/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/const_bool_dead_branch/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/const_generic/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/const_generic/Cargo.lock index b15a635b4c..5f3219e271 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/const_generic/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/const_generic/Cargo.lock @@ -198,6 +198,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/const_table_lookup/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/const_table_lookup/Cargo.lock index 8ae82696df..20deaa9fa1 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/const_table_lookup/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/const_table_lookup/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/const_tuple_table_lookup/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/const_tuple_table_lookup/Cargo.lock index 53037c381d..57ce14515b 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/const_tuple_table_lookup/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/const_tuple_table_lookup/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_index_from_end/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_index_from_end/Cargo.lock index ab06a74fe1..6028c7043b 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_index_from_end/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_index_from_end/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory/Cargo.lock index 441dc70016..71f6baf8fd 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_coeffs/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_coeffs/Cargo.lock index cbd2c4a773..ef3d774030 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_coeffs/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_coeffs/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_simple/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_simple/Cargo.lock index 8656b34c60..371f459dc7 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_simple/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_simple/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_table/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_table/Cargo.lock index e1b980e909..2077171f28 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_table/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/constant_memory_table/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/coop_groups_demo/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/coop_groups_demo/Cargo.lock index cd1195cbd1..b1c194d6a3 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/coop_groups_demo/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/coop_groups_demo/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/copy_aggregate_borrow/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/copy_aggregate_borrow/Cargo.lock index 0ef4472db0..903794bd61 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/copy_aggregate_borrow/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/copy_aggregate_borrow/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/copy_nonoverlapping/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/copy_nonoverlapping/Cargo.lock index 03fc3fb565..f46061ee60 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/copy_nonoverlapping/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/copy_nonoverlapping/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/counted_barrier/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/counted_barrier/Cargo.lock index ee38589b3f..8c247e788d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/counted_barrier/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/counted_barrier/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cp_async_small/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cp_async_small/Cargo.lock index 8884ed45e2..662c000d4d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cp_async_small/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cp_async_small/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cp_async_zfill/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cp_async_zfill/Cargo.lock index 4c768d4fe9..2d412e3d89 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cp_async_zfill/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cp_async_zfill/Cargo.lock @@ -197,6 +197,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cpp_consumes_rust_device/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cpp_consumes_rust_device/Cargo.lock index 51381eb264..5fecd0b6d0 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cpp_consumes_rust_device/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cpp_consumes_rust_device/Cargo.lock @@ -196,6 +196,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -417,8 +419,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_embedded/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_embedded/Cargo.lock index 58f9f47452..b952b98d95 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_embedded/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_embedded/Cargo.lock @@ -198,6 +198,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -428,8 +430,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/Cargo.lock index 4142ea1aa4..dcb7410672 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/Cargo.lock @@ -199,6 +199,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -429,8 +431,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/Cargo.toml b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/Cargo.toml index 4a75520499..b37ac28fc1 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/Cargo.toml +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/Cargo.toml @@ -17,3 +17,7 @@ cuda-device = { path = "../../../cuda-device" } cuda-host = { path = "../../../cuda-host" } cuda-core = { path = "../../../../../cuda-core" } ptx-parse = { path = "../../../ptx-parse" } + +[features] +# Adds a second emitting crate to exercise the native-loader diagnostic. +native-ambiguity = ["kernel-lib/native-ambiguity"] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/README.md index aff5decf2b..66d7916b4d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/README.md +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/README.md @@ -1,5 +1,10 @@ # Cross-Crate Kernel Example +The `native-ambiguity` feature adds a concrete library kernel. With +`--materialize-cubin`, this produces separate library and consumer CUBINs; +the generic loader reports their incompatible topology. The compiled launch +facts script exercises this expected rejection. + This example demonstrates **defining type- and const-generic kernels in a library crate** and instantiating them from a binary crate. @@ -27,6 +32,7 @@ cross_crate_kernel/ ```bash cargo oxide run cross_crate_kernel +cargo oxide run cross_crate_kernel --arch sm_120 --materialize-cubin ``` The built executable can compare its own lookup names against generated PTX diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/kernel-lib/Cargo.toml b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/kernel-lib/Cargo.toml index 3300772048..b694ed873c 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/kernel-lib/Cargo.toml +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/kernel-lib/Cargo.toml @@ -9,3 +9,6 @@ license = "Apache-2.0" cuda-core = { path = "../../../../../../cuda-core" } cuda-device = { path = "../../../../cuda-device" } cuda-host = { path = "../../../../cuda-host" } + +[features] +native-ambiguity = [] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/kernel-lib/src/lib.rs b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/kernel-lib/src/lib.rs index 06fb421ff4..edd30936fe 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/kernel-lib/src/lib.rs +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/kernel-lib/src/lib.rs @@ -17,6 +17,11 @@ use cuda_device::{DisjointSlice, cuda_module, kernel, thread}; pub mod kernels { use super::*; + /// Emits a separate library artifact for the native ambiguity check. + #[cfg(feature = "native-ambiguity")] + #[kernel] + pub fn concrete() {} + /// Generic scale kernel - multiplies each element by a factor. /// /// This kernel is exported from the library and can be instantiated diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/src/main.rs b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/src/main.rs index 36388bf446..944f0aeb2c 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/src/main.rs +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_kernel/src/main.rs @@ -114,11 +114,9 @@ fn main() { // The device code is embedded in this binary, so there is no loose `.ptx` // to locate or keep in step. // - // `kernels` is generic, and a generic module's generated loader merges the - // PTX bundles of every crate in the build instead of selecting one by name - // (it discards the crate-name hint outright). That merge is what makes the - // specializations below resolvable at all: they are monomorphized here, in - // the binary, from kernels declared in kernel-lib. + // These specializations belong to the consuming binary. Generic loading + // merges its PTX bundles or loads the sole complete materialized artifact, + // then resolves each exact specialization name in that one CUDA module. let module = kernels::load(&ctx).expect("Failed to load embedded CUDA module"); // Test data @@ -300,7 +298,7 @@ fn main() { println!("\nThis demonstrates:"); println!(" - Generic kernels can be defined in library crates"); println!(" - They are monomorphized when used in the application"); - println!(" - PTX is generated for all used instantiations"); + println!(" - Device code is generated for all used instantiations"); println!(" - Const values participate in cross-crate kernel identity"); println!(" - Device helper functions from libraries also work"); } diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_merged_symbols/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_merged_symbols/Cargo.lock index 12297db68c..d8485d2680 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_merged_symbols/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_merged_symbols/Cargo.lock @@ -198,6 +198,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -428,8 +430,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_recursion/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_recursion/Cargo.lock index 8f2b797d96..0fa905fb7c 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_recursion/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cross_crate_recursion/Cargo.lock @@ -198,6 +198,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_contract/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_contract/Cargo.lock index 08be6237f6..778b5c3353 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_contract/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_contract/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_in_lib/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_in_lib/Cargo.lock index ed02b84ccf..af04e9638d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_in_lib/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_in_lib/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -428,8 +430,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_nested/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_nested/Cargo.lock index 971388c6c3..821ced1df1 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_nested/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cuda_module_nested/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cutile_inter_kernel/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cutile_inter_kernel/Cargo.lock index fe8a69f59d..f033829f60 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cutile_inter_kernel/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cutile_inter_kernel/Cargo.lock @@ -713,8 +713,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object 0.36.7", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cutile_inter_kernel/simt/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cutile_inter_kernel/simt/Cargo.lock index 35aaf4c667..dd9a614f39 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cutile_inter_kernel/simt/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cutile_inter_kernel/simt/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cvt_f16x2/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cvt_f16x2/Cargo.lock index 818576913e..775bb475b7 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cvt_f16x2/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cvt_f16x2/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/cvt_packed/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/cvt_packed/Cargo.lock index 94d0618251..d9426835d0 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/cvt_packed/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/cvt_packed/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/debug-tests/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/debug-tests/Cargo.lock index f5df8eec21..ba170e30a6 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/debug-tests/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/debug-tests/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/debug/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/debug/Cargo.lock index 06c9f62bfd..0c47946338 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/debug/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/debug/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/debug_pointer_locals/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/debug_pointer_locals/Cargo.lock index a163c07916..0148f7c017 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/debug_pointer_locals/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/debug_pointer_locals/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_closures/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_closures/Cargo.lock index a71448a33a..37ca3bcc89 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_closures/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_closures/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/Cargo.lock index a158e03b8d..d8fa432c73 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -195,6 +197,13 @@ dependencies = [ name = "cuda-target-spec" version = "0.1.0" +[[package]] +name = "device-ffi-collectives" +version = "0.1.0" +dependencies = [ + "cuda-device", +] + [[package]] name = "device_ffi_test" version = "0.1.0" @@ -202,6 +211,7 @@ dependencies = [ "cuda-core", "cuda-device", "cuda-host", + "device-ffi-collectives", ] [[package]] @@ -418,8 +428,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/Cargo.toml b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/Cargo.toml index 28ace2a1d4..3c7fef7608 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/Cargo.toml +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/Cargo.toml @@ -11,3 +11,4 @@ license = "Apache-2.0" cuda-device = { path = "../../../cuda-device" } cuda-host = { path = "../../../cuda-host" } cuda-core = { path = "../../../../../cuda-core" } +device-ffi-collectives = { path = "convergence-helper" } diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/README.md index d02e6056cd..b71a620120 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/README.md +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/README.md @@ -125,16 +125,17 @@ device_ffi_test/ ## How It Works -### 1. Rust Kernel Code (`src/main.rs`) +### 1. Rust Kernel Code (simplified) ```rust -use cuda_device::{device, kernel}; +use cuda_device::{convergent, device, kernel}; // Declare external device functions from CUDA C++ -// Note: No NVVM attributes needed - see "Why No NVVM Attributes?" below +// Mark collectives before the Rust device module is optimized. #[device] unsafe extern "C" { fn magnitude_squared(x: f32, y: f32) -> f32; + #[convergent] fn warp_reduce_sum(val: f32) -> f32; } @@ -205,46 +206,27 @@ callers that deliberately use this mapping may allow that lint on the extern. --- -## Why No NVVM Attributes on Extern Declarations? +## Convergence on Extern Declarations -When using LTOIR linking, **NVVM attributes (`#[convergent]`, `#[pure]`, `#[readonly]`) -are not needed on Rust extern function declarations**. Here's why: +Mark external warp and block collective declarations with `#[convergent]`. +cuda-oxide emits LLVM's `convergent` attribute on each marked declaration before +libNVVM optimizes the Rust device module. Attributes on external definitions +arrive later during LTO and cannot protect earlier optimization. -### The LTOIR Already Has Proper Attributes +The annotation forbids transformations that add control dependencies to the +call. It does not make threads reach the call or guarantee reconvergence; +callers must satisfy the collective's warp or block participation requirements. +Reachable declarations of the same symbol must agree on the annotation. Ordinary +scalar helpers and storage-size queries do not need this annotation. -External CUDA C++ compiled with `nvcc -dc -dlto` produces LTOIR with complete -attribute specifications on the function **definitions**: +The `convergence-helper` dependency declares `warp_reduce_sum` privately and +calls it through a public generic device helper. `verify-code-shape.sh` checks +that this declaration retains convergence in the consuming module, alongside +local collective declarations and unmarked scalar declarations. -```llvm -; From cccl_wrappers_text.ltoir -attributes #0 = { convergent inlinehint mustprogress willreturn } -attributes #7 = { convergent nounwind } -``` - -### nvJitLink Uses Definition Attributes - -During LTO linking: -1. cuda-oxide LTOIR has **declarations** (no function body) -2. External LTOIR has **definitions** with proper attributes -3. nvJitLink resolves symbols and uses the **definition's attributes** for optimization - -### Attributes on Declarations Are Redundant - -Since the linker uses the definition's attributes: -- Attributes on declarations don't affect the final code -- The external library authors already set correct attributes -- User-specified attributes could be incorrect or misleading - -### What About cuda-oxide Built-in Intrinsics? - -For cuda-oxide's own intrinsics (like `sync_threads()`, `shuffle()`, etc.), the -compiler handles convergent semantics internally. Users don't need to annotate these. - -### Historical Note - -Earlier versions of this example used `#[convergent]`, `#[pure]`, and `#[readonly]` -attributes. These have been removed as they provided no benefit with LTOIR linking -and could mislead users into thinking they were necessary. +Built-in intrinsics such as `sync_threads()` and warp shuffles already carry +convergence information. `#[pure]` and `#[readonly]` do not currently emit LLVM +memory-effect attributes. --- diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/convergence-helper/Cargo.toml b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/convergence-helper/Cargo.toml new file mode 100644 index 0000000000..a5a148e40d --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/convergence-helper/Cargo.toml @@ -0,0 +1,12 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +[package] +name = "device-ffi-collectives" +version = "0.1.0" +edition = "2024" +license = "Apache-2.0" +publish = false + +[dependencies] +cuda-device = { path = "../../../../cuda-device" } diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/convergence-helper/src/lib.rs b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/convergence-helper/src/lib.rs new file mode 100644 index 0000000000..52c17256c0 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/convergence-helper/src/lib.rs @@ -0,0 +1,22 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#[cuda_device::device] +unsafe extern "C" { + // Deliberately private: the downstream generic instantiation must recover + // convergence from dependency metadata without an exported declaration. + #[cuda_device::convergent] + fn warp_reduce_sum(value: f32) -> f32; +} + +/// Reduce a warp and scale its sum in a downstream device instantiation. +/// +/// # Safety +/// +/// All lanes in a full warp must participate in the reduction. +#[cuda_device::device] +pub unsafe fn scaled_warp_sum(value: f32) -> f32 { + unsafe { warp_reduce_sum(value) * SCALE as f32 } +} diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/src/main.rs b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/src/main.rs index 0deb545121..02b51e9cdb 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/src/main.rs +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/src/main.rs @@ -20,16 +20,15 @@ //! cargo run --release //! ``` -use cuda_device::{device, gpu_printf, kernel, shared::DynamicSharedArray}; +use cuda_device::{convergent, device, gpu_printf, kernel, shared::DynamicSharedArray}; use cuda_host::cuda_module; +use device_ffi_collectives::scaled_warp_sum; // ============================================================================= // External device functions from external_device_funcs.cu // -// NOTE: No NVVM attributes (#[convergent], #[pure], #[readonly]) are needed here. -// The external LTOIR already contains proper attributes on the function definitions. -// When nvJitLink performs LTO linking, it uses the definition's attributes. -// See README.md "Why No NVVM Attributes?" for details. +// Collective declarations carry convergence before libNVVM optimization. +// See README.md "Convergence on Extern Declarations" for details. // ============================================================================= #[device] @@ -37,7 +36,7 @@ unsafe extern "C" { fn magnitude_squared(x: f32, y: f32) -> f32; fn fast_rsqrt(x: f32) -> f32; fn dot_product(a: *const f32, b: *const f32, n: i32) -> f32; - fn warp_reduce_sum(val: f32) -> f32; + #[convergent] fn warp_ballot(predicate: i32) -> u32; fn simple_add(a: f32, b: f32) -> f32; // `char` is a plain 32-bit device-extern slot. Rust still warns because C @@ -56,13 +55,16 @@ unsafe extern "C" { // CCCL (CUB) wrapper functions from cccl_wrappers.cu // // These wrap CUB template functions as extern "C" for FFI. -// The CCCL LTOIR already has proper convergent/nounwind attributes. +// Mark collectives so their participation requirements survive prelink optimization. // ============================================================================= #[device] unsafe extern "C" { + #[convergent] fn cub_block_reduce_sum_f32_256(input: f32, temp: *mut u8) -> f32; + #[convergent] fn cub_block_reduce_max_f32_256(input: f32, temp: *mut u8) -> f32; + #[convergent] fn cub_warp_reduce_sum_f32(input: f32) -> f32; fn cub_get_block_reduce_temp_size_256() -> i32; } @@ -88,7 +90,7 @@ mod kernels { let added = unsafe { simple_add(mag, 1.0) }; // Test convergent function (all threads participate) - let sum = unsafe { warp_reduce_sum(added) }; + let sum = unsafe { scaled_warp_sum::<1>(added) }; // Lane 0 writes result if tid.is_multiple_of(32) { diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/verify-code-shape.sh b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/verify-code-shape.sh index 66bd4fcaf1..e61bf5750d 100755 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/verify-code-shape.sh +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_ffi_test/verify-code-shape.sh @@ -4,12 +4,14 @@ # A runtime q -> Q check cannot distinguish a plain i32 ABI from the plausible # but wrong `zeroext i32` mapping: both reach the same PTX and hardware result. -# Pin the declaration and calls in the emitted LLVM IR before LTO. +# Pin the declaration and calls in the emitted LLVM IR before LTO. Also check +# that a private extern reached through a dependency's generic helper retains +# convergence, while the ordinary char declarations remain unmarked. set -euo pipefail root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -ll="${root}/device_ffi_test.ll" +ll="${1:-${root}/device_ffi_test.ll}" test -s "${ll}" @@ -46,4 +48,19 @@ if grep -Eq '\b(signext|zeroext)\b' <<<"${char_lines}"; then exit 1 fi -echo "device_ffi_test char ABI shape: PASS" +# Calls retain the existing conservative convergence group; only these ordinary +# declarations must be unmarked. The anchored declaration patterns above also +# reject an unexpected attribute trailer. +if grep -E '^declare .*@(char_to_upper|char_store)\(' "${ll}" | grep -qw convergent; then + echo "error: ordinary char declarations must not be convergent" >&2 + exit 1 +fi + +for symbol in warp_reduce_sum cub_warp_reduce_sum_f32; do + require_count "convergent ${symbol} declaration" 1 \ + "^declare float @${symbol}\(float\) convergent$" +done +require_count "convergent warp_ballot declaration" 1 \ + '^declare i32 @warp_ballot\(i32\) convergent$' + +echo "device_ffi_test char ABI and convergence shape: PASS (${ll})" diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_global/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_global/Cargo.lock index 35ee0cd474..34a044dde0 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_global/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_global/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_panic_trap/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_panic_trap/Cargo.lock index 6407c721d4..3cba554846 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/device_panic_trap/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/device_panic_trap/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/disjoint_from_raw_parts/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/disjoint_from_raw_parts/Cargo.lock index 16f5eeea64..490c0d0a67 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/disjoint_from_raw_parts/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/disjoint_from_raw_parts/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/disjoint_slice_len/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/disjoint_slice_len/Cargo.lock index dd634310c2..28069e461e 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/disjoint_slice_len/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/disjoint_slice_len/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/dotprod/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/dotprod/Cargo.lock index 6eae6d938e..0661576639 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/dotprod/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/dotprod/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/dpx_minmax_chains/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/dpx_minmax_chains/Cargo.lock index e089b4e94a..0ca009a89c 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/dpx_minmax_chains/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/dpx_minmax_chains/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/drop_glue/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/drop_glue/Cargo.lock index 266b7f6694..e23269615a 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/drop_glue/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/drop_glue/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/dst_metadata/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/dst_metadata/Cargo.lock index 9c6fb2bc3e..b64a9b2b79 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/dst_metadata/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/dst_metadata/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/dynamic_smem/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/dynamic_smem/Cargo.lock index d00f6456ab..25be24e31b 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/dynamic_smem/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/dynamic_smem/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/elect_leader/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/elect_leader/Cargo.lock index 24b95937f2..fcfb5c8f14 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/elect_leader/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/elect_leader/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_abi_multi_payload/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_abi_multi_payload/Cargo.lock index 6139e1050f..24f00c9000 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_abi_multi_payload/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_abi_multi_payload/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_array_match/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_array_match/Cargo.lock index 4985ca6d9f..3782625d34 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_array_match/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_array_match/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_constant_provenance/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_constant_provenance/Cargo.lock index 8af4e5d135..6cc9062d99 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_constant_provenance/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_constant_provenance/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_payload_addr/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_payload_addr/Cargo.lock index c952ef0989..00d764f904 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_payload_addr/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_payload_addr/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_state_transitions/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_state_transitions/Cargo.lock index 3a6c6a60cc..e84831240e 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_state_transitions/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_state_transitions/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_table_lookup/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_table_lookup/Cargo.lock index 984dd1bb34..b165a21f0b 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_table_lookup/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/enum_table_lookup/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error/Cargo.lock index aaa54e5982..46b2ab5ea4 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_bool_payload_addr/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_bool_payload_addr/Cargo.lock index ce15431ac5..654202bc73 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_bool_payload_addr/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_bool_payload_addr/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_pointer_overlap/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_pointer_overlap/Cargo.lock index 0fa3b0a4ee..a4b50245fd 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_pointer_overlap/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_pointer_overlap/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_shared_pointer_layout/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_shared_pointer_layout/Cargo.lock index f06797a06b..8b0ba7235f 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_shared_pointer_layout/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_enum_shared_pointer_layout/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_abi/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_abi/Cargo.lock index 4c5a1cecc5..ba6ba19c3a 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_abi/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_abi/Cargo.lock @@ -192,6 +192,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -422,8 +424,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_callable/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_callable/Cargo.lock index edd815e111..5c867e9f4a 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_callable/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_callable/Cargo.lock @@ -192,6 +192,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -422,8 +424,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_fn_pointer/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_fn_pointer/Cargo.lock index d5446db5d0..78e2ca4b95 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_fn_pointer/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_fn_pointer/Cargo.lock @@ -192,6 +192,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -422,8 +424,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_unknown_id/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_unknown_id/Cargo.lock index 9b25129d83..b1b7265ffd 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_unknown_id/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_generated_intrinsic_unknown_id/Cargo.lock @@ -192,6 +192,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -422,8 +424,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_heap_alloc/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_heap_alloc/Cargo.lock index 1a466544e6..b227a77857 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_heap_alloc/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_heap_alloc/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_host_arch_intrinsic/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_host_arch_intrinsic/Cargo.lock index 7191053847..7b68e83e2a 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_host_arch_intrinsic/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_host_arch_intrinsic/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_host_target_feature/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_host_target_feature/Cargo.lock index 3219ee0d34..bd716642d0 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_host_target_feature/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_host_target_feature/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_kernel_shared_param/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_kernel_shared_param/Cargo.lock index 44916f1a99..4bfd78c739 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_kernel_shared_param/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_kernel_shared_param/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_kernel_shared_ptr_param/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_kernel_shared_ptr_param/Cargo.lock index c46db5e9e1..aec4d393ee 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_kernel_shared_ptr_param/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_kernel_shared_ptr_param/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_missing_device_attr/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_missing_device_attr/Cargo.lock index 649e784194..e0e4d32478 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_missing_device_attr/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_missing_device_attr/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_set_discriminant_uninhabited/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_set_discriminant_uninhabited/Cargo.lock index 5c81d90910..e3d2e3d001 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_set_discriminant_uninhabited/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_set_discriminant_uninhabited/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_union_shared_pointer_addr/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_union_shared_pointer_addr/Cargo.lock index 746e3e1063..f1d5c7bd90 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_union_shared_pointer_addr/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_union_shared_pointer_addr/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_union_shared_pointer_layout/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_union_shared_pointer_layout/Cargo.lock index ac804086d6..2acbde1d31 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/error_union_shared_pointer_layout/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/error_union_shared_pointer_layout/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/ex2_approx_f16/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/ex2_approx_f16/Cargo.lock index 33cd0aa21e..63fca3d627 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/ex2_approx_f16/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/ex2_approx_f16/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/exact_div_chunks/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/exact_div_chunks/Cargo.lock index 93a2a2860b..5c793ec1d6 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/exact_div_chunks/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/exact_div_chunks/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/export_name_policy/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/export_name_policy/Cargo.lock index ad50057c7b..0d216aa157 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/export_name_policy/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/export_name_policy/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/extern_crate_closure/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/extern_crate_closure/Cargo.lock index a3de61cf65..a5bcb03706 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/extern_crate_closure/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/extern_crate_closure/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -423,8 +425,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/extern_libdevice/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/extern_libdevice/Cargo.lock index 676af798d0..2ff208b8b3 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/extern_libdevice/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/extern_libdevice/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/Cargo.lock new file mode 100644 index 0000000000..129767b8ab --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/Cargo.lock @@ -0,0 +1,753 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cuda-artifact-finalizer" +version = "0.2.1" +dependencies = [ + "libnvvm-sys", + "nvjitlink-sys", + "serde", + "sha2", + "thiserror", +] + +[[package]] +name = "cuda-bindings" +version = "0.4.0" +dependencies = [ + "bindgen", + "libloading", + "prettyplease", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cuda-core" +version = "0.4.0" +dependencies = [ + "anyhow", + "cuda-bindings", + "cuda-core-derive", + "half", + "oxide-artifacts", +] + +[[package]] +name = "cuda-core-derive" +version = "0.4.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cuda-device" +version = "0.2.1" +dependencies = [ + "cuda-macros", +] + +[[package]] +name = "cuda-host" +version = "0.2.1" +dependencies = [ + "cuda-artifact-finalizer", + "cuda-core", + "cuda-macros", + "half", + "libc", + "oxide-artifacts", + "ptx-parse", + "sha2", + "thiserror", +] + +[[package]] +name = "cuda-macros" +version = "0.2.1" +dependencies = [ + "oxide-tile-export", + "proc-macro2", + "quote", + "reserved-oxide-symbols", + "serde", + "serde_json", + "syn", +] + +[[package]] +name = "cuda-target-spec" +version = "0.1.0" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "external_ltoir" +version = "0.1.0" +dependencies = [ + "cuda-core", + "cuda-device", + "cuda-host", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libnvvm-sys" +version = "0.2.1" +dependencies = [ + "cuda-target-spec", + "libloading", + "thiserror", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nvjitlink-sys" +version = "0.2.1" +dependencies = [ + "libloading", + "thiserror", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "crc32fast", + "hashbrown 0.15.5", + "indexmap", + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "oxide-artifacts" +version = "0.2.1" +dependencies = [ + "object", +] + +[[package]] +name = "oxide-tile-export" +version = "0.2.1" +dependencies = [ + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "ptx-parse" +version = "0.1.0" + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "reserved-oxide-symbols" +version = "0.2.1" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/Cargo.toml b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/Cargo.toml new file mode 100644 index 0000000000..0daa15796f --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/Cargo.toml @@ -0,0 +1,15 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +[package] +name = "external_ltoir" +version = "0.1.0" +edition = "2024" +license = "Apache-2.0" +publish = false + +[workspace] + +[dependencies] +cuda-device = { path = "../../../cuda-device" } +cuda-host = { path = "../../../cuda-host" } +cuda-core = { path = "../../../../../cuda-core" } diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/README.md new file mode 100644 index 0000000000..a81f51b014 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/README.md @@ -0,0 +1,36 @@ +# External device LTO-IR + +This example calls a CUDA C++ device function from a Rust kernel. The C++ +function calls another function in a second LTO-IR file. `cargo oxide` links +both files into the embedded cubin during the build, and the program uses the +ordinary `kernels::load` API. It checks `output[i] = 2 * input[i] + 3` on the GPU. + +From `cuda-oxide/`, with the CUDA Toolkit and a matching GPU available: + +```bash +example=crates/rustc-codegen-cuda/examples/external_ltoir +mkdir -p build/device-libs +nvcc --ltoir -dlto -arch=sm_120 \ + "$example/scale.cu" -o build/device-libs/scale.ltoir +nvcc --ltoir -dlto -arch=sm_120 \ + "$example/add.cu" -o build/device-libs/add.ltoir +cargo oxide run external_ltoir --arch sm_120 --materialize-cubin \ + --link-ltoir build/device-libs/scale.ltoir \ + --link-ltoir build/device-libs/add.ltoir +``` + +Use the same architecture for both compilers. Each `--link-ltoir` adds one +file in argument order; paths are relative to the command's working directory. +The inputs must be raw LTO-IR, not object files or fatbins. `--ltoir -dlto` +writes the explicit output path, including with architecture names such as +`sm_90a`. All supplied files are linked into each materialized device artifact +in the Cargo invocation. The executable contains the finished cubin and needs no external `.ltoir` files +or runtime link step. + +`scripts/check-external-ltoir.sh sm_120` exercises run, build and test, repeated +build freshness, content changes at the same path, a missing transitive symbol, +execution with the link inputs removed, corrupt LTO-IR, and rejection of an +input/output collision without changing either file. It prints the +temporary directory containing its logs and generated inputs; it uses the +same nvcc commands with those temporary output paths. The check requires a GPU +matching the requested architecture. diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/add.cu b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/add.cu new file mode 100644 index 0000000000..d74d9bd981 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/add.cu @@ -0,0 +1,12 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef EXTERNAL_ADDEND +#define EXTERNAL_ADDEND 3 +#endif + +extern "C" __device__ int external_add(int value) { + return value + EXTERNAL_ADDEND; +} diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/scale.cu b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/scale.cu new file mode 100644 index 0000000000..ea5be973c4 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/scale.cu @@ -0,0 +1,10 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +extern "C" __device__ int external_add(int value); + +extern "C" __device__ int external_scale_add(int value) { + return external_add(value * 2); +} diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/src/main.rs b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/src/main.rs new file mode 100644 index 0000000000..04efbfab78 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/external_ltoir/src/main.rs @@ -0,0 +1,73 @@ +/* + * SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +//! Link two CUDA C++ device libraries during compilation and load the embedded cubin. + +use cuda_core::simt::LaunchConfig; +use cuda_core::{CudaContext, DeviceBuffer}; +use cuda_device::{DisjointSlice, device, kernel, thread}; +use cuda_host::cuda_module; + +#[device] +unsafe extern "C" { + fn external_scale_add(value: i32) -> i32; +} + +#[cuda_module] +mod kernels { + use super::*; + + #[kernel] + pub fn scale_add(input: &[i32], mut output: DisjointSlice) { + let index = thread::index_1d(); + let offset = index.get(); + if let Some(value) = output.get_mut(index) { + // SAFETY: the C++ definition takes and returns an int32 scalar; + // it accesses no pointers and has no participation requirement. + *value = unsafe { external_scale_add(input[offset]) }; + } + } +} + +fn verify(expected_addend: i32) -> Result<(), Box> { + let context = CudaContext::new(0)?; + let stream = context.default_stream(); + let input: Vec = (-128..129).collect(); + let device_input = DeviceBuffer::from_host(&stream, &input)?; + let mut device_output = DeviceBuffer::::zeroed(&stream, input.len())?; + let module = kernels::load(&context)?; + // SAFETY: the equal-length buffers cover every access, the bounds check + // handles the partial last block, and the kernel needs no shared memory. + unsafe { + module.scale_add( + &stream, + LaunchConfig::for_num_elems(input.len() as u32), + &device_input, + &mut device_output, + )?; + } + let actual = device_output.to_host_vec(&stream)?; + let expected: Vec = input + .iter() + .map(|value| value * 2 + expected_addend) + .collect(); + assert_eq!(actual, expected); + println!("PASS external LTO-IR: 257 values, addend={expected_addend}"); + Ok(()) +} + +fn main() -> Result<(), Box> { + let expected_addend = std::env::args() + .nth(1) + .map(|value| value.parse()) + .transpose()? + .unwrap_or(3); + verify(expected_addend) +} + +#[test] +fn linked_device_libraries_execute() { + verify(3).unwrap(); +} diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/f16_stress/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/f16_stress/Cargo.lock index 1981d414f2..ff6fec6bf4 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/f16_stress/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/f16_stress/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/f16x2_arith/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/f16x2_arith/Cargo.lock index 31579841ea..1fbc0d9b22 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/f16x2_arith/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/f16x2_arith/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/f32x2_arith/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/f32x2_arith/Cargo.lock index 9bc296863f..1e19d42863 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/f32x2_arith/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/f32x2_arith/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/fcmp_ne_nan_smoke/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/fcmp_ne_nan_smoke/Cargo.lock index 71b0d21466..e703a14d26 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/fcmp_ne_nan_smoke/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/fcmp_ne_nan_smoke/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/field_array_assign/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/field_array_assign/Cargo.lock index b198305b8e..d550be6734 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/field_array_assign/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/field_array_assign/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/float_rounding/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/float_rounding/Cargo.lock index 80dfa026eb..e84cf5c37d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/float_rounding/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/float_rounding/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/fmaxmin_smoke/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/fmaxmin_smoke/Cargo.lock index a3233b3c21..8658870241 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/fmaxmin_smoke/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/fmaxmin_smoke/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/fn_ptr_naming/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/fn_ptr_naming/Cargo.lock index 2a909c83ac..5b702a3a9e 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/fn_ptr_naming/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/fn_ptr_naming/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/fp_special_literal_smoke/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/fp_special_literal_smoke/Cargo.lock index 86eb3f25e8..59d7802668 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/fp_special_literal_smoke/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/fp_special_literal_smoke/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/function_item_call/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/function_item_call/Cargo.lock index fc1c163579..ccee9e9b5f 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/function_item_call/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/function_item_call/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/future_apis/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/future_apis/Cargo.lock index cbfd3853ea..8e3be64b44 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/future_apis/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/future_apis/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm/Cargo.lock index d83a865a01..190fd721bc 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_sol/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_sol/Cargo.lock index 4ce39a1971..7e1725f960 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_sol/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_sol/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_sol_final/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_sol_final/Cargo.lock index ad956f3af4..db696d9c83 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_sol_final/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_sol_final/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -420,8 +422,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_views/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_views/Cargo.lock index 9a3324ea0b..68a1b7909c 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_views/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/gemm_views/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -419,8 +421,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_intrinsics/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_intrinsics/Cargo.lock index cd9f2ba0b2..b39986147c 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_intrinsics/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_intrinsics/Cargo.lock @@ -192,6 +192,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -423,8 +425,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_intrinsics_blackwell/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_intrinsics_blackwell/Cargo.lock index 04de2c5f8b..2149219dfd 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_intrinsics_blackwell/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_intrinsics_blackwell/Cargo.lock @@ -192,6 +192,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -423,8 +425,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_ldmatrix/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_ldmatrix/Cargo.lock index bb356b611b..ad614a0dc5 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_ldmatrix/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/generated_ldmatrix/Cargo.lock @@ -192,6 +192,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -423,8 +425,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/generic/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/generic/Cargo.lock index 6a78ca4f12..4ac3b32844 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/generic/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/generic/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap/Cargo.lock index 86b24f7d2a..5fcdf702d1 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap_v2/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap_v2/Cargo.lock index 0fb7f0e99e..e853259d52 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap_v2/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap_v2/Cargo.lock @@ -219,6 +219,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -453,8 +455,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap_v3/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap_v3/Cargo.lock index b781c994c5..d4ea73dfbb 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap_v3/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/hashmap_v3/Cargo.lock @@ -219,6 +219,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -453,8 +455,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/hello_constant/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/hello_constant/Cargo.lock index f3fe99746f..ab7b9cf416 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/hello_constant/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/hello_constant/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/helper_fn/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/helper_fn/Cargo.lock index 7de74fdb2b..486c0eb04d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/helper_fn/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/helper_fn/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure/Cargo.lock index 05cdf65074..15d2a8ac17 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure/Cargo.lock @@ -210,6 +210,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -558,8 +560,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure_target_feature/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure_target_feature/Cargo.lock index 6c77a5ff67..0e0aae4bff 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure_target_feature/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/host_closure_target_feature/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/iket_trace/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/iket_trace/Cargo.lock index 86c75b8ff3..adc4499587 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/iket_trace/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/iket_trace/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/image_convolution/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/image_convolution/Cargo.lock index d5aa2ae65e..9d1d65fefc 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/image_convolution/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/image_convolution/Cargo.lock @@ -200,6 +200,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -471,8 +473,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/index2d_const/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/index2d_const/Cargo.lock index 3836acca0b..a51ea3797d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/index2d_const/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/index2d_const/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/index_field_assign/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/index_field_assign/Cargo.lock index 1a1e93d7b5..ff4ce9e1fe 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/index_field_assign/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/index_field_assign/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/inline_intent/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/inline_intent/Cargo.lock index cb8ef2d6db..b98ddfd161 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/inline_intent/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/inline_intent/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/inline_ptx/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/inline_ptx/Cargo.lock index 53bc623360..2f00a288bb 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/inline_ptx/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/inline_ptx/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/integer_minmax/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/integer_minmax/Cargo.lock index fe88f463bb..1876e267c7 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/integer_minmax/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/integer_minmax/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/interior_mutability/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/interior_mutability/Cargo.lock index a6f716be40..7b8c8c6cdb 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/interior_mutability/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/interior_mutability/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/interop_cubin_identity/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/interop_cubin_identity/Cargo.lock index 8746a26f4b..f58ab57e9b 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/interop_cubin_identity/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/interop_cubin_identity/Cargo.lock @@ -346,8 +346,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/interop_cubin_identity/device/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/interop_cubin_identity/device/Cargo.lock index f22694c1a4..5851c457fb 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/interop_cubin_identity/device/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/interop_cubin_identity/device/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/kernel_reference_validity/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/kernel_reference_validity/Cargo.lock index 6100df50d1..f4ccd984b3 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/kernel_reference_validity/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/kernel_reference_validity/Cargo.lock @@ -210,6 +210,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -557,8 +559,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/lanemask_scan/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/lanemask_scan/Cargo.lock index 394622c351..50c08df470 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/lanemask_scan/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/lanemask_scan/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_atomic_fadd/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_atomic_fadd/Cargo.lock index 1e2ee59815..08e48a5f67 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_atomic_fadd/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_atomic_fadd/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_atomic_rmw_cas/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_atomic_rmw_cas/Cargo.lock index ecfb175d50..2104ce45aa 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_atomic_rmw_cas/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_atomic_rmw_cas/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_nvvm_pointer_shapes/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_nvvm_pointer_shapes/Cargo.lock index 1aa0595d80..ed39398346 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_nvvm_pointer_shapes/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/legacy_nvvm_pointer_shapes/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/libdevice_math/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/libdevice_math/Cargo.lock index d285772669..d4dd551d13 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/libdevice_math/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/libdevice_math/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/libm_math/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/libm_math/Cargo.lock index 460643529b..9452790b57 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/libm_math/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/libm_math/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -425,8 +427,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/manual_launch_generic/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/manual_launch_generic/Cargo.lock index 3f172b6f05..da6499f56b 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/manual_launch_generic/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/manual_launch_generic/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/manual_launch_libdevice/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/manual_launch_libdevice/Cargo.lock index 4118e90b10..aa8948c218 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/manual_launch_libdevice/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/manual_launch_libdevice/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/map_sum/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/map_sum/Cargo.lock index 9924014ffa..ca7892e5e7 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/map_sum/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/map_sum/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/math_atan/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/math_atan/Cargo.lock index 8ce1894329..2d9f7a36c9 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/math_atan/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/math_atan/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/math_hyperbolic/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/math_hyperbolic/Cargo.lock index f7f1e6c274..5a698da6b5 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/math_hyperbolic/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/math_hyperbolic/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/math_no_mir_inline/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/math_no_mir_inline/Cargo.lock index b7718a33a7..0f300b48d6 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/math_no_mir_inline/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/math_no_mir_inline/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/math_tan/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/math_tan/Cargo.lock index 552212e5e4..2d3d1309ae 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/math_tan/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/math_tan/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/mathdx_ffi_test/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/mathdx_ffi_test/Cargo.lock index 76fc9daba6..ba24c9f2f8 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/mathdx_ffi_test/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/mathdx_ffi_test/Cargo.lock @@ -208,6 +208,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -455,8 +457,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/mcast_barrier_test/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/mcast_barrier_test/Cargo.lock index 47eec7302e..bd30881e04 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/mcast_barrier_test/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/mcast_barrier_test/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/mem_swap/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/mem_swap/Cargo.lock index 611d7a182b..794d07b7e0 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/mem_swap/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/mem_swap/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/mir_projected_call_destination/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/mir_projected_call_destination/Cargo.lock index 8791af0505..c870acdd1b 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/mir_projected_call_destination/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/mir_projected_call_destination/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -425,8 +427,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/mma_mxf8f6f4/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/mma_mxf8f6f4/Cargo.lock index da7974c0f7..69f11e54ca 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/mma_mxf8f6f4/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/mma_mxf8f6f4/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/Cargo.lock new file mode 100644 index 0000000000..fbc8697266 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/Cargo.lock @@ -0,0 +1,755 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" + +[[package]] +name = "bindgen" +version = "0.69.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "lazy_static", + "lazycell", + "log", + "prettyplease", + "proc-macro2", + "quote", + "regex", + "rustc-hash", + "shlex", + "syn", + "which", +] + +[[package]] +name = "bitflags" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "cuda-artifact-finalizer" +version = "0.2.1" +dependencies = [ + "libnvvm-sys", + "nvjitlink-sys", + "serde", + "sha2", + "thiserror", +] + +[[package]] +name = "cuda-bindings" +version = "0.4.0" +dependencies = [ + "bindgen", + "libloading", + "prettyplease", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cuda-core" +version = "0.4.0" +dependencies = [ + "anyhow", + "cuda-bindings", + "cuda-core-derive", + "half", + "oxide-artifacts", +] + +[[package]] +name = "cuda-core-derive" +version = "0.4.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "cuda-device" +version = "0.2.1" +dependencies = [ + "cuda-macros", +] + +[[package]] +name = "cuda-host" +version = "0.2.1" +dependencies = [ + "cuda-artifact-finalizer", + "cuda-core", + "cuda-macros", + "half", + "libc", + "oxide-artifacts", + "ptx-parse", + "sha2", + "thiserror", +] + +[[package]] +name = "cuda-macros" +version = "0.2.1" +dependencies = [ + "oxide-tile-export", + "proc-macro2", + "quote", + "reserved-oxide-symbols", + "serde", + "serde_json", + "syn", +] + +[[package]] +name = "cuda-target-spec" +version = "0.1.0" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "either" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "indexmap" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +dependencies = [ + "equivalent", + "hashbrown 0.17.1", +] + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] + +[[package]] +name = "libnvvm-sys" +version = "0.2.1" +dependencies = [ + "cuda-target-spec", + "libloading", + "thiserror", +] + +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "memchr" +version = "2.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "native_library" +version = "0.1.0" +dependencies = [ + "cuda-core", + "cuda-device", + "cuda-host", + "serde_json", + "sha2", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nvjitlink-sys" +version = "0.2.1" +dependencies = [ + "libloading", + "thiserror", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "crc32fast", + "hashbrown 0.15.5", + "indexmap", + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "oxide-artifacts" +version = "0.2.1" +dependencies = [ + "object", +] + +[[package]] +name = "oxide-tile-export" +version = "0.2.1" +dependencies = [ + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "ptx-parse" +version = "0.1.0" + +[[package]] +name = "quote" +version = "1.0.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "reserved-oxide-symbols" +version = "0.2.1" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "syn" +version = "2.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "typenum" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "which" +version = "4.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" +dependencies = [ + "either", + "home", + "once_cell", + "rustix", +] + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zerocopy" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce1022995ff5ff5d841ad7d994facc23098cd40152f2c1d11cd607c6f530653f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ae7f38b72ec2a254e2b87ef277cf2cd4fb97cbebf944faa6f33354da0867930" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zmij" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/Cargo.toml b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/Cargo.toml new file mode 100644 index 0000000000..0c085d9f98 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/Cargo.toml @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 + +[package] +name = "native_library" +version = "0.1.0" +edition = "2024" +license = "Apache-2.0" +publish = false + +[workspace] + +[dependencies] +cuda-device = { path = "../../../cuda-device" } +cuda-host = { path = "../../../cuda-host" } +cuda-core = { path = "../../../../../cuda-core" } + +[build-dependencies] +serde_json = "1" +sha2 = "0.10" diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/README.md b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/README.md new file mode 100644 index 0000000000..6dafcc085e --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/README.md @@ -0,0 +1,36 @@ +# Native library discovery + +This unsafe compiler fixture loads an i32 tile and adds seven through a native +CUDA implementation. Its generic dependency helper is instantiated with one +and four items per thread. The build script registers itself as the provider; +the compiler sends concrete requests and links the returned LTO-IR. No CUB +checkout, hand-written extern declaration or external artifact list is needed. + +From `cuda-oxide/`, with a CUDA toolkit and matching GPU: + +```sh +cargo oxide run native_library --arch sm_120 --materialize-cubin +cargo oxide test native_library --arch sm_120 --materialize-cubin +``` + +The provider invokes the selected toolkit's `nvcc`; `CUDAHOSTCXX` may select +its host compiler. Launch preparation uses inferred shared-memory facts and +rejects an equal-product wrong block shape. Both kernels run three blocks and +check every output. The raw helper requires full input/output tiles and exact +participation; this fixture does not claim a safe collective API. + +The smoke script supplies materialization and the target in each lane: + +```sh +scripts/smoketest.sh --only '^native_library$' +scripts/smoketest.sh --only '^native_library$' --compile-only +scripts/smoketest.sh --only '^native_library$' --full-debug +``` + +The artifact-only lanes run the fixture's `--check-artifact TARGET OUTPUT` +mode without creating a CUDA context. It verifies the embedded CUBIN and +both kernels' launch facts, then extracts the image to `OUTPUT`. Full debug +adds `--full-debug`, requires the recorded full-debug policy, and uses +`readelf` or `llvm-readelf` to check both kernels' DWARF. That lane uses the +modern libNVVM target (the host target on Blackwell or newer, otherwise +`sm_100`) and launches no kernels. diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/build.rs b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/build.rs new file mode 100644 index 0000000000..2c5d5d075b --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/build.rs @@ -0,0 +1,141 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +use serde_json::{Value, json}; +use sha2::{Digest, Sha256}; +use std::io::{Read, Write}; + +fn serve() -> Result<(), Box> { + let mut input = String::new(); + std::io::stdin() + .take(1024 * 1024 + 1) + .read_to_string(&mut input)?; + assert!(input.len() <= 1024 * 1024); + let request: Value = serde_json::from_str(&input)?; + assert_eq!(request["version"], 1); + let target = request["target"].as_str().ok_or("missing target")?; + // nvcc emits PTX for -arch=compute_XX even with --ltoir. Select its + // matching real architecture to obtain raw LTO-IR for nvJitLink. + let nvcc_target = format!( + "sm_{}", + target.strip_prefix("compute_").ok_or("invalid target")? + ); + let cuda = request["cuda_root"].as_str().ok_or("missing toolkit")?; + let mut source = String::new(); + let mut entries = Vec::new(); + let scalar = json!({"kind":"signed", "bits":32}); + for (index, item) in request["requests"] + .as_array() + .ok_or("missing requests")? + .iter() + .enumerate() + { + assert_eq!(item["operation"], "load_add"); + assert_eq!(item["algorithm"], "direct"); + assert_eq!(item["dtype"], scalar); + let block = item["block"].as_array().ok_or("missing block")?; + assert_eq!(&block[1..], &[json!(1), json!(1)]); + let threads = block[0].as_u64().ok_or("invalid block")?; + let items = item["items_per_thread"].as_u64().ok_or("invalid extent")?; + assert!((1..=1024).contains(&threads) && (1..=16).contains(&items)); + let symbol = format!("fixture_load_b{threads}_i{items}"); + source.push_str(&format!( + "extern \"C\" __device__ void {symbol}(const int* memory, int* values, unsigned char*, int add) {{\n#pragma unroll\nfor (int i=0; i<{items}; ++i) values[i]=memory[threadIdx.x*{items}+i]+add;\n}}\n" + )); + entries.push(json!({ + "request_index": index, + "identity": Sha256::digest(symbol.as_bytes()).to_vec(), + "symbol": symbol, + "arguments": [ + {"kind":"const_pointer", "scalar":scalar}, + {"kind":"mut_pointer", "scalar":scalar}, + {"kind":"value", "scalar":scalar} + ], + "cub_layout": {"size":0,"alignment":1}, + "scratch": {"size":0,"alignment":1}, + "scratch_free": true, "mutates_payload": true + })); + } + // This fixture compiles a tiny native implementation without a CUB dependency. + // Each invocation owns its temporary files, including simultaneous consumers. + let directory = + std::env::temp_dir().join(format!("oxide-library-fixture-{}", std::process::id())); + std::fs::create_dir(&directory)?; + let result = (|| -> Result, Box> { + let cpp = directory.join("provider.cu"); + let lto = directory.join("provider.ltoir"); + std::fs::write(&cpp, source)?; + let mut command = std::process::Command::new(std::path::Path::new(cuda).join("bin/nvcc")); + command.args(["--ltoir", "-dlto", "-arch", &nvcc_target]); + if let Some(host) = std::env::var_os("CUDAHOSTCXX") { + command.arg("-ccbin").arg(host); + } + let status = command.arg(&cpp).arg("-o").arg(<o).status()?; + if !status.success() { + return Err("fixture native compilation failed".into()); + } + Ok(std::fs::read(lto)?) + })(); + std::fs::remove_dir_all(&directory)?; + let lto = result?; + let header = serde_json::to_vec(&json!({ + "version":1, "batch_identity":Sha256::digest(<o).to_vec(), + "specializations":entries + }))?; + let mut output = std::io::stdout().lock(); + output.write_all(b"OXDLIB01")?; + output.write_all(&(header.len() as u64).to_le_bytes())?; + output.write_all(&(lto.len() as u64).to_le_bytes())?; + output.write_all(&header)?; + output.write_all(<o)?; + Ok(()) +} + +fn serve_inputs() -> Result<(), Box> { + let mut bytes = Vec::new(); + std::io::stdin() + .take(1024 * 1024 + 1) + .read_to_end(&mut bytes)?; + assert!(bytes.len() <= 1024 * 1024); + let request: Value = serde_json::from_slice(&bytes)?; + assert_eq!(request["version"], 1); + let cuda = std::path::Path::new(request["cuda_root"].as_str().ok_or("missing toolkit")?); + let host = std::env::var_os("CUDAHOSTCXX").unwrap_or_else(|| "g++".into()); + let host = std::path::PathBuf::from(host); + let host = if host.is_absolute() { + host + } else { + std::env::split_paths(&std::env::var_os("PATH").unwrap_or_default()) + .map(|directory| directory.join(&host)) + .find(|path| path.is_file()) + .ok_or("cannot locate native host compiler")? + }; + // The example tracks CUDA tools/headers and the host compiler driver. + // The host compiler's installed system headers/libraries are assumed stable. + serde_json::to_writer( + std::io::stdout().lock(), + &json!({ + "version":1, + "paths":[cuda.join("bin"), cuda.join("nvvm"), cuda.join("include"), host], + "environment":["CUDAHOSTCXX", "PATH", "NVCC_PREPEND_FLAGS", "NVCC_APPEND_FLAGS", + "CPATH", "CPLUS_INCLUDE_PATH", "GCC_EXEC_PREFIX", "COMPILER_PATH"] + }), + )?; + Ok(()) +} + +fn main() -> Result<(), Box> { + match std::env::args().nth(1).as_deref() { + Some("--oxide-library-request-v1") => return serve(), + Some("--oxide-library-inputs-v1") => return serve_inputs(), + _ => {} + } + println!("cargo::rerun-if-changed=build.rs"); + let registration = json!({ + "version":1, "provider":"native_library_fixture", + "executable":std::env::current_exe()?, + "operation":"load_add", "algorithm":"direct" + }); + println!("cargo::rustc-env=FIXTURE_REGISTRATION={registration}"); + Ok(()) +} diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/src/lib.rs b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/src/lib.rs new file mode 100644 index 0000000000..de2edaefb9 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/src/lib.rs @@ -0,0 +1,32 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +#![no_std] + +fn registration() -> &'static str { + cuda_device::library::registration!("FIXTURE_REGISTRATION") +} + +/// Load a complete block tile through a native provider in a dependency crate. +/// +/// # Safety +/// +/// Launch 128-thread one-dimensional blocks. Input/output must cover every +/// block's complete tile; input stays immutable and output tiles are disjoint. +#[inline(never)] +pub unsafe fn load_add(input: *const i32, output: *mut i32) { + let lane = cuda_device::thread::threadIdx_x() as usize; + let origin = cuda_device::thread::blockIdx_x() as usize * 128 * ITEMS; + let mut values = [0_i32; ITEMS]; + // SAFETY: each thread owns its initialized local array, and the caller + // supplies the full input tile and required geometry. This recipe uses no scratch. + unsafe { + cuda_device::library::call_v1::( + registration, + (input.add(origin), values.as_mut_ptr(), 7_i32), + ); + for (item, value) in values.iter().enumerate() { + output.add(origin + lane * ITEMS + item).write(*value); + } + } +} diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/src/main.rs b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/src/main.rs new file mode 100644 index 0000000000..c7302dba27 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/native_library/src/main.rs @@ -0,0 +1,134 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +use cuda_core::embedded::{ + ArtifactDebugPolicy, ArtifactPayloadKind, artifact_bundles_from_current_exe, +}; +use cuda_core::{CudaContext, DeviceBuffer, LaunchConfig3D}; +use cuda_device::{kernel, launch_bounds, launch_contract}; +use cuda_host::cuda_module; + +#[cuda_module] +mod kernels { + use super::*; + + #[kernel] + #[launch_bounds(256)] + #[launch_contract(domain = 3, dynamic_shared = inferred)] + pub unsafe fn one(input: *const i32, output: *mut i32) { + unsafe { + native_library::load_add::<1>(input, output); + } + } + + #[kernel] + #[launch_bounds(256)] + #[launch_contract(domain = 3, dynamic_shared = inferred)] + pub unsafe fn four(input: *const i32, output: *mut i32) { + unsafe { + native_library::load_add::<4>(input, output); + } + } +} + +fn verify() -> Result<(), Box> { + let context = CudaContext::new(0)?; + let stream = context.default_stream(); + // SAFETY: the embedded image was produced from this module's declarations. + let module = unsafe { kernels::load(&context)? }; + for items in [1, 4] { + let input: Vec = (0..3 * 128 * items).map(|i| i * 3 - 11).collect(); + let device_input = DeviceBuffer::from_host(&stream, &input)?; + let device_output = DeviceBuffer::::zeroed(&stream, input.len())?; + let config = LaunchConfig3D::auto_shared((3, 1, 1), (128, 1, 1)); + macro_rules! launch { + ($prepare:ident, $kernel:ident) => {{ + let prepared = module.$prepare(config)?; + let facts = prepared.function().launch_facts().unwrap(); + assert_eq!(facts.exact_block, Some((128, 1, 1))); + assert_eq!(facts.dynamic_shared_bytes, 0); + assert!( + module + .$prepare(LaunchConfig3D::auto_shared((3, 1, 1), (64, 2, 1))) + .is_err() + ); + // SAFETY: complete, immutable input and disjoint output tiles + // outlive execution. Preparation enforces exact geometry. + unsafe { + module.$kernel( + &stream, + &prepared, + device_input.cu_deviceptr() as *const i32, + device_output.cu_deviceptr() as *mut i32, + )?; + } + }}; + } + if items == 1 { + launch!(prepare_one, one); + } else { + launch!(prepare_four, four); + } + assert_eq!( + device_output.to_host_vec(&stream)?, + input.iter().map(|value| value + 7).collect::>() + ); + println!("PASS native library: items={items}, {} values", input.len()); + } + Ok(()) +} + +// Artifact-only smoke lanes call this before creating any CUDA context. Read +// the executable's actual bundle, including its launch facts and debug policy. +fn check_artifact( + target: &str, + output: &std::path::Path, + full_debug: bool, +) -> Result<(), Box> { + let bundles = artifact_bundles_from_current_exe()?; + let [bundle] = bundles.as_slice() else { + return Err("expected exactly one embedded device bundle".into()); + }; + assert_eq!(bundle.target, target); + for symbol in ["one", "four"] { + let facts = bundle.entry(symbol).unwrap().launch_facts.unwrap(); + assert_eq!(facts.exact_block, Some((128, 1, 1))); + assert_eq!(facts.dynamic_shared_bytes, 0); + } + if full_debug { + assert_eq!( + bundle.compile_options.debug_policy(), + ArtifactDebugPolicy::Full + ); + } + let cubin = bundle + .payload(ArtifactPayloadKind::Cubin) + .ok_or("missing embedded CUBIN")?; + assert!(cubin.starts_with(b"\x7fELF")); + std::fs::write(output, cubin)?; + println!("PASS embedded CUBIN: target={target}, kernels=one,four"); + Ok(()) +} + +fn main() -> Result<(), Box> { + let args: Vec<_> = std::env::args_os().skip(1).collect(); + if args.first().is_some_and(|arg| arg == "--check-artifact") { + if !(args.len() == 3 || (args.len() == 4 && args[3] == "--full-debug")) { + return Err("expected --check-artifact TARGET OUTPUT [--full-debug]".into()); + } + return check_artifact( + args[1].to_str().ok_or("invalid target")?, + std::path::Path::new(&args[2]), + args.len() == 4, + ); + } + if !args.is_empty() { + return Err("unexpected fixture argument".into()); + } + verify() +} + +#[test] +fn native_provider_executes() { + verify().unwrap(); +} diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/ne_bytes_transmute/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/ne_bytes_transmute/Cargo.lock index 4bd0371e5b..bb5673bf98 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/ne_bytes_transmute/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/ne_bytes_transmute/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/nested_index_assignment/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/nested_index_assignment/Cargo.lock index c52786e005..500c8dba4b 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/nested_index_assignment/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/nested_index_assignment/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/numeric_stress/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/numeric_stress/Cargo.lock index bfd2fa4115..1ff585db78 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/numeric_stress/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/numeric_stress/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/nvls_all_reduce/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/nvls_all_reduce/Cargo.lock index 781a8d3f06..111da91854 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/nvls_all_reduce/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/nvls_all_reduce/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/option_ref_transmute/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/option_ref_transmute/Cargo.lock index b5af8f30b4..685341f7c8 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/option_ref_transmute/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/option_ref_transmute/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ dependencies = [ [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/option_ref_unwrap_or/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/option_ref_unwrap_or/Cargo.lock index f5893ba8a7..fdec78306f 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/option_ref_unwrap_or/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/option_ref_unwrap_or/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ dependencies = [ [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/option_unwrap_trap/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/option_unwrap_trap/Cargo.lock index 85a0cbe346..49ffc7c666 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/option_unwrap_trap/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/option_unwrap_trap/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ dependencies = [ [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/ord_cmp/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/ord_cmp/Cargo.lock index b80b1f9dcb..1794ead8c3 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/ord_cmp/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/ord_cmp/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -418,8 +420,6 @@ dependencies = [ [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/packed_aggregate_abi/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/packed_aggregate_abi/Cargo.lock index f4c8348b24..32393adb76 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/packed_aggregate_abi/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/packed_aggregate_abi/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/packed_atomic_add/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/packed_atomic_add/Cargo.lock index 5c9aae69d3..bdc22a01ca 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/packed_atomic_add/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/packed_atomic_add/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/padded_constants/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/padded_constants/Cargo.lock index 7621003859..e29c18c0d7 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/padded_constants/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/padded_constants/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/partial_warp_reduce/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/partial_warp_reduce/Cargo.lock index 1dd0ec55a8..691774ca43 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/partial_warp_reduce/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/partial_warp_reduce/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/pinned_overlap/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/pinned_overlap/Cargo.lock index f00ea7f41c..2a6f4ebadf 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/pinned_overlap/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/pinned_overlap/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/place_read_fallbacks/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/place_read_fallbacks/Cargo.lock index 63206cdbab..ee1da38967 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/place_read_fallbacks/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/place_read_fallbacks/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/policy_config/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/policy_config/Cargo.lock index ac860e426a..32ba8e47c9 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/policy_config/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/policy_config/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/primitive_stress/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/primitive_stress/Cargo.lock index f07ca73faa..c3687e6992 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/primitive_stress/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/primitive_stress/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/printf/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/printf/Cargo.lock index cfaa742b4f..9be9c4e2b9 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/printf/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/printf/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/projected_place_read/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/projected_place_read/Cargo.lock index 30bc83e4e5..85d2eb6055 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/projected_place_read/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/projected_place_read/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/proof_carrying_views/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/proof_carrying_views/Cargo.lock index 42b08210f7..740bf93b63 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/proof_carrying_views/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/proof_carrying_views/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_copy/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_copy/Cargo.lock index de5ac4ae48..457d646457 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_copy/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_copy/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_offset_from/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_offset_from/Cargo.lock index 0ec7cfb44f..0a6d23eafc 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_offset_from/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_offset_from/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_without_provenance/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_without_provenance/Cargo.lock index fa5df66742..b7ad3a320b 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_without_provenance/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/ptr_without_provenance/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/reborrow/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/reborrow/Cargo.lock index 8d7de86367..777b32e356 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/reborrow/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/reborrow/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_f32/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_f32/Cargo.lock index a74777042e..ecc7d5cfcb 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_f32/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_f32/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_minmax/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_minmax/Cargo.lock index bbb321da29..360c5f0cf4 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_minmax/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_minmax/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_sum/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_sum/Cargo.lock index 3495a7289a..f1d33eea28 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_sum/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/redux_sum/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/ref_index_projections/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/ref_index_projections/Cargo.lock index 58a388e07a..e1e369b9fd 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/ref_index_projections/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/ref_index_projections/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/ref_operand_mul/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/ref_operand_mul/Cargo.lock index ec2404f932..fb27a0a074 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/ref_operand_mul/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/ref_operand_mul/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_align_block_args/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_align_block_args/Cargo.lock index cc0078e643..4b1e8e5b1d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_align_block_args/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_align_block_args/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_transparent_abi/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_transparent_abi/Cargo.lock index fa4c02c424..eac149c159 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_transparent_abi/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_transparent_abi/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_u32_enum_stride/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_u32_enum_stride/Cargo.lock index 6af97378f8..92352ccff2 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_u32_enum_stride/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/repr_u32_enum_stride/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/row_width_slice/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/row_width_slice/Cargo.lock index 85b2f5f477..d61a249ef0 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/row_width_slice/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/row_width_slice/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/rustlantis-smoke/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/rustlantis-smoke/Cargo.lock index 67e55271c0..ee4e53c6bf 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/rustlantis-smoke/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/rustlantis-smoke/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -413,8 +415,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/scoped_atomic_load_store/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/scoped_atomic_load_store/Cargo.lock index 013a3379fb..65a5e90c73 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/scoped_atomic_load_store/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/scoped_atomic_load_store/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/select_unpredictable/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/select_unpredictable/Cargo.lock index 86eafa2b6e..61d5523aa5 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/select_unpredictable/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/select_unpredictable/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/set_discriminant/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/set_discriminant/Cargo.lock index bbd354e38b..15547743cc 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/set_discriminant/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/set_discriminant/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/set_discriminant_niche/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/set_discriminant_niche/Cargo.lock index e157fea2ac..9c4aad196a 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/set_discriminant_niche/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/set_discriminant_niche/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_debug/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_debug/Cargo.lock index 3195c5052d..a3d81d06a6 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_debug/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_debug/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_memory_helper/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_memory_helper/Cargo.lock index e72dcc60f5..f913278688 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_memory_helper/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_memory_helper/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_ptr_api/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_ptr_api/Cargo.lock index 0df03ea524..364066dedb 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_ptr_api/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_ptr_api/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_ptr_transmute/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_ptr_transmute/Cargo.lock index 42647acf94..d20d18ca5d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_ptr_transmute/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_ptr_transmute/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_slice_unsize/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_slice_unsize/Cargo.lock index 7517a55603..8d612648e3 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_slice_unsize/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_slice_unsize/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_stage_select/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_stage_select/Cargo.lock index 98f07a9a47..9328a3f16d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_stage_select/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/shared_stage_select/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/sharedmem/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/sharedmem/Cargo.lock index e60e6cf190..c0317e0e93 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/sharedmem/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/sharedmem/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/shuffle_64/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/shuffle_64/Cargo.lock index 46b3b08f05..e081aff204 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/shuffle_64/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/shuffle_64/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_from_raw_parts_cast/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_from_raw_parts_cast/Cargo.lock index 52b8d52887..9fe56b9159 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_from_raw_parts_cast/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_from_raw_parts_cast/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_get_mut/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_get_mut/Cargo.lock index 20152e80f8..fa3c74943d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_get_mut/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_get_mut/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_index_bounds_check/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_index_bounds_check/Cargo.lock index e28e9d5ddf..64a4e5efc5 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_index_bounds_check/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_index_bounds_check/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_iterators/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_iterators/Cargo.lock index 0ac8bde6f2..0fd0b20fcf 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_iterators/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_iterators/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_reslice/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_reslice/Cargo.lock index fe2e92d2b2..ee998c6b26 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_reslice/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/slice_reslice/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/small_type_ffi_test/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/small_type_ffi_test/Cargo.lock index d446e6625f..bdab0bf44d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/small_type_ffi_test/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/small_type_ffi_test/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/sparse_mma_fp8/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/sparse_mma_fp8/Cargo.lock index c781eb7524..ed419c41fb 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/sparse_mma_fp8/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/sparse_mma_fp8/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/sparse_mma_ordered_float/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/sparse_mma_ordered_float/Cargo.lock index 03d67c5e3a..bc1190582a 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/sparse_mma_ordered_float/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/sparse_mma_ordered_float/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/split_at_mut/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/split_at_mut/Cargo.lock index 4324edf483..f8378aaad2 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/split_at_mut/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/split_at_mut/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/standalone_device_fn/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/standalone_device_fn/Cargo.lock index bbf2681720..9d75674aee 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/standalone_device_fn/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/standalone_device_fn/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/static_slice_addend/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/static_slice_addend/Cargo.lock index 15f0537070..518447f41c 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/static_slice_addend/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/static_slice_addend/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/static_slice_unsize/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/static_slice_unsize/Cargo.lock index c074858de1..011bdec3db 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/static_slice_unsize/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/static_slice_unsize/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/step_by/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/step_by/Cargo.lock index 84cba98cab..82274706ed 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/step_by/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/step_by/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/struct_constant_provenance/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/struct_constant_provenance/Cargo.lock index 690c24a327..b2646519c1 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/struct_constant_provenance/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/struct_constant_provenance/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/struct_field_layout/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/struct_field_layout/Cargo.lock index fe53acdb76..9228db6288 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/struct_field_layout/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/struct_field_layout/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/subslice_projection/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/subslice_projection/Cargo.lock index 7ef72e0da5..3d5ed94fff 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/subslice_projection/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/subslice_projection/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/switchint_128bit/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/switchint_128bit/Cargo.lock index 03811356e6..3409bb8bf5 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/switchint_128bit/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/switchint_128bit/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/swizzle_smem/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/swizzle_smem/Cargo.lock index f152cecc4c..1065556823 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/swizzle_smem/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/swizzle_smem/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/tcgen05/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/tcgen05/Cargo.lock index 8c6054ce23..d5a697d4f0 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/tcgen05/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/tcgen05/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/tcgen05_matmul/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/tcgen05_matmul/Cargo.lock index 651ffe661e..91817e2b94 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/tcgen05_matmul/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/tcgen05_matmul/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/thread_runs/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/thread_runs/Cargo.lock index 75c208fc87..80c7c208fe 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/thread_runs/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/thread_runs/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/tiled_gemm/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/tiled_gemm/Cargo.lock index cf9576c158..ea192cf476 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/tiled_gemm/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/tiled_gemm/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/tilelib_relu/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/tilelib_relu/Cargo.lock index c86e4ed6e2..51539970e9 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/tilelib_relu/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/tilelib_relu/Cargo.lock @@ -173,6 +173,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -394,8 +396,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/tma_copy/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/tma_copy/Cargo.lock index 5a9c81ad8f..e9fe80ffb2 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/tma_copy/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/tma_copy/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/tma_multicast/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/tma_multicast/Cargo.lock index 3977ab9ddc..2d3312c039 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/tma_multicast/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/tma_multicast/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/toolchain_pairing_smoke/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/toolchain_pairing_smoke/Cargo.lock index 29f8b4dec6..2c2ef52787 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/toolchain_pairing_smoke/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/toolchain_pairing_smoke/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/transmute_scalar_struct/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/transmute_scalar_struct/Cargo.lock index 0e2998f8d5..5cf668630d 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/transmute_scalar_struct/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/transmute_scalar_struct/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_array_provenance/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_array_provenance/Cargo.lock index de10cae507..0a5cf329b9 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_array_provenance/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_array_provenance/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_constant_provenance/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_constant_provenance/Cargo.lock index 48212e960c..c7a456a6b5 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_constant_provenance/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_constant_provenance/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_field_lookup/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_field_lookup/Cargo.lock index 47aad8a282..56dd361a29 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_field_lookup/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_field_lookup/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_return/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_return/Cargo.lock index 2ac68321ee..ced63da828 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_return/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/tuple_return/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/unaligned_memory/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/unaligned_memory/Cargo.lock index 4affc8b321..e4aa5e5a76 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/unaligned_memory/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/unaligned_memory/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/unchecked_indexing/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/unchecked_indexing/Cargo.lock index 53f368594d..ce39447534 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/unchecked_indexing/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/unchecked_indexing/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/uninit_const/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/uninit_const/Cargo.lock index 1517384a3b..b4f9e727d2 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/uninit_const/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/uninit_const/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/union_aggregate/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/union_aggregate/Cargo.lock index c2a4fec2d7..703744daa8 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/union_aggregate/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/union_aggregate/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/unroll_bounds_check/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/unroll_bounds_check/Cargo.lock index 71e089c287..4a1b8db915 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/unroll_bounds_check/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/unroll_bounds_check/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/unroll_smoke/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/unroll_smoke/Cargo.lock index 780f6f3e9d..6c80e4c79f 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/unroll_smoke/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/unroll_smoke/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/vecadd/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/vecadd/Cargo.lock index 9d76a571bd..0dc3433021 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/vecadd/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/vecadd/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/vectorization/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/vectorization/Cargo.lock index 6cb5e3d2a9..e59553bfcf 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/vectorization/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/vectorization/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/volatile_memory/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/volatile_memory/Cargo.lock index 51689b847a..5486ae5283 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/volatile_memory/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/volatile_memory/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/warp_reduce/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/warp_reduce/Cargo.lock index 49805d2fe3..76c703bbf0 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/warp_reduce/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/warp_reduce/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/warp_sums/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/warp_sums/Cargo.lock index 1b446984c3..f343de5813 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/warp_sums/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/warp_sums/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/wgmma/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/wgmma/Cargo.lock index 11fbfa1d79..9ba13eb207 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/wgmma/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/wgmma/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/examples/wgmma_mma_bf16/Cargo.lock b/cuda-oxide/crates/rustc-codegen-cuda/examples/wgmma_mma_bf16/Cargo.lock index e5e504178f..c59c57a3ef 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/examples/wgmma_mma_bf16/Cargo.lock +++ b/cuda-oxide/crates/rustc-codegen-cuda/examples/wgmma_mma_bf16/Cargo.lock @@ -188,6 +188,8 @@ dependencies = [ "proc-macro2", "quote", "reserved-oxide-symbols", + "serde", + "serde_json", "syn", ] @@ -409,8 +411,6 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object", ] diff --git a/cuda-oxide/crates/rustc-codegen-cuda/src/collector.rs b/cuda-oxide/crates/rustc-codegen-cuda/src/collector.rs index 97e5b7c45a..c813181091 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/src/collector.rs +++ b/cuda-oxide/crates/rustc-codegen-cuda/src/collector.rs @@ -354,27 +354,20 @@ pub struct DeviceExternDecl { /// NVVM attributes for device extern declarations. /// -/// NOTE: These attributes are currently **not emitted** to the LLVM IR output. -/// When linking LTOIR via nvJitLink, the external library's LTOIR already contains -/// proper attributes (convergent, nounwind, memory, etc.) on the function DEFINITIONS. -/// nvJitLink uses the definition's attributes during LTO, making attributes on our -/// declarations redundant. -/// -/// The `#[convergent]`, `#[pure]`, and `#[readonly]` Rust attributes are still parsed -/// but their values are not used in code generation. This struct is retained for -/// potential future use or debugging. +/// Convergence is emitted on the declaration before libNVVM optimization. +/// Memory-effect annotations remain inactive; they are not inferred from external +/// definitions that become available only during LTO. #[derive(Debug, Clone, Default)] pub struct DeviceExternAttrs { - /// Function is convergent (all threads must execute together). - /// NOTE: Not currently emitted - external LTOIR has proper convergent attrs. + /// Function has convergence requirements for its participating threads. pub is_convergent: bool, /// Function is pure (no side effects, result depends only on inputs). - /// NOTE: Not currently emitted - external LTOIR has proper memory attrs. + /// Inactive for Rust source annotations. pub is_pure: bool, /// Function is read-only (only reads memory, doesn't write). - /// NOTE: Not currently emitted - external LTOIR has proper memory attrs. + /// Inactive for Rust source annotations. pub is_readonly: bool, } @@ -384,6 +377,10 @@ pub struct DeviceExternAttrs { /// declarations (for FFI with external LTOIR). #[derive(Debug)] pub struct CollectionResult<'tcx> { + /// Calls to the exact compiler library marker, before body deduplication. + pub library_calls: Vec>, + /// Every resolved edge, retaining all kernel contexts of shared helpers. + pub call_edges: Vec<(Instance<'tcx>, Instance<'tcx>)>, /// Functions to compile (kernels and device helpers with MIR bodies). pub functions: Vec>, @@ -394,8 +391,8 @@ pub struct CollectionResult<'tcx> { /// /// This is true for a `#[cuda_module]` containing a generic kernel and /// for a concrete specialization of a generic kernel imported from a - /// dependency. Cubin materialization must reject this case until it can - /// reproduce the same cross-crate linking semantics. + /// dependency. Materialized loading instead requires one complete native + /// artifact; this existing marker remains the generic-module classification. pub requires_ptx_bundle_merge: bool, /// `#[tile_export]` descriptions read from this crate's metadata @@ -815,7 +812,10 @@ fn rust_alloc_shim_name(fn_path: &str) -> Option<&str> { /// fat-pointer string constants are inspected; everything else returns /// `None`. Evaluation failures (e.g. a constant in still-generic MIR) /// also return `None`, which simply means "no message found". -fn const_str_text<'tcx>(tcx: TyCtxt<'tcx>, constant: &ConstOperand<'tcx>) -> Option { +pub(crate) fn const_str_text<'tcx>( + tcx: TyCtxt<'tcx>, + constant: &ConstOperand<'tcx>, +) -> Option { let ty = constant.const_.ty(); let TyKind::Ref(_, pointee, _) = ty.kind() else { return None; @@ -1121,9 +1121,8 @@ pub fn collect_device_functions<'tcx>( // A downstream monomorphization of a generic kernel may be // present even when the defining crate's private module - // marker is not. Such modules use the all-PTX-bundles loader, - // so strict ahead-of-time cubin materialization cannot safely - // compile only this crate's artifact. + // marker is not. Keep its generic-module classification even + // when only the consuming crate has concrete kernel entries. requires_ptx_bundle_merge |= tcx .generics_of(instance.def_id()) .requires_monomorphization(tcx); @@ -1281,6 +1280,9 @@ struct DeviceCollector<'tcx> { /// once per program — the message is procedural advice about the /// kernel-launch contract, not anything per-call. warned_dynamic_shared_array: bool, + library_defs: HashSet, + library_calls: Vec>, + call_edges: Vec<(Instance<'tcx>, Instance<'tcx>)>, /// Print progress to stderr. verbose: bool, } @@ -1297,6 +1299,9 @@ impl<'tcx> DeviceCollector<'tcx> { device_externs: Vec::new(), seen_device_externs: HashSet::new(), warned_dynamic_shared_array: false, + library_defs: crate::library::marker_definitions(tcx), + library_calls: Vec::new(), + call_edges: Vec::new(), verbose, } } @@ -1459,6 +1464,8 @@ impl<'tcx> DeviceCollector<'tcx> { } CollectionResult { + library_calls: self.library_calls, + call_edges: self.call_edges, functions: self.result, device_externs: self.device_externs, requires_ptx_bundle_merge: false, @@ -1509,7 +1516,12 @@ impl<'tcx> DeviceCollector<'tcx> { .next() .is_some() }; - attrs.is_convergent = check("convergent"); + attrs.is_convergent = rustc_attr_ir::find_attr!( + self.tcx, def_id, Doc(doc) + if doc.aliases.contains_key(&Symbol::intern( + reserved_oxide_symbols::DEVICE_EXTERN_CONVERGENT_MARKER + )) + ); attrs.is_pure = check("pure"); attrs.is_readonly = check("readonly"); @@ -1594,6 +1606,7 @@ impl<'tcx> DeviceCollector<'tcx> { return; } + self.call_edges.push((caller.instance, drop_instance)); let mangled = self.tcx.symbol_name(drop_instance).name.to_string(); if self.seen.contains(&mangled) { return; @@ -1890,6 +1903,17 @@ impl<'tcx> DeviceCollector<'tcx> { return; }; + // Preserve edges before deduplicating bodies: the same helper can be + // reached from several kernels with distinct resource requirements. + self.call_edges.push((caller.instance, resolved)); + if self.library_defs.contains(&resolved.def_id()) { + self.library_calls.push(crate::library::LibraryCall { + instance: resolved, + span: call_span, + }); + return; + } + // Skip already-seen monomorphizations (use mangled name as unique key) let mangled = self.tcx.symbol_name(resolved).name.to_string(); if self.seen.contains(&mangled) { @@ -2121,6 +2145,13 @@ impl<'tcx> DeviceCollector<'tcx> { _ => return, }; + if self.library_defs.contains(&instance.def_id()) { + self.tcx.dcx().span_fatal( + call_span, + "the native library marker requires a direct call; pass a wrapper helper instead", + ); + } + self.call_edges.push((caller.instance, instance)); let target = self.tcx.def_path_str(instance.def_id()); let crate_name = self.tcx.crate_name(instance.def_id().krate); if self.is_generated_intrinsic_placeholder_or_report_mismatch( diff --git a/cuda-oxide/crates/rustc-codegen-cuda/src/device_codegen.rs b/cuda-oxide/crates/rustc-codegen-cuda/src/device_codegen.rs index 941dd11d10..ba7ae452b8 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/src/device_codegen.rs +++ b/cuda-oxide/crates/rustc-codegen-cuda/src/device_codegen.rs @@ -326,6 +326,8 @@ pub struct DeviceCodegenResult { pub debug_kind: llvm_export::export::DebugKind, /// Source launch bounds for kernel entries, keyed by exported kernel name. pub kernel_launch_bounds: BTreeMap, + /// Finalized resource requirements for each concrete kernel export. + pub kernel_launch_facts: BTreeMap, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -914,6 +916,7 @@ pub fn generate_device_code<'tcx>( tcx: TyCtxt<'tcx>, functions: &[CollectedFunction<'tcx>], device_externs: &[DeviceExternDecl], + libraries: &crate::library::FinalizedLibraries<'tcx>, config: &DeviceCodegenConfig, ) -> Result { use rustc_public::rustc_internal; @@ -959,7 +962,7 @@ pub fn generate_device_code<'tcx>( // Convert device externs to mir-importer format // We extract signature info from rustc here since we have access to TyCtxt - let stable_device_externs: Vec = device_externs + let mut stable_device_externs: Vec = device_externs .iter() .map(|decl| { // Get function signature from rustc @@ -1019,6 +1022,8 @@ pub fn generate_device_code<'tcx>( }) .collect::>()?; + stable_device_externs.extend(libraries.declarations.clone()); + let output_dir = config.output_dir.clone(); let output_name = config.output_name.clone(); let verbose = config.verbose; @@ -1276,11 +1281,21 @@ pub fn generate_device_code<'tcx>( // Run the cuda-oxide pipeline! // Rust MIR → `dialect-mir` → mem2reg → unroll → LLVM dialect → LLVM IR → PTX. // Device externs are emitted as `declare` statements in LLVM IR - mir_importer::run_pipeline( + let library_calls = libraries + .calls + .iter() + .map(|(instance, plan)| { + let instance: rustc_public::mir::mono::Instance = rustc_internal::stable(*instance); + (instance.mangled_name().to_string(), plan.clone()) + }) + .collect(); + mir_importer::run_pipeline_with_libraries( &stable_functions, &stable_device_externs, &pipeline_config, known_defs, + library_calls, + &libraries.roots, ) }); @@ -1325,6 +1340,7 @@ pub fn generate_device_code<'tcx>( allow_fma_contraction: compilation_result.allow_fma_contraction, debug_kind, kernel_launch_bounds: compilation_result.kernel_launch_bounds, + kernel_launch_facts: compilation_result.kernel_launch_facts, }) } Err(pipeline_err) => Err(DeviceCodegenError::PtxGeneration(format!( @@ -1466,6 +1482,7 @@ mod tests { target: "sm_90".to_string(), allow_fma_contraction: false, kernel_launch_bounds: BTreeMap::new(), + kernel_launch_facts: BTreeMap::new(), }; let artifact = read_compilation_artifact(&result).unwrap().unwrap(); @@ -1493,6 +1510,7 @@ mod tests { target: "sm_90".to_string(), allow_fma_contraction: true, kernel_launch_bounds: BTreeMap::new(), + kernel_launch_facts: BTreeMap::new(), }; let artifact = read_compilation_artifact(&result).unwrap().unwrap(); diff --git a/cuda-oxide/crates/rustc-codegen-cuda/src/lib.rs b/cuda-oxide/crates/rustc-codegen-cuda/src/lib.rs index 600b298617..e078b63de0 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/src/lib.rs +++ b/cuda-oxide/crates/rustc-codegen-cuda/src/lib.rs @@ -329,6 +329,7 @@ extern crate rustc_codegen_llvm; mod collector; mod device_codegen; mod generated_intrinsics; +mod library; mod materialize; use rustc_codegen_ssa::traits::CodegenBackend; @@ -610,7 +611,7 @@ impl CodegenBackend for CudaCodegenBackend { // Step 2: If device code exists, compile via cuda-oxide let _device_result = if has_device_code { - let materialization_request = + let mut materialization_request = materialize::request_from_env().unwrap_or_else(|error| { tcx.dcx().fatal(format!( "[rustc_codegen_cuda] Invalid cubin materialization request: {error}" @@ -627,10 +628,36 @@ impl CodegenBackend for CudaCodegenBackend { self.config.verbose, ); + if !collection_result.library_calls.is_empty() && materialization_request.is_none() + { + tcx.dcx().fatal( + "native library calls require `cargo oxide build --materialize-cubin`", + ); + } + let mut libraries = + library::finalize(tcx, &collection_result).unwrap_or_else(|error| { + tcx.dcx().fatal(format!("native device library: {error}")) + }); + if self.config.verbose { + for (kernel, plan) in &libraries.roots { + eprintln!( + "[library] {kernel}: exact block {:?}, scratch {} bytes aligned {}", + plan.exact_block, + plan.dynamic_shared_bytes, + plan.dynamic_shared_alignment + ); + } + } + // The provider returns owned bytes. No consumer-created artifact + // list or path is needed, and output-path checks still apply to + // the file inputs received from cargo-oxide. + if let Some(request) = &mut materialization_request { + request.add_library_inputs(std::mem::take(&mut libraries.inputs)); + } + materialize::validate_collection( - materialization_request, + materialization_request.as_ref(), !collection_result.device_externs.is_empty(), - collection_result.requires_ptx_bundle_merge, ) .unwrap_or_else(|error| { tcx.dcx().fatal(format!( @@ -664,6 +691,16 @@ impl CodegenBackend for CudaCodegenBackend { dump_mir_dialect: self.config.dump_mir_dialect, dump_llvm_dialect: self.config.dump_llvm_dialect, }; + materialize::validate_output_paths( + materialization_request.as_ref(), + &device_config.output_dir, + &device_config.output_name, + ) + .unwrap_or_else(|error| { + tcx.dcx().fatal(format!( + "[rustc_codegen_cuda] Cannot write device artifacts: {error}" + )) + }); // Run the cuda-oxide pipeline, catching backend panics and // re-emitting them as a cuda-oxide diagnostic. A panic @@ -700,6 +737,7 @@ impl CodegenBackend for CudaCodegenBackend { tcx, device_functions, &collection_result.device_externs, + &libraries, &device_config, ) })); @@ -953,10 +991,11 @@ fn write_device_artifact_object( } else { oxide_artifacts::ArtifactEntryKind::DeviceFunction }; - spec = spec.with_entry(oxide_artifacts::ArtifactEntrySpec::new( - &function.export_name, - kind, - )); + let mut entry = oxide_artifacts::ArtifactEntrySpec::new(&function.export_name, kind); + if let Some(facts) = result.kernel_launch_facts.get(&function.export_name) { + entry = entry.with_launch_facts(*facts); + } + spec = spec.with_entry(entry); } let blob = oxide_artifacts::build_artifact_blob(&spec)?; diff --git a/cuda-oxide/crates/rustc-codegen-cuda/src/library.rs b/cuda-oxide/crates/rustc-codegen-cuda/src/library.rs new file mode 100644 index 0000000000..55bd820ac8 --- /dev/null +++ b/cuda-oxide/crates/rustc-codegen-cuda/src/library.rs @@ -0,0 +1,688 @@ +// SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +//! Resolve typed library markers and finalize one batch per native provider. + +use std::collections::{BTreeMap, HashMap, HashSet}; +use std::io::{Read, Write}; +use std::path::PathBuf; +use std::process::{Command, Stdio}; + +use oxide_artifacts::KernelLaunchFacts; +use rustc_hir::def_id::{CRATE_DEF_INDEX, DefId}; +use rustc_middle::mir::{Operand, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind}; +use rustc_middle::ty::consts::ConstExt; +use rustc_middle::ty::{Instance, Ty, TyCtxt, TyKind, TypingEnv}; +use rustc_span::Span; +use serde::{Deserialize, Serialize}; + +use crate::collector::CollectionResult; + +const MAX_HEADER: usize = 1024 * 1024; +const MAX_LTO: usize = 256 * 1024 * 1024; + +#[derive(Debug)] +pub(crate) struct LibraryCall<'tcx> { + pub instance: Instance<'tcx>, + pub span: Span, +} + +/// Resolve definitions through the actual dependency module, then compare DefIds +/// at call sites. A user function with the same spelling is an ordinary function. +pub(crate) fn marker_definitions(tcx: TyCtxt<'_>) -> HashSet { + let mut definitions = HashSet::new(); + for &krate in tcx.crates(()) { + if tcx.crate_name(krate).as_str() != "cuda_device" { + continue; + } + let root = DefId { + krate, + index: CRATE_DEF_INDEX, + }; + for module in tcx.module_children(root) { + if module.ident.name.as_str() != "library" { + continue; + } + let Some(module) = module.res.opt_def_id() else { + continue; + }; + for item in tcx.module_children(module) { + if item.ident.name.as_str() == reserved_oxide_symbols::LIBRARY_CALL_V1 + && let Some(def) = item.res.opt_def_id() + { + definitions.insert(def); + } + } + } + } + definitions +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct Registration { + version: u32, + provider: String, + executable: PathBuf, + operation: String, + algorithm: String, +} + +#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)] +#[serde( + tag = "kind", + content = "bits", + rename_all = "snake_case", + deny_unknown_fields +)] +enum Scalar { + Signed(u16), + Unsigned(u16), + Float(u16), +} + +#[derive(Clone, Debug, Deserialize, PartialEq, Eq)] +#[serde( + tag = "kind", + content = "scalar", + rename_all = "snake_case", + deny_unknown_fields +)] +enum Argument { + ConstPointer(Scalar), + MutPointer(Scalar), + Value(Scalar), +} + +#[derive(Debug, Serialize)] +struct BatchRequest<'a> { + version: u32, + target: &'a str, + cuda_root: PathBuf, + requests: &'a [Request], +} + +#[derive(Clone, Debug, Serialize, PartialEq, Eq, Hash)] +struct Request { + operation: String, + algorithm: String, + dtype: Scalar, + block: [u32; 3], + items_per_thread: u32, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct Layout { + size: u64, + alignment: u64, +} + +impl Layout { + fn checked(&self) -> Result<(u32, u32), String> { + let size = u32::try_from(self.size).map_err(|_| "library layout exceeds u32")?; + let align = u32::try_from(self.alignment).map_err(|_| "library alignment exceeds u32")?; + if !align.is_power_of_two() { + return Err("library alignment must be a nonzero power of two".into()); + } + Ok((size, align)) + } +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct Specialization { + request_index: u32, + identity: [u8; 32], + symbol: String, + arguments: Vec, + cub_layout: Layout, + scratch: Layout, + scratch_free: bool, + mutates_payload: bool, +} + +#[derive(Debug, Deserialize)] +#[serde(deny_unknown_fields)] +struct BatchResponse { + version: u32, + batch_identity: [u8; 32], + specializations: Vec, +} + +#[derive(Default)] +pub(crate) struct FinalizedLibraries<'tcx> { + pub calls: Vec<(Instance<'tcx>, mir_importer::LibraryCallPlan)>, + pub declarations: Vec, + pub inputs: Vec<(String, Vec)>, + pub roots: BTreeMap, +} + +fn scalar(ty: Ty<'_>) -> Result { + use rustc_middle::ty::{FloatTy, IntTy, UintTy}; + match ty.kind() { + TyKind::Int(kind) => match kind { + IntTy::I8 => Ok(Scalar::Signed(8)), + IntTy::I16 => Ok(Scalar::Signed(16)), + IntTy::I32 => Ok(Scalar::Signed(32)), + IntTy::I64 => Ok(Scalar::Signed(64)), + _ => Err(format!("unsupported library scalar `{ty}`")), + }, + TyKind::Uint(kind) => match kind { + UintTy::U8 => Ok(Scalar::Unsigned(8)), + UintTy::U16 => Ok(Scalar::Unsigned(16)), + UintTy::U32 => Ok(Scalar::Unsigned(32)), + UintTy::U64 => Ok(Scalar::Unsigned(64)), + _ => Err(format!("unsupported library scalar `{ty}`")), + }, + TyKind::Float(FloatTy::F16) => Ok(Scalar::Float(16)), + TyKind::Float(FloatTy::F32) => Ok(Scalar::Float(32)), + TyKind::Float(FloatTy::F64) => Ok(Scalar::Float(64)), + _ => Err(format!( + "unsupported library scalar `{ty}`; use a fixed-width numeric scalar" + )), + } +} + +fn argument(ty: Ty<'_>) -> Result { + match ty.kind() { + TyKind::RawPtr(pointee, mutability) => Ok(if mutability.is_mut() { + Argument::MutPointer(scalar(*pointee)?) + } else { + Argument::ConstPointer(scalar(*pointee)?) + }), + _ => Ok(Argument::Value(scalar(ty)?)), + } +} + +fn read_registration<'tcx>(tcx: TyCtxt<'tcx>, witness: Ty<'tcx>) -> Result { + let TyKind::FnDef(def, args) = witness.kind() else { + return Err( + "library registration must be a function item, not a closure or function pointer" + .into(), + ); + }; + let args = args + .no_bound_vars() + .ok_or("registration has unresolved bound arguments")?; + let instance = Instance::try_resolve(tcx, TypingEnv::fully_monomorphized(), *def, args) + .map_err(|_| "cannot resolve library registration")? + .ok_or("cannot resolve library registration")?; + let body = tcx.instance_mir(instance.def); + // Deliberately accept only the constant getter contract. Do not evaluate + // arbitrary target code or search a more complicated body for a JSON string. + if body.basic_blocks.len() != 1 { + return Err("registration getter must return one constant string".into()); + } + if !matches!( + body.basic_blocks.iter().next().unwrap().terminator().kind, + TerminatorKind::Return + ) { + return Err("registration getter must return one constant string".into()); + } + let mut text = None; + for statement in &body.basic_blocks.iter().next().unwrap().statements { + if let StatementKind::Assign(assign) = &statement.kind { + let (place, value) = &**assign; + if place.as_local() != Some(RETURN_PLACE) { + return Err("registration getter must return one constant string".into()); + } + let Rvalue::Use(Operand::Constant(constant), _) = value else { + return Err("registration getter must return one constant string".into()); + }; + if text.is_some() { + return Err("registration getter writes its result more than once".into()); + } + text = crate::collector::const_str_text(tcx, constant); + } + } + let text = text.ok_or("registration getter must return one constant UTF-8 string")?; + let registration: Registration = + serde_json::from_str(&text).map_err(|e| format!("invalid library registration: {e}"))?; + if registration.version != 1 + || registration.provider.is_empty() + || !registration.executable.is_absolute() + { + return Err("library registration requires version 1, a provider name, and an absolute executable path".into()); + } + Ok(registration) +} + +fn decode_response( + bytes: &[u8], + expected_count: usize, +) -> Result<(BatchResponse, Vec), String> { + if bytes.len() < 24 || &bytes[..8] != b"OXDLIB01" { + return Err("invalid or truncated library response frame".into()); + } + let header_len = u64::from_le_bytes(bytes[8..16].try_into().unwrap()); + let lto_len = u64::from_le_bytes(bytes[16..24].try_into().unwrap()); + if header_len > MAX_HEADER as u64 || lto_len == 0 || lto_len > MAX_LTO as u64 { + return Err("library response length is out of bounds".into()); + } + let header_end = 24 + header_len as usize; + if bytes.len() != header_end + lto_len as usize { + return Err("library response is truncated or has trailing bytes".into()); + } + let response: BatchResponse = serde_json::from_slice(&bytes[24..header_end]) + .map_err(|e| format!("invalid library response JSON: {e}"))?; + if response.version != 1 || response.specializations.len() != expected_count { + return Err( + "library response version or specialization count does not match request".into(), + ); + } + let mut symbols = HashSet::new(); + let mut identities = HashSet::new(); + for (index, spec) in response.specializations.iter().enumerate() { + if usize::try_from(spec.request_index).ok() != Some(index) + || !symbols.insert(&spec.symbol) + || !identities.insert(spec.identity) + || spec.symbol.is_empty() + || !spec + .symbol + .bytes() + .enumerate() + .all(|(i, b)| b == b'_' || b.is_ascii_alphabetic() || (i > 0 && b.is_ascii_digit())) + { + return Err( + "library response has an invalid index, symbol, or duplicate identity".into(), + ); + } + spec.cub_layout.checked()?; + let (size, _) = spec.scratch.checked()?; + if spec.scratch_free != (size == 0) { + return Err("library scratch-free flag disagrees with its layout".into()); + } + if !matches!( + spec.arguments.first(), + Some(Argument::ConstPointer(_) | Argument::MutPointer(_)) + ) || !matches!(spec.arguments.get(1), Some(Argument::MutPointer(_))) + { + return Err( + "library ABI requires memory and mutable payload pointers before scratch slot 2" + .into(), + ); + } + for argument in &spec.arguments { + let (Argument::ConstPointer(scalar) + | Argument::MutPointer(scalar) + | Argument::Value(scalar)) = argument; + if !matches!( + scalar, + Scalar::Signed(8 | 16 | 32 | 64) + | Scalar::Unsigned(8 | 16 | 32 | 64) + | Scalar::Float(16 | 32 | 64) + ) { + return Err("library response contains an unsupported scalar width".into()); + } + } + } + Ok((response, bytes[header_end..].to_vec())) +} + +fn invoke( + executable: &PathBuf, + request: &BatchRequest<'_>, +) -> Result<(BatchResponse, Vec), String> { + let json = serde_json::to_vec(request).map_err(|e| e.to_string())?; + if json.len() > MAX_HEADER { + return Err("library request exceeds 1 MiB".into()); + } + let mut child = Command::new(executable) + .arg("--oxide-library-request-v1") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::inherit()) + .spawn() + .map_err(|e| { + format!( + "cannot execute native library provider {}: {e}", + executable.display() + ) + })?; + child + .stdin + .take() + .unwrap() + .write_all(&json) + .map_err(|e| format!("cannot send library request: {e}"))?; + let mut bytes = Vec::new(); + child + .stdout + .take() + .unwrap() + .take((24 + MAX_HEADER + MAX_LTO + 1) as u64) + .read_to_end(&mut bytes) + .map_err(|e| format!("cannot read library response: {e}"))?; + if bytes.len() > 24 + MAX_HEADER + MAX_LTO { + let _ = child.kill(); + } + let status = child + .wait() + .map_err(|e| format!("cannot wait for library provider: {e}"))?; + if !status.success() { + return Err(format!( + "native library provider failed with {status}; see its stderr diagnostics" + )); + } + decode_response(&bytes, request.requests.len()) +} + +fn extern_scalar(scalar: &Scalar) -> mir_importer::DeviceExternType { + use mir_importer::DeviceExternType as E; + match *scalar { + Scalar::Signed(bits) | Scalar::Unsigned(bits) => E::Integer(u32::from(bits)), + Scalar::Float(16) => E::Float16, + Scalar::Float(32) => E::Float32, + Scalar::Float(64) => E::Float64, + _ => unreachable!("validated scalar type"), + } +} + +fn extern_argument(argument: &Argument) -> mir_importer::DeviceExternType { + use mir_importer::DeviceExternType as E; + match argument { + Argument::Value(Scalar::Signed(bits)) if *bits < 32 => E::SignExtInteger(u32::from(*bits)), + Argument::Value(Scalar::Unsigned(bits)) if *bits < 32 => { + E::ZeroExtInteger(u32::from(*bits)) + } + Argument::Value(s) => extern_scalar(s), + Argument::ConstPointer(s) | Argument::MutPointer(s) => E::pointer_to(extern_scalar(s), 0), + } +} + +/// Finalize all call identities once, while retaining every root's reachability. +pub(crate) fn finalize<'tcx>( + tcx: TyCtxt<'tcx>, + collection: &CollectionResult<'tcx>, +) -> Result, String> { + let mut result = FinalizedLibraries::default(); + if collection.library_calls.is_empty() { + return Ok(result); + } + let target = std::env::var("CUDA_OXIDE_TARGET") + .map_err(|_| "library calls require an explicit CUDA target")?; + let target = target + .strip_prefix("sm_") + .map(|v| format!("compute_{v}")) + .unwrap_or(target); + let cuda_root = std::env::var_os("CUDA_HOME") + .or_else(|| std::env::var_os("CUDA_PATH")) + .map(PathBuf::from) + .ok_or("library calls require CUDA_HOME or CUDA_PATH")?; + // BTreeMap gives deterministic invocation order. Request order is first + // encounter order, and the response explicitly carries each request index. + type ProviderBatch<'a, 'tcx> = Vec<(Request, Vec<&'a LibraryCall<'tcx>>)>; + let mut batches: BTreeMap<(String, PathBuf), ProviderBatch<'_, 'tcx>> = BTreeMap::new(); + for call in &collection.library_calls { + let args = call.instance.args; + let report = |error: String| -> ! { + tcx.dcx() + .span_fatal(call.span, format!("native device library: {error}")) + }; + let registration = + read_registration(tcx, args.type_at(1)).unwrap_or_else(|error| report(error)); + let positive = |index| { + let value = args + .const_at(index) + .try_to_target_usize(tcx) + .ok_or("library extent is not a concrete usize")?; + u32::try_from(value) + .ok() + .filter(|v| *v != 0) + .ok_or("library extent must fit nonzero u32") + }; + let request = Request { + operation: registration.operation, + algorithm: registration.algorithm, + dtype: scalar(args.type_at(0)).unwrap_or_else(|error| report(error)), + block: [ + positive(3) + .map_err(str::to_owned) + .unwrap_or_else(|error| report(error)), + 1, + 1, + ], + items_per_thread: positive(4) + .map_err(str::to_owned) + .unwrap_or_else(|error| report(error)), + }; + let batch = batches + .entry((registration.provider, registration.executable)) + .or_default(); + if let Some((_, calls)) = batch.iter_mut().find(|(existing, _)| *existing == request) { + calls.push(call); + } else { + batch.push((request, vec![call])); + } + } + let mut finalized = HashMap::new(); + let mut all_symbols = HashSet::new(); + for ((provider, executable), batch) in batches { + let requests: Vec<_> = batch.iter().map(|(request, _)| request.clone()).collect(); + let batch_span = batch[0].1[0].span; + let (response, lto) = invoke( + &executable, + &BatchRequest { + version: 1, + target: &target, + cuda_root: cuda_root.clone(), + requests: &requests, + }, + ) + .unwrap_or_else(|error| { + tcx.dcx() + .span_fatal(batch_span, format!("native device library: {error}")) + }); + let identity: String = response + .batch_identity + .iter() + .map(|b| format!("{b:02x}")) + .collect(); + result + .inputs + .push((format!("library-{provider}-{identity}.ltoir"), lto)); + for ((request, calls), spec) in batch.into_iter().zip(response.specializations) { + if !all_symbols.insert(spec.symbol.clone()) { + return Err(format!( + "different provider batches returned the same symbol {}", + spec.symbol + )); + } + let (scratch_bytes, scratch_alignment) = spec.scratch.checked()?; + let mut params: Vec<_> = spec.arguments.iter().map(extern_argument).collect(); + params.insert( + 2, + mir_importer::DeviceExternType::pointer_to( + mir_importer::DeviceExternType::Integer(8), + 0, + ), + ); + result.declarations.push(mir_importer::DeviceExternDecl { + export_name: spec.symbol.clone(), + param_types: params, + return_type: mir_importer::DeviceExternType::Void, + attrs: mir_importer::DeviceExternAttrs { + is_convergent: true, + is_pure: false, + is_readonly: false, + }, + }); + for call in calls { + let TyKind::Tuple(fields) = call.instance.args.type_at(2).kind() else { + tcx.dcx().span_fatal( + call.span, + "library Args must be a tuple of scalars and raw pointers", + ); + }; + let actual = fields + .iter() + .map(argument) + .collect::, _>>() + .unwrap_or_else(|error| tcx.dcx().span_fatal(call.span, error)); + if actual != spec.arguments { + tcx.dcx().span_fatal(call.span, format!( + "library runtime tuple for {} disagrees with provider ABI: actual {actual:?}, expected {:?}", + spec.symbol, spec.arguments + )); + } + let _ = spec.mutates_payload; // Metadata, not permission to read payload. + let plan = mir_importer::LibraryCallPlan { + symbol: spec.symbol.clone(), + scratch_bytes, + scratch_alignment, + }; + if finalized + .insert( + call.instance, + KernelLaunchFacts { + exact_block: Some(( + request.block[0], + request.block[1], + request.block[2], + )), + dynamic_shared_bytes: scratch_bytes, + dynamic_shared_alignment: scratch_alignment, + }, + ) + .is_none() + { + result.calls.push((call.instance, plan)); + } + } + } + } + for root in collection.functions.iter().filter(|f| f.is_kernel) { + let mut visited = HashSet::new(); + let mut pending = vec![root.instance]; + let mut root_plan: Option = None; + while let Some(instance) = pending.pop() { + if !visited.insert(instance) { + continue; + } + if let Some(plan) = finalized.get(&instance) { + if let Some(current) = &mut root_plan { + if current.exact_block != plan.exact_block { + tcx.dcx().span_fatal( + tcx.def_span(root.instance.def_id()), + format!( + "kernel {} has conflicting exact library block shapes", + root.export_name + ), + ); + } + current.dynamic_shared_bytes = + current.dynamic_shared_bytes.max(plan.dynamic_shared_bytes); + current.dynamic_shared_alignment = current + .dynamic_shared_alignment + .max(plan.dynamic_shared_alignment); + } else { + root_plan = Some(*plan); + } + } + pending.extend( + collection + .call_edges + .iter() + .filter(|(caller, _)| *caller == instance) + .map(|(_, callee)| *callee), + ); + } + if let Some(plan) = root_plan { + for instance in visited { + let path = tcx.def_path_str(instance.def_id()); + if tcx.crate_name(instance.def_id().krate).as_str() == "cuda_device" + && path.contains("DynamicSharedArray") + { + return Err(format!( + "kernel {} mixes library scratch with a native dynamic shared view", + root.export_name + )); + } + } + result.roots.insert(root.export_name.clone(), plan); + } + } + Ok(result) +} + +#[cfg(test)] +mod tests { + use super::*; + + fn response() -> serde_json::Value { + let scalar = serde_json::json!({"kind": "signed", "bits": 32}); + serde_json::json!({ + "version": 1, "batch_identity": vec![0; 32], + "specializations": [{ + "request_index": 0, "identity": vec![1; 32], "symbol": "library_i32", + "arguments": [ + {"kind": "const_pointer", "scalar": scalar}, + {"kind": "mut_pointer", "scalar": scalar} + ], + "cub_layout": {"size": 1, "alignment": 1}, + "scratch": {"size": 0, "alignment": 1}, + "scratch_free": true, "mutates_payload": true + }] + }) + } + + fn frame(response: &serde_json::Value) -> Vec { + let json = serde_json::to_vec(response).unwrap(); + let mut bytes = b"OXDLIB01".to_vec(); + bytes.extend((json.len() as u64).to_le_bytes()); + bytes.extend(3_u64.to_le_bytes()); + bytes.extend(json); + bytes.extend([1, 2, 3]); + bytes + } + + #[test] + fn response_frame_retains_bytes_and_rejects_truncation_or_trailing_data() { + let bytes = frame(&response()); + assert_eq!(decode_response(&bytes, 1).unwrap().1, [1, 2, 3]); + for end in [0, 8, 16, 23, bytes.len() - 1] { + assert!(decode_response(&bytes[..end], 1).is_err()); + } + let mut trailing = bytes.clone(); + trailing.push(0); + assert!(decode_response(&trailing, 1).is_err()); + let mut empty_lto = bytes; + empty_lto[16..24].copy_from_slice(&0_u64.to_le_bytes()); + assert!(decode_response(&empty_lto, 1).is_err()); + } + + #[test] + fn response_rejects_inconsistent_identity_layout_and_abi() { + for (field, value) in [ + ("request_index", serde_json::json!(1)), + ("symbol", serde_json::json!("not a symbol")), + ("scratch_free", serde_json::json!(false)), + ("scratch", serde_json::json!({"size": 0, "alignment": 3})), + ( + "cub_layout", + serde_json::json!({"size": 4294967296_u64, "alignment": 1}), + ), + ("arguments", serde_json::json!([])), + ] { + let mut value_response = response(); + value_response["specializations"][0][field] = value; + assert!( + decode_response(&frame(&value_response), 1).is_err(), + "{field}" + ); + } + let mut duplicate = response(); + let mut second = duplicate["specializations"][0].clone(); + second["request_index"] = 1.into(); + duplicate["specializations"] + .as_array_mut() + .unwrap() + .push(second); + assert!(decode_response(&frame(&duplicate), 2).is_err()); + assert!(decode_response(&frame(&response()), 2).is_err()); + let mut version = response(); + version["version"] = 2.into(); + assert!(decode_response(&frame(&version), 1).is_err()); + } +} diff --git a/cuda-oxide/crates/rustc-codegen-cuda/src/materialize.rs b/cuda-oxide/crates/rustc-codegen-cuda/src/materialize.rs index 387c4ce4f6..8519ac61c7 100644 --- a/cuda-oxide/crates/rustc-codegen-cuda/src/materialize.rs +++ b/cuda-oxide/crates/rustc-codegen-cuda/src/materialize.rs @@ -27,10 +27,18 @@ pub(crate) const MATERIALIZER_HANDSHAKE_ENV: &str = reserved_oxide_symbols::MATERIALIZER_HANDSHAKE_ENV; pub(crate) const CODEGEN_FINGERPRINT_ENV: &str = reserved_oxide_symbols::CODEGEN_FINGERPRINT_ENV; -#[derive(Clone, Copy, Debug, Eq, PartialEq)] +#[derive(Debug)] pub(crate) struct MaterializationRequest { expected_provenance: [u8; 32], tool_identity_handshake: cuda_artifact_finalizer::MaterializerHandshakeV1, + external_inputs: Vec<(String, Vec)>, + library_inputs: Vec<(String, Vec)>, +} + +impl MaterializationRequest { + pub(crate) fn add_library_inputs(&mut self, inputs: Vec<(String, Vec)>) { + self.library_inputs.extend(inputs); + } } /// Cubin bytes plus ptxas resource diagnostics from the final link. @@ -92,15 +100,13 @@ pub(crate) enum MaterializeError { ProvenanceMismatch { expected: String, actual: String }, #[error( - "build-time cubin materialization does not yet support generic #[cuda_module] loading because it merges PTX bundles across crates at run time" - )] - RequiresPtxBundleMerge, - - #[error( - "build-time cubin materialization does not yet support #[device] extern declarations because their ordered external link inputs are not available to the backend" + "build-time cubin materialization of #[device] extern declarations requires their definitions; supply ordered --link-ltoir inputs" )] HasDeviceExterns, + #[error("invalid cargo-oxide external LTO-IR input list: {reason}")] + InvalidExternalInputs { reason: String }, + #[error( "build-time cubin materialization requires an NVVM IR or LTOIR artifact, but codegen produced PTX; use cargo-oxide so materialization can force NVVM IR emission" )] @@ -147,12 +153,38 @@ pub(crate) fn request_from_env() -> Result, Mater })?; validate_tool_identity_handshake(expected_provenance, &handshake)?; validate_codegen_fingerprint()?; + let external_inputs = external_inputs_from_env()?; Ok(Some(MaterializationRequest { expected_provenance, tool_identity_handshake: handshake, + external_inputs, + library_inputs: Vec::new(), })) } +fn external_inputs_from_env() -> Result)>, MaterializeError> { + let value = match std::env::var(reserved_oxide_symbols::EXTERNAL_LTOIR_ENV) { + Ok(value) => value, + Err(std::env::VarError::NotPresent) => return Ok(Vec::new()), + Err(error) => { + return Err(MaterializeError::InvalidExternalInputs { + reason: error.to_string(), + }); + } + }; + let files: Vec = + serde_json::from_str(&value).map_err(|error| MaterializeError::InvalidExternalInputs { + reason: error.to_string(), + })?; + files + .into_iter() + .map(|file| { + let bytes = file.read_verified()?; + Ok((file.name()?.to_owned(), bytes)) + }) + .collect() +} + fn validate_tool_identity_handshake( expected_provenance: [u8; 32], handshake: &cuda_artifact_finalizer::MaterializerHandshakeV1, @@ -174,22 +206,43 @@ fn validate_tool_identity_handshake( /// Reject artifact-loading models the finalizer cannot reproduce, before any /// CUDA compiler library is discovered or loaded. pub(crate) fn validate_collection( - request: Option, + request: Option<&MaterializationRequest>, has_device_externs: bool, - requires_ptx_bundle_merge: bool, ) -> Result<(), MaterializeError> { - if request.is_none() { + let Some(request) = request else { return Ok(()); - } - if requires_ptx_bundle_merge { - return Err(MaterializeError::RequiresPtxBundleMerge); - } - if has_device_externs { + }; + if has_device_externs && request.external_inputs.is_empty() && request.library_inputs.is_empty() + { return Err(MaterializeError::HasDeviceExterns); } Ok(()) } +/// Use the actual rustc crate name and configured output directory, including +/// for Cargo passthrough builds whose working directory differs from the CLI's. +pub(crate) fn validate_output_paths( + request: Option<&MaterializationRequest>, + output_dir: &std::path::Path, + output_name: &str, +) -> Result<(), MaterializeError> { + let Some(request) = request else { + return Ok(()); + }; + let mut outputs = + mir_importer::pipeline::stale_compilation_artifact_paths(output_dir, output_name); + outputs.push(output_dir.join(format!( + "{output_name}.{}", + oxide_tile_export::DESCRIPTIONS_SUFFIX + ))); + for (input, _) in &request.external_inputs { + for output in &outputs { + cuda_artifact_finalizer::check_ltoir_input_output(std::path::Path::new(input), output)?; + } + } + Ok(()) +} + pub(crate) fn nvvm_ir_to_cubin( request: MaterializationRequest, nvvm_ir: &[u8], @@ -199,8 +252,13 @@ pub(crate) fn nvvm_ir_to_cubin( debug_policy: DebugPolicy, ) -> Result { let options = options(target, allow_fma_contraction, debug_policy)?; - let finalizer = checked_finalizer(request)?; - let report = finalizer.materialize_nvvm_ir_with_report(module_name, nvvm_ir, &options)?; + let finalizer = checked_finalizer(&request)?; + let ltoir = finalizer + .compiler() + .compile_nvvm_ir_to_ltoir(module_name, nvvm_ir, &options)?; + let name = format!("{module_name}.ltoir"); + let inputs = link_inputs(&request, &name, <oir); + let report = finalizer.link_ltoir_with_report(&inputs, &options, FinalizerOutput::Cubin)?; Ok(MaterializedCubin { bytes: report.image, resource_usage: report.resource_usage, @@ -216,18 +274,31 @@ pub(crate) fn ltoir_to_cubin( debug_policy: DebugPolicy, ) -> Result { let options = options(target, allow_fma_contraction, debug_policy)?; - let finalizer = checked_finalizer(request)?; - let report = finalizer.link_ltoir_with_report( - &[NamedInput::new(module_name, ltoir)], - &options, - FinalizerOutput::Cubin, - )?; + let finalizer = checked_finalizer(&request)?; + let inputs = link_inputs(&request, module_name, ltoir); + let report = finalizer.link_ltoir_with_report(&inputs, &options, FinalizerOutput::Cubin)?; Ok(MaterializedCubin { bytes: report.image, resource_usage: report.resource_usage, }) } +fn link_inputs<'a>( + request: &'a MaterializationRequest, + name: &'a str, + bytes: &'a [u8], +) -> Vec> { + std::iter::once(NamedInput::new(name, bytes)) + .chain( + request + .external_inputs + .iter() + .chain(&request.library_inputs) + .map(|(name, bytes)| NamedInput::new(name, bytes)), + ) + .collect() +} + fn options( target: &str, allow_fma_contraction: bool, @@ -239,7 +310,7 @@ fn options( .with_debug_policy(debug_policy)) } -fn checked_finalizer(request: MaterializationRequest) -> Result { +fn checked_finalizer(request: &MaterializationRequest) -> Result { let finalizer = Finalizer::discover_with_handshake(&request.tool_identity_handshake)?; let actual = finalizer .provenance_digest() @@ -385,21 +456,58 @@ mod tests { } #[test] - fn unsupported_collection_models_fail_without_tools() { + fn output_overlap_uses_the_actual_crate_and_output_directory() { + let root = std::env::temp_dir().join(format!( + "oxide-materialize-overlap-{}-{}", + std::process::id(), + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_nanos() + )); + std::fs::create_dir_all(&root).unwrap(); + let input = root.join("custom_target.ll"); + std::fs::write(&input, b"external input").unwrap(); let handshake = test_handshake(); - let request = Some(MaterializationRequest { + let request = MaterializationRequest { expected_provenance: handshake.provenance_sha256, tool_identity_handshake: handshake, - }); + library_inputs: Vec::new(), + external_inputs: vec![( + input.to_str().unwrap().to_owned(), + b"external input".to_vec(), + )], + }; + assert!(validate_output_paths(Some(&request), &root, "package_name").is_ok()); assert!(matches!( - validate_collection(request, false, true), - Err(MaterializeError::RequiresPtxBundleMerge) + validate_output_paths(Some(&request), &root, "custom_target"), + Err(MaterializeError::Finalizer( + FinalizerError::LtoirInputOutputOverlap { .. } + )) )); + assert_eq!(std::fs::read(&input).unwrap(), b"external input"); + std::fs::remove_dir_all(root).unwrap(); + } + + #[test] + fn unsupported_collection_models_fail_without_tools() { + let handshake = test_handshake(); + let mut request = MaterializationRequest { + expected_provenance: handshake.provenance_sha256, + tool_identity_handshake: handshake, + library_inputs: Vec::new(), + external_inputs: Vec::new(), + }; + assert!(validate_collection(Some(&request), false).is_ok()); assert!(matches!( - validate_collection(request, true, false), + validate_collection(Some(&request), true), Err(MaterializeError::HasDeviceExterns) )); - assert!(validate_collection(None, true, true).is_ok()); + assert!(validate_collection(None, true).is_ok()); + request + .external_inputs + .push(("definition.ltoir".into(), vec![1])); + assert!(validate_collection(Some(&request), true).is_ok()); } #[test] diff --git a/cuda-oxide/cuda-oxide-book/compiler/native-library-calls.md b/cuda-oxide/cuda-oxide-book/compiler/native-library-calls.md new file mode 100644 index 0000000000..2bcec49af4 --- /dev/null +++ b/cuda-oxide/cuda-oxide-book/compiler/native-library-calls.md @@ -0,0 +1,172 @@ +# Native library calls + +`cuda_device::library::call_v1` is an unsafe integration point for library +authors. It specializes native device implementations from concrete Rust +calls, then supplies their LTO-IR to ordinary CUBIN materialization. The +compiler owns discovery and linking; the library owns its operation semantics, +native code, ABI and scratch requirements. + +Use `cargo oxide build`, `run` or `test` with `--materialize-cubin`. The compiler +recognizes the actual marker definition, including calls reached through +generic dependency helpers. A same-named user function remains ordinary Rust. +The marker must be called directly; pass a wrapper helper rather than the +marker itself as a callable value. + +The `native_library` example is an executable provider with no CUB dependency. +Its dependency helper is instantiated at one and four items per thread, and +two concrete kernel roots run through the embedded module loader: + +```sh +cargo oxide run native_library --arch sm_120 --materialize-cubin +``` + +## Registration and call ABI + +The marker's generic parameters are `T`, `Registration`, `Args`, +`const BLOCK_THREADS: usize` and `const ITEMS_PER_THREAD: usize`. +Both extents must fit positive `u32`. It accepts a registration function item +and one tuple of scalar/raw-pointer arguments; it returns unit. + +The registration getter returns one constant UTF-8 JSON string. Its MIR must +contain one return block and one assignment of that constant to its result. +Closures, function pointers and computed getters are rejected. The compiler +reads the constant without running Rust device code. A Cargo build script can +embed the string with `cargo::rustc-env` and serve as the already-built native +provider. Read it through the registration macro so Cargo tracks native inputs: + +```rust +fn registration() -> &'static str { + cuda_device::library::registration!("MY_LIBRARY_REGISTRATION") +} +``` + +The macro requires nonempty provider, operation and algorithm names and expands +to the same constant string. The provider executable must +recognize its protocol arguments before its ordinary Cargo build-script behavior. + +Registration fields are: + +| Field | Meaning | +| --- | --- | +| `version` | Integer `1` | +| `provider` | Nonempty library identifier | +| `executable` | Absolute path to the built host provider | +| `operation`, `algorithm` | Opaque recipe names interpreted by that provider | + +The runtime tuple starts with a const or mutable memory pointer and a mutable +payload pointer. Remaining fields are supported fixed-width numeric values or +raw pointers. The provider declares the exact ordered types and pointer +mutability; the compiler compares them with the Rust tuple. It inserts a +generic `unsigned char*` scratch parameter at native argument index two. +Small signed and unsigned integer values retain their native extension rules. +The native function returns `void`. + +## Host request and response + +For each `(provider, executable)` pair, the compiler invokes the executable +once with `--oxide-library-request-v1`. Stdin is one JSON object with `version: 1`, +`target`, `cuda_root`, and an ordered `requests` array. Each request contains +`operation`, `algorithm`, `dtype`, `block: [B,1,1]`, and `items_per_thread`. +Repeated concrete requests are deduplicated across roots. Scalar descriptions +use `{"kind":"signed|unsigned|float", "bits":N}`; integer widths are +8/16/32/64 and float widths are 16/32/64. A provider may support a narrower set +and must diagnose unsupported requests. + +Stdout contains only a binary response: eight bytes `OXDLIB01`, little-endian +u64 JSON-header length, little-endian u64 LTO-IR length, then the header and raw +LTO-IR. Diagnostics go to stderr; failure exits nonzero. Requests and response +headers are limited to 1 MiB, and the nonempty LTO-IR buffer to 256 MiB. + +The header has `version: 1`, a 32-byte `batch_identity` array, and one +`specializations` entry per request, in the same order: + +| Field | Meaning | +| --- | --- | +| `request_index` | Zero-based request position | +| `identity`, `symbol` | Unique 32-byte specialization identity and native link symbol | +| `arguments` | Ordered runtime tuple ABI, excluding the inserted scratch pointer | +| `cub_layout`, `scratch` | Native temporary-layout and required scratch `{size, alignment}` | +| `scratch_free` | Must agree with `scratch.size == 0` | +| `mutates_payload` | Semantic information; never permission to read an undefined value | + +Argument descriptions use `kind: "const_pointer"`, `"mut_pointer"` or +`"value"`, with a `scalar` description. Layout fields must fit `u32`, and +alignment must be a positive power of two. Symbol names use letters, digits +and underscores and cannot start with a digit. Different batches must not +return the same symbol. Truncated/trailing frames, mismatched versions, duplicate +identities and ABI mismatches fail compilation. + +The production provider is responsible for truthful layouts and identities +covering its sources, headers, recipes and toolchain. Returning owned bytes +avoids a second read of a mutable LTO file during finalization. The registration +macro tracks native inputs before rustc emits dep-info; +manual registration getters must arrange equivalent dependency tracking. + +## Native input dependencies + +The registration macro tracks its environment variable, the provider executable, +CUDA_HOME/CUDA_PATH selection, and the device compilation settings. During CUBIN +materialization it invokes the provider with `--oxide-library-inputs-v1`. Ordinary +host builds and rustdoc do not query toolkit inputs or require installed CUDA. + +The input query reads stdin through EOF. Its JSON request is +`{"version":1,"cuda_root":"/selected/toolkit","target":"compute_120"}`. +Stdout is one JSON response with `version: 1`, `paths` (absolute file or directory +paths) and `environment` (additional environment variable names). Requests and +responses are limited to 1 MiB. Diagnostics go to stderr; failures exit nonzero. +Unknown fields, invalid versions, relative/missing paths and invalid environment +names are errors. The query declares dependencies without compiling native code. + +The library owns this inventory, including sources, headers, compiler tools and +any environment affecting their selection or behavior. Directories are tracked +recursively so adding a header also causes recompilation. The macro records +these dependencies in the library crate; Cargo propagates its rebuild to +consumers and concrete generic kernel instantiations. The compiler has no +library-specific header layout or native cache. + +Cargo's timestamp freshness rules apply. Replacements with unchanged or older +timestamps can remain undetected, including restored files or a symlink switched +to an older installation at the same path. Clean/rebuild affected crates after +such external changes. +The `native_library` example tracks its provider, CUDA tools/headers, host compiler +driver and relevant environment. It assumes the host compiler's installed system +headers and libraries remain unchanged during a build; its declarations are not +a general inventory of an arbitrary C++ toolchain. + +## Debug information + +Providers choose the debug information in their LTO-IR; the compiler preserves +it during linking. With CUDA 13.3, Rust `--lineinfo` and native nvcc +`--generate-line-info` can be combined, retaining both source line tables. +Rust `--device-debug` also works with a provider built without debug information, +as exercised by the `native_library` full-debug smoke route. + +CUDA 13.3 rejects nvcc `-G` with `-dlto`. Linking Rust full debug with native line +information also fails in nvJitLink when it sees more than one debug compilation +unit. Select a supported combination explicitly; provider metadata is not +silently stripped to make these combinations link. + +## Resources and unsafe obligations + +Every reachable library call contributes its exact block shape and required +scratch to its kernel root. Conflicting shapes and incompatible declared launch +contracts or maximum bounds are errors. The compiled artifact carries the +resulting facts to launch preparation; `dynamic_shared = inferred` with +`LaunchConfig3D::auto_shared` uses the compiled byte count. + +This version aliases all library scratch views at the dynamic shared base, +using the maximum required size and alignment. The caller must complete each +use before conflicting reuse. Mixing native dynamic shared views +with library calls is rejected. No barrier, allocation token or borrow-based +completion is supplied by the marker. + +The library wrapper must enforce pointer validity, alignment, capacity, +initialization, nonaliasing, collective participation and resource reuse for +its native implementation. Convergent declarations preserve optimization +constraints; they do not prove participation or make the wrapper safe. The +marker is an unsafe compiler boundary, not a safe collective operation. + +The provider reads the complete request through stdin EOF before writing its +response. Reserve stdout for the binary response frame and use stderr for +diagnostics. The compiler waits for provider completion; provider execution has +the same trust boundary as a dependency's Cargo build script. diff --git a/cuda-oxide/cuda-oxide-book/getting-started/installation.md b/cuda-oxide/cuda-oxide-book/getting-started/installation.md index 4a39d2ea3a..05c031356c 100644 --- a/cuda-oxide/cuda-oxide-book/getting-started/installation.md +++ b/cuda-oxide/cuda-oxide-book/getting-started/installation.md @@ -373,6 +373,22 @@ cargo oxide emit-ltoir my_kernels --arch sm_90 Every command takes `--help`, which lists the flags each one accepts. +For kernels that call external device functions, `--materialize-cubin` +links their CUDA LTO-IR definitions during the ordinary Cargo build. Pass each +input with `--link-ltoir` after the subcommand, in link order: + +```bash +cargo oxide run --materialize-cubin --arch sm_120 \ + --link-ltoir build/device-libs/scale.ltoir --link-ltoir build/device-libs/add.ltoir +``` + +Inputs must be raw CUDA LTO-IR, not object files or fatbins. Every supplied +file is linked into each materialized device artifact in the Cargo invocation. +This requires a build-host CUDA Toolkit compatible with the external inputs. +The resulting executable embeds the final cubin. Input names and contents are +part of Cargo's device-code fingerprint, so a changed definition rebuilds the +artifact. See the `external_ltoir` example for C++ sources and generation commands. + --- ## Verifying your installation @@ -410,3 +426,18 @@ If everything is configured correctly, this compiles a Rust kernel to PTX, launc - `cuda.h not found` -- Set `CUDA_TOOLKIT_PATH` to your CUDA install root, or ensure `/usr/local/cuda/include/cuda.h` exists. - `rust-src` / `llvm-tools` component missing -- Run `rustup component add rust-src llvm-tools --toolchain nightly-2026-10-11`. ::: + +Generic `#[cuda_module]` loaders support materialization when all required concrete +specializations are in one embedded native artifact. They retain exact symbol +lookup and compiled launch facts in one CUDA module. Multiple native artifacts +or mixed native/PTX bundles are rejected because separate module loads would not +preserve shared device globals. PTX-only builds continue to merge their bundles. + +On Linux, generic loaders read the mapped image containing the defining crate's +host loader code. Link the crate that instantiates the kernels into that same +image. This applies to both native and PTX loading and requires readable +`/proc/self/maps` and `/proc/self/map_files`; a missing or replaced mapped file +is an error. The loader does not fall back to the process executable. +A concrete kernel compiled in a dependency can create a second native artifact; +keep native specializations in one emitting crate. A missing specialization in +an otherwise selected artifact fails at kernel lookup. diff --git a/cuda-oxide/cuda-oxide-book/index.md b/cuda-oxide/cuda-oxide-book/index.md index 5c15827081..42c3f46a4b 100644 --- a/cuda-oxide/cuda-oxide-book/index.md +++ b/cuda-oxide/cuda-oxide-book/index.md @@ -194,6 +194,7 @@ compiler/compiler-optimizations compiler/mlir-dialects compiler/lowering-pipeline compiler/adding-new-intrinsics +compiler/native-library-calls compiler/catalog-generated-intrinsics compiler/fuzzing-and-differential-testing ``` diff --git a/cuda-oxide/scripts/check-compiled-launch-facts.sh b/cuda-oxide/scripts/check-compiled-launch-facts.sh new file mode 100755 index 0000000000..7dfd7e8652 --- /dev/null +++ b/cuda-oxide/scripts/check-compiled-launch-facts.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +set -euo pipefail +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +arch="${1:-sm_120}" +oxide=(cargo oxide) +if [[ -n "${CARGO_OXIDE_BIN:-}" ]]; then + oxide=("$CARGO_OXIDE_BIN") +fi +log=$(mktemp) +trap 'rm -f "$log"' EXIT + +"${oxide[@]}" run compiled_launch_facts --arch "$arch" +"${oxide[@]}" run compiled_launch_facts --arch "$arch" --features generic +"${oxide[@]}" run compiled_launch_facts --arch "$arch" --materialize-cubin + +if "${oxide[@]}" run compiled_launch_facts --arch "$arch" --features invalid-raw >"$log" 2>&1; then + echo "error: inferred scratch accepted an unconstrained raw dynamic view" >&2 + exit 1 +fi +grep -F 'inferred dynamic shared memory cannot include unconstrained' "$log" + +"${oxide[@]}" run compiled_launch_facts --arch "$arch" --features generic --materialize-cubin +"${oxide[@]}" run cross_crate_kernel --arch "$arch" --features native-ambiguity +if "${oxide[@]}" run cross_crate_kernel --arch "$arch" --materialize-cubin --features native-ambiguity >"$log" 2>&1; then + echo "error: generic loading accepted separate native artifacts" >&2 + exit 1 +fi +grep -F 'IncompatibleGenericArtifacts' "$log" +grep -F 'kernel-lib' "$log" +echo 'PASS: compiled launch facts, incomplete-plan and native-ambiguity rejection' diff --git a/cuda-oxide/scripts/check-example-smoketest-contract.sh b/cuda-oxide/scripts/check-example-smoketest-contract.sh index 710032d4e8..d48e017fa0 100644 --- a/cuda-oxide/scripts/check-example-smoketest-contract.sh +++ b/cuda-oxide/scripts/check-example-smoketest-contract.sh @@ -228,7 +228,7 @@ if not re.search( r'\[\[ \$\{FULL_DEBUG\} -eq 0 \]\] && verify_nvvm_in_compile_only', source ): sys.exit("full-debug verdict contract missing: libNVVM artifact branch is not excluded") -if "FULL_DEBUG_CONFIGURED_ROUTE_EXAMPLES=(interop_cubin_identity)" not in source: +if "FULL_DEBUG_CONFIGURED_ROUTE_EXAMPLES=(interop_cubin_identity native_library)" not in source: sys.exit("full-debug route contract missing: explicit cubin-project accommodation") if "Full-debug configured route: %d / %d passed" not in source: sys.exit("full-debug route contract missing: configured-route summary") diff --git a/cuda-oxide/scripts/check-external-ltoir.sh b/cuda-oxide/scripts/check-external-ltoir.sh new file mode 100755 index 0000000000..ff2f87dbc5 --- /dev/null +++ b/cuda-oxide/scripts/check-external-ltoir.sh @@ -0,0 +1,106 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# Run with a CUDA Toolkit and GPU matching the requested architecture. +set -euo pipefail + +cd "$(dirname "$0")/.." +arch="${1:-sm_120}" +example="$PWD/crates/rustc-codegen-cuda/examples/external_ltoir" +artifacts="$(mktemp -d "${TMPDIR:-/tmp}/oxide-external-ltoir.XXXXXX")" +echo "External LTO-IR regression artifacts: $artifacts" +# Keep the example's executable location independent of the caller's Cargo cache. +unset CARGO_TARGET_DIR +oxide=(cargo oxide) +if [[ -n "${CARGO_OXIDE_BIN:-}" ]]; then + oxide=("$CARGO_OXIDE_BIN") +fi + +nvcc_flags=(--ltoir -dlto -arch="$arch") +if [[ -n "${NVCC_CCBIN:-${CUDAHOSTCXX:-}}" ]]; then + nvcc_flags+=(-ccbin="${NVCC_CCBIN:-$CUDAHOSTCXX}") +fi +nvcc "${nvcc_flags[@]}" "$example/scale.cu" -o "$artifacts/scale.ltoir" +nvcc "${nvcc_flags[@]}" -DEXTERNAL_ADDEND=3 "$example/add.cu" -o "$artifacts/add.ltoir" + +flags=(--arch "$arch" --materialize-cubin + --link-ltoir "$artifacts/scale.ltoir" --link-ltoir "$artifacts/add.ltoir") +cargo_args=(--manifest-path "$example/Cargo.toml" --release) + +run() { + local label="$1" + shift + if ! "$@" >"$artifacts/$label.log" 2>&1; then + cat "$artifacts/$label.log" >&2 + return 1 + fi + echo "PASS $label" +} + +run run "${oxide[@]}" run external_ltoir "${flags[@]}" +run test "${oxide[@]}" test "${flags[@]}" -- "${cargo_args[@]}" -- --nocapture +run build "${oxide[@]}" build "${flags[@]}" -- "${cargo_args[@]}" -v +run fresh "${oxide[@]}" build "${flags[@]}" -- "${cargo_args[@]}" -v +grep -q 'Fresh external_ltoir ' "$artifacts/fresh.log" + +# Change just the library content, retaining its path, size and modification +# time. The next passthrough build must invalidate Cargo's cached device code. +cp -p "$artifacts/add.ltoir" "$artifacts/add-original.ltoir" +nvcc "${nvcc_flags[@]}" -DEXTERNAL_ADDEND=1 "$example/add.cu" -o "$artifacts/add.ltoir" +if [[ "$(wc -c < "$artifacts/add-original.ltoir")" != "$(wc -c < "$artifacts/add.ltoir")" ]]; then + echo "error: this nvcc did not produce equal-sized addend variants" >&2 + exit 1 +fi +if cmp -s "$artifacts/add-original.ltoir" "$artifacts/add.ltoir"; then + echo "error: the addend variants have identical bytes" >&2 + exit 1 +fi +touch -r "$artifacts/add-original.ltoir" "$artifacts/add.ltoir" +run content-change "${oxide[@]}" build "${flags[@]}" -- "${cargo_args[@]}" -v +mv "$artifacts/scale.ltoir" "$artifacts/scale.saved" +mv "$artifacts/add.ltoir" "$artifacts/add.saved" +run changed-result "$example/target/release/external_ltoir" 1 +mv "$artifacts/scale.saved" "$artifacts/scale.ltoir" +mv "$artifacts/add.saved" "$artifacts/add.ltoir" + +if "${oxide[@]}" build --arch "$arch" --materialize-cubin \ + --link-ltoir "$artifacts/scale.ltoir" -- "${cargo_args[@]}" \ + >"$artifacts/missing-symbol.log" 2>&1; then + echo "error: a missing transitive device definition unexpectedly linked" >&2 + exit 1 +fi +grep -q 'external_add' "$artifacts/missing-symbol.log" +grep -qi 'nvJitLink' "$artifacts/missing-symbol.log" +echo "PASS missing-symbol" + +printf 'not an LTO-IR module\n' >"$artifacts/corrupt.ltoir" +if "${oxide[@]}" build --arch "$arch" --materialize-cubin \ + --link-ltoir "$artifacts/scale.ltoir" --link-ltoir "$artifacts/corrupt.ltoir" \ + -- "${cargo_args[@]}" >"$artifacts/corrupt-input.log" 2>&1; then + echo "error: corrupt LTO-IR unexpectedly linked" >&2 + exit 1 +fi +grep -qi 'nvJitLink' "$artifacts/corrupt-input.log" +grep -q 'corrupt.ltoir' "$artifacts/corrupt-input.log" +echo "PASS corrupt-input" + +# Exercise the backend guard using a disposable output directory. The supplied +# input and a previous output must both survive rejection before codegen writes. +collision="$artifacts/collision" +mkdir -p "$collision" +cp "$artifacts/scale.ltoir" "$collision/external_ltoir.ll" +printf 'previous output sentinel\n' >"$artifacts/previous-output" +cp "$artifacts/previous-output" "$collision/external_ltoir.ptx" +if CUDA_OXIDE_PTX_DIR="$collision" "${oxide[@]}" build --arch "$arch" --materialize-cubin \ + --link-ltoir "$collision/external_ltoir.ll" --link-ltoir "$artifacts/add.ltoir" \ + -- "${cargo_args[@]}" >"$artifacts/input-output-overlap.log" 2>&1; then + echo "error: an external input overlapping generated output was accepted" >&2 + exit 1 +fi +grep -q 'overlaps generated artifact' "$artifacts/input-output-overlap.log" +cmp "$artifacts/scale.ltoir" "$collision/external_ltoir.ll" +cmp "$artifacts/previous-output" "$collision/external_ltoir.ptx" +echo "PASS input-output-overlap" + +cp -p "$artifacts/add-original.ltoir" "$artifacts/add.ltoir" +run restored "${oxide[@]}" run external_ltoir "${flags[@]}" diff --git a/cuda-oxide/scripts/check-oxide-artifacts-parity.sh b/cuda-oxide/scripts/check-oxide-artifacts-parity.sh index 3d3d713239..8a0a4eacda 100755 --- a/cuda-oxide/scripts/check-oxide-artifacts-parity.sh +++ b/cuda-oxide/scripts/check-oxide-artifacts-parity.sh @@ -1,61 +1,61 @@ #!/usr/bin/env bash # SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. # SPDX-License-Identifier: Apache-2.0 -# Verify the in-tree oxide-artifacts crate and the crates.io release everyone -# consumes are the same version. -# -# crates/oxide-artifacts is the source the release is published from, but no -# workspace consumes it by path any more: the backend writes artifact bundles -# and the shared cuda-core (cutile-rs) reads them, both through crates.io -# oxide-artifacts, so writer and reader are one crate. The in-tree copy can -# still drift ahead of the release; if it does, an edit to the format lands in -# git without reaching any consumer, and the next publish silently changes -# what every reader accepts. This guard fails as soon as the in-tree version, -# the workspace dependency requirements, and the versions resolved in every -# lock file disagree. -# -# Format changes therefore go: bump crates/oxide-artifacts, publish, then move -# the requirement in the SIMT and backend manifests and relock. +# Keep artifact writers and readers on one in-tree implementation and version. set -euo pipefail export LC_ALL=C cd "$(dirname "$0")/.." GIT_ROOT="$(git rev-parse --show-toplevel)" -in_tree="$(sed -n -E 's/^version = "([^"]+)"/\1/p' crates/oxide-artifacts/Cargo.toml | head -1)" -[ -n "${in_tree}" ] || { echo "error: crates/oxide-artifacts/Cargo.toml has no version" >&2; exit 1; } -echo "in-tree oxide-artifacts: ${in_tree}" +python3 - "${GIT_ROOT}" <<'PYTHON' +import pathlib +import subprocess +import sys +import tomllib -status=0 -req_of() { # req_of FILE -> the version requirement on the oxide-artifacts line - local line - line="$(grep -E '^oxide-artifacts[[:space:]]*=' "$1" | head -1 || true)" - if [[ "${line}" =~ version[[:space:]]*=[[:space:]]*\"([^\"]+)\" ]] || [[ "${line}" =~ ^oxide-artifacts[[:space:]]*=[[:space:]]*\"([^\"]+)\" ]]; then - echo "${BASH_REMATCH[1]}" - elif [[ "${line}" =~ path[[:space:]]*= ]]; then - echo "path" - else - echo "missing" - fi -} -for manifest in Cargo.toml crates/rustc-codegen-cuda/Cargo.toml; do - req="$(req_of "${manifest}")" - if [ "${req}" != "${in_tree}" ]; then - echo "error: ${manifest}: oxide-artifacts requirement is '${req}', in-tree version is ${in_tree}" >&2; status=1 - fi -done +root = pathlib.Path(sys.argv[1]) +artifact_dir = root / "cuda-oxide/crates/oxide-artifacts" -# Every lock that resolves oxide-artifacts must resolve exactly the in-tree -# version, from the registry (the SIMT lock also lists the in-tree member). -while IFS= read -r lock; do - versions="$(awk '/^name = "oxide-artifacts"$/{getline; print $3}' "${lock}" | tr -d '"' | sort -u)" - [ -n "${versions}" ] || continue - if [ "${versions}" != "${in_tree}" ]; then - echo "error: ${lock}: oxide-artifacts resolves to ${versions//$'\n'/, }, in-tree version is ${in_tree}" >&2; status=1 - fi - if ! grep -A3 '^name = "oxide-artifacts"$' "${lock}" | grep -q 'source = "registry+'; then - echo "error: ${lock}: oxide-artifacts is not consumed from crates.io" >&2; status=1 - fi -done < <(git -C "${GIT_ROOT}" ls-files 'Cargo.lock' '*/Cargo.lock' '**/Cargo.lock' | while read -r lock; do echo "${GIT_ROOT}/${lock}"; done) +def read_toml(path): + with path.open("rb") as source: + return tomllib.load(source) -[ "${status}" -eq 0 ] && echo "OK: oxide-artifacts is ${in_tree} in the tree, in both manifests, and in every lock (from crates.io)." -exit "${status}" +version = read_toml(artifact_dir / "Cargo.toml")["package"]["version"] +errors = [] +for relative, workspace in [ + ("cuda-core/Cargo.toml", False), + ("cuda-oxide/Cargo.toml", True), + ("cuda-oxide/crates/rustc-codegen-cuda/Cargo.toml", False), +]: + manifest = root / relative + data = read_toml(manifest) + dependencies = data["workspace"]["dependencies"] if workspace else data["dependencies"] + dependency = dependencies["oxide-artifacts"] + if not isinstance(dependency, dict) or dependency.get("version") != version: + errors.append(f"{relative}: oxide-artifacts must declare version {version}") + continue + path = dependency.get("path") + if path is None or (manifest.parent / path).resolve() != artifact_dir.resolve(): + errors.append(f"{relative}: oxide-artifacts must use {artifact_dir}") + +lockfiles = subprocess.check_output( + ["git", "-C", str(root), "ls-files", "-z", "*Cargo.lock"] +).decode().split("\0") +checked = 0 +for relative in filter(None, lockfiles): + packages = [ + package for package in read_toml(root / relative).get("package", []) + if package["name"] == "oxide-artifacts" + ] + if not packages: + continue + checked += 1 + if len(packages) != 1 or packages[0]["version"] != version or "source" in packages[0]: + errors.append(f"{relative}: oxide-artifacts must resolve once to the in-tree version {version}") + +for error in errors: + print(f"error: {error}", file=sys.stderr) +if errors: + sys.exit(1) +print(f"OK: oxide-artifacts {version} uses one in-tree source in all three manifests and {checked} locks.") +PYTHON diff --git a/cuda-oxide/scripts/smoketest.sh b/cuda-oxide/scripts/smoketest.sh index 35d8eb57a2..e6f75e64bb 100755 --- a/cuda-oxide/scripts/smoketest.sh +++ b/cuda-oxide/scripts/smoketest.sh @@ -90,7 +90,7 @@ set -uo pipefail TCGEN05_EXAMPLES=(gemm_sol gemm_sol_final tcgen05 tcgen05_matmul) WGMMA_EXAMPLES=(wgmma) BLACKWELL_MMA_EXAMPLES=(mma_mxf8f6f4) -LTOIR_EXAMPLES=(addressof_sharedarray constant_memory cpp_consumes_rust_device device_ffi_test legacy_atomic_fadd legacy_atomic_rmw_cas legacy_nvvm_pointer_shapes manual_launch_libdevice mathdx_ffi_test primitive_stress) +LTOIR_EXAMPLES=(addressof_sharedarray constant_memory cpp_consumes_rust_device device_ffi_test external_ltoir legacy_atomic_fadd legacy_atomic_rmw_cas legacy_nvvm_pointer_shapes manual_launch_libdevice mathdx_ffi_test primitive_stress) LTOIR_MODERN_EXAMPLES=(small_type_ffi_test) TILELIB_EXAMPLES=(tilelib_relu) AUTO_NVVM_EXAMPLES=(libdevice_math) @@ -127,13 +127,13 @@ NO_LAUNCH_EXAMPLES=(wgmma_mma_bf16) # afterwards purely to produce the artifacts the shape check reads. NO_OPT_SHAPE_EXAMPLES=(const_bool_dead_branch shared_memory_helper) -# This example intentionally configures a cubin artifact in Cargo metadata. -# Its supported project route necessarily includes NVVM IR + libNVVM + +# These examples require cubin artifacts, through Cargo metadata or native +# library materialization. Their supported route includes NVVM IR + libNVVM + # nvJitLink; the full-debug census must exercise that reality rather than # silently rewriting the project to PTX. It is reported separately from the -# direct-LLVM census so the one accommodation cannot be mistaken for direct +# direct-LLVM census so these accommodations cannot be mistaken for direct # backend coverage. -FULL_DEBUG_CONFIGURED_ROUTE_EXAMPLES=(interop_cubin_identity) +FULL_DEBUG_CONFIGURED_ROUTE_EXAMPLES=(interop_cubin_identity native_library) classify() { local ex="$1" cat @@ -263,14 +263,14 @@ OPTIONS is missing or too old). Error examples must still fail. Works on GPU-less CI. --full-debug Compile selected examples through the normal LLVM - `cargo oxide build --device-debug` route (except an - explicitly configured cubin project, reported as a + `cargo oxide build --device-debug` route (except the + configured cubin projects, reported as a separate configured-route accommodation). Validates fresh artifacts, ptxas assembly, permanent verify-debug-info.sh contracts, and intentional error diagnostics, but skips libNVVM and optimized code-shape gates because those do not accept/describe full-debug - output. Nothing is executed. Cannot be combined with + output. No kernels execute. Cannot be combined with --compile-only. -x, --fail-fast Stop at the first failure. -v, --verbose Stream cargo output live (instead of capturing to @@ -539,9 +539,9 @@ printf "%scuda-oxide smoketest%s @ %s%s%s (%s)\n" "${C_BOLD}" "${C_RESET}" "${C_ printf "GPU: %s\n" "${gpu_info}" printf "LTOIR arch: %s (modern: %s)\n" "${LTOIR_ARCH}" "${LTOIR_MODERN_ARCH}" if [[ ${COMPILE_ONLY} -eq 1 ]]; then - printf "Mode: compile-only (device artifacts only; nothing is executed)\n" + printf "Mode: compile-only (device artifacts only; no kernels execute)\n" elif [[ ${FULL_DEBUG} -eq 1 ]]; then - printf "Mode: full-debug compile census (direct LLVM plus explicit configured routes; nothing is executed)\n" + printf "Mode: full-debug compile census (direct LLVM plus explicit configured routes; no kernels execute)\n" fi if [[ -n "${ONLY}" ]]; then printf "Filter --only: %s\n" "${ONLY}"; fi if [[ -n "${SKIP}" ]]; then printf "Filter --skip: %s\n" "${SKIP}"; fi @@ -1026,6 +1026,10 @@ verdict_compile() { local artifact="${ex//-/_}" if [[ ${ec} -gt 128 ]]; then echo "FAIL (crashed, signal $((ec - 128)))"; return 1; fi if [[ ${ec} -ne 0 ]]; then echo "FAIL (exit=${ec})"; return 1; fi + if [[ "${ex}" == "native_library" ]]; then + native_library_cubin_verdict "${log}" + return + fi if [[ ${FULL_DEBUG} -eq 1 ]]; then case "${ex}" in device_ffi_test|mathdx_ffi_test|small_type_ffi_test) @@ -1038,6 +1042,11 @@ verdict_compile() { "${ex}" "${ex_dir}/${artifact}.ptx" return ;; + external_ltoir) + full_debug_relocatable_ffi_verdict \ + "${ex}" "${ex_dir}/${artifact}.ptx" + return + ;; cutile_inter_kernel) full_debug_ptx_verdict \ "${ex_dir}/simt/cutile_inter_kernel_simt.ptx" \ @@ -1180,6 +1189,9 @@ full_debug_relocatable_ffi_verdict() { mathdx_ffi_test) expected_undefined=$'cublasdx_gemm_32x32x32_block_dim_x\ncublasdx_gemm_32x32x32_block_dim_y\ncublasdx_gemm_32x32x32_block_dim_z\ncublasdx_gemm_32x32x32_f32\ncublasdx_gemm_32x32x32_f32_alphabeta\ncublasdx_gemm_32x32x32_smem_size\ncublasdx_gemm_32x32x32_smem_size_ab\ncufftdx_fft_16_c2c_f32_forward\ncufftdx_fft_16_c2c_f32_inverse\ncufftdx_fft_16_elements_per_thread\ncufftdx_fft_16_storage_size\ncufftdx_fft_32_storage_size\ncufftdx_fft_8_c2c_f32_forward\ncufftdx_fft_8_c2c_f32_inverse\ncufftdx_fft_8_elements_per_thread\ncufftdx_fft_8_storage_size\ndebug_extern_double_array' ;; + external_ltoir) + expected_undefined='external_scale_add' + ;; small_type_ffi_test) expected_undefined=$'small_add_u16\nsmall_add_u8\nsmall_half_add\nsmall_not_bool\nsmall_scale_i16\nsmall_scale_i8\nsmall_widen_i8\nsmall_widen_u16' ;; @@ -1266,6 +1278,56 @@ full_debug_relocatable_ffi_verdict() { echo "PASS (full-debug FFI PTX assembled relocatably for ${arch}; DWARF and undefined interface verified)" } +# The native-library fixture embeds its final image in the host executable. +# Its host-only check extracts that exact CUBIN without loading the CUDA driver. +native_library_cubin_verdict() { + local log="$1" target="${LTOIR_ARCH}" cubin elf_reader sections dwarf symbol + local binary="${CARGO_TARGET_DIR}/release/native_library" + # cargo oxide builds with the example as cwd; Cargo resolves relative + # target directories there, while this verdict runs from the repo root. + if [[ "${CARGO_TARGET_DIR}" != /* ]]; then + binary="${repo_root}/crates/rustc-codegen-cuda/examples/native_library/${binary}" + fi + local -a args=("--check-artifact") + if [[ ${FULL_DEBUG} -eq 1 ]]; then target="${LTOIR_MODERN_ARCH}"; fi + cubin="$(mktemp "${TMPDIR:-/tmp}/native-library.XXXXXX.cubin")" || return 1 + args+=("${target}" "${cubin}") + if [[ ${FULL_DEBUG} -eq 1 ]]; then args+=("--full-debug"); fi + if ! "${binary}" "${args[@]}" >>"${log}" 2>&1; then + rm -f "${cubin}" + echo "FAIL (native library embedded CUBIN check failed)" + return 1 + fi + if [[ ${FULL_DEBUG} -eq 1 ]]; then + elf_reader="$(command -v readelf || command -v llvm-readelf || true)" + if [[ -z "${elf_reader}" ]] \ + || ! sections="$("${elf_reader}" -W -S "${cubin}" 2>>"${log}")" \ + || ! dwarf="$("${elf_reader}" --debug-dump=info "${cubin}" 2>>"${log}")"; then + rm -f "${cubin}" + echo "FAIL (could not inspect native library CUBIN DWARF with readelf)" + return 1 + fi + rm -f "${cubin}" + if ! grep -q '[.]debug_info' <<<"${sections}" \ + || ! grep -q '[.]debug_line' <<<"${sections}" \ + || ! grep -q 'DW_TAG_compile_unit' <<<"${dwarf}" \ + || ! grep -q 'DW_TAG_subprogram' <<<"${dwarf}"; then + echo "FAIL (native library CUBIN is missing consumable DWARF)" + return 1 + fi + for symbol in one four; do + if ! grep -Eq "DW_AT_name.*: ${symbol}$" <<<"${dwarf}"; then + echo "FAIL (native library CUBIN is missing ${symbol} DWARF)" + return 1 + fi + done + echo "PASS (embedded CUBIN recorded debug=full and contains consumable DWARF)" + else + rm -f "${cubin}" + echo "PASS (embedded CUBIN and launch facts verified for ${target})" + fi +} + # The one configured cubin project cannot be judged through the root PTX # convention. Verify its complete versioned sidecar handshake and consume the # linked cubin's DWARF so a silently ignored interop debug policy cannot pass. @@ -1362,11 +1424,12 @@ run_full_debug_build() { # Full debug is unsupported by the legacy LLVM 7 NVVM dialect. Keep # the project's configured cubin path, but use the supported modern # dialect at the host target or its GPU-less sm_100 floor. - interop_cubin_identity) arch="${LTOIR_MODERN_ARCH}" ;; + interop_cubin_identity|native_library) arch="${LTOIR_MODERN_ARCH}" ;; esac if [[ -n "${arch}" ]]; then args+=("--arch=${arch}") fi + if [[ "${ex}" == "native_library" ]]; then args+=("--materialize-cubin"); fi if [[ ${VERBOSE} -eq 1 ]]; then cargo oxide "${args[@]}" 2>&1 | tee "${log}" @@ -1405,6 +1468,15 @@ run_cargo() { run_full_debug_build "${ex}" "${log}" "${cat}" return fi + # This fixture exercises compile-time linking of external device libraries. + # Its script supplies those inputs and verifies the embedded executable. + # Compile-only and full-debug retain the ordinary artifact-only FFI routes. + if [[ ${COMPILE_ONLY} -eq 0 && "${ex}" == "external_ltoir" ]]; then + bash scripts/check-external-ltoir.sh "${LTOIR_ARCH}" >"${log}" 2>&1 + CARGO_EC=$? + if [[ ${VERBOSE} -eq 1 ]]; then cat "${log}"; fi + return + fi # Rust `char` must remain plain i32 in both NVVM dialects. A runtime # round-trip cannot distinguish it from an incorrect zeroext i32 ABI. if [[ ${COMPILE_ONLY} -eq 1 && "${ex}" == "device_ffi_test" ]]; then @@ -2192,6 +2264,9 @@ run_cargo() { local verb="run" if [[ ${COMPILE_ONLY} -eq 1 ]]; then verb="build"; fi local -a args=("${verb}" "${ex}") + if [[ "${ex}" == "native_library" ]]; then + args+=("--materialize-cubin" "--arch=${LTOIR_ARCH}") + fi if [[ ${COMPILE_ONLY} -eq 0 && "${ex}" == "ex2_approx_f16" \ && "${host_cc}" =~ ^[0-9]+\.[0-9]+$ \ && $((10#${host_cc//./})) -lt 75 ]]; then diff --git a/cutile-rs/Cargo.lock b/cutile-rs/Cargo.lock index d95ed3effd..a16a645447 100644 --- a/cutile-rs/Cargo.lock +++ b/cutile-rs/Cargo.lock @@ -1251,8 +1251,6 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "oxide-artifacts" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d9a941c0c43d2dceaf25f5c9ca4c9f9cceb28dfa5e4e3cfd14e476f003e7c9" dependencies = [ "object 0.36.7", ]