diff --git a/tests/compiletests/ui/atomic/atomic_operations.rs b/tests/compiletests/ui/atomic/atomic_operations.rs new file mode 100644 index 00000000..48ae8d9c --- /dev/null +++ b/tests/compiletests/ui/atomic/atomic_operations.rs @@ -0,0 +1,38 @@ +// Test CUDA atomic operations compile correctly +// build-pass + +use core::sync::atomic::Ordering; +use cuda_std::atomic::{ + AtomicF32, AtomicF64, BlockAtomicF32, BlockAtomicF64, SystemAtomicF32, SystemAtomicF64, +}; +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_cuda_atomic_floats() { + // Device-scoped atomic float + let atomic_f32 = AtomicF32::new(3.14); + let _old = atomic_f32.fetch_add(1.0, Ordering::Relaxed); + let _val = atomic_f32.load(Ordering::Relaxed); + atomic_f32.store(2.718, Ordering::Relaxed); + + // Block-scoped atomic float + let block_atomic = BlockAtomicF32::new(1.5); + let _old = block_atomic.fetch_add(0.5, Ordering::Relaxed); + + // System-scoped atomic float + let system_atomic = SystemAtomicF32::new(0.0); + let _old = system_atomic.fetch_add(1.0, Ordering::Relaxed); + + // Test f64 as well + let atomic_f64 = AtomicF64::new(3.14159); + let _old = atomic_f64.fetch_add(1.0, Ordering::Relaxed); + + // Test block-scoped f64 + let block_f64 = BlockAtomicF64::new(2.718); + let _old = block_f64.fetch_sub(0.5, Ordering::Relaxed); + + // Test bitwise operations on floats + let _old = atomic_f32.fetch_and(3.14, Ordering::Relaxed); + let _old = atomic_f32.fetch_or(1.0, Ordering::Relaxed); + let _old = atomic_f32.fetch_xor(2.0, Ordering::Relaxed); +} diff --git a/tests/compiletests/ui/float/float_extensions.rs b/tests/compiletests/ui/float/float_extensions.rs new file mode 100644 index 00000000..a8b4e913 --- /dev/null +++ b/tests/compiletests/ui/float/float_extensions.rs @@ -0,0 +1,42 @@ +// Test CUDA float extension functions compile correctly +// build-pass + +use cuda_std::kernel; +use cuda_std::FloatExt; + +#[kernel] +pub unsafe fn test_float_extensions() { + let x = 3.14f32; + + // Test various float extension methods + let _cospi = x.cospi(); + let _erf = x.error_function(); + let _erfc = x.complementary_error_function(); + let _erfcx = x.scaled_complementary_error_function(); + + // Test frexp + let (_frac, _exp) = x.frexp(); + let _exp = x.unbiased_exp(); + + // Test bessel functions + let _j0 = x.j0(); + let _j1 = x.j1(); + let _jn = x.jn(2); + + // Test other functions + let _ldexp = x.ldexp(3); + let _lgamma = x.log_gamma(); + let _log1p = x.log1p(); + + // Test normcdf functions + let _normcdf = x.norm_cdf(); + let _normcdfinv = (0.5f32).inv_norm_cdf(); + + // Test sinpi + let _sinpi = x.sinpi(); + + // Test f64 as well + let y = 2.718f64; + let _cospi_f64 = y.cospi(); + let _erf_f64 = y.error_function(); +} diff --git a/tests/compiletests/ui/glam/mat3_vec3_multiply.rs b/tests/compiletests/ui/glam/mat3_vec3_multiply.rs new file mode 100644 index 00000000..adda6e82 --- /dev/null +++ b/tests/compiletests/ui/glam/mat3_vec3_multiply.rs @@ -0,0 +1,11 @@ +// Tests multiplying a `Mat3` by a `Vec3`. +// build-pass + +use cuda_std::glam; +use cuda_std::kernel; + +#[kernel] +pub unsafe fn mat3_vec3_multiply(input: glam::Mat3, output: *mut glam::Vec3) { + let vector = input * glam::Vec3::new(1.0, 2.0, 3.0); + *output = vector; +} diff --git a/tests/compiletests/ui/lang/consts/shallow-ref.rs b/tests/compiletests/ui/lang/consts/shallow-ref.rs new file mode 100644 index 00000000..0065d47f --- /dev/null +++ b/tests/compiletests/ui/lang/consts/shallow-ref.rs @@ -0,0 +1,26 @@ +// Test `&'static T` constants where the `T` values don't themselves contain +// references, and where the `T` values aren't immediately loaded from. + +// build-pass + +use cuda_std::glam::{Mat2, Vec2}; +use cuda_std::kernel; + +#[inline(never)] +fn scalar_load(r: &'static u32) -> u32 { + *r +} + +const ROT90: Mat2 = Mat2::from_cols_array_2d(&[[0.0, 1.0], [-1.0, 0.0]]); + +#[kernel] +pub unsafe fn test_shallow_ref( + scalar_out: *mut u32, + vec_in: Vec2, + bool_out: *mut u32, + vec_out: *mut Vec2, +) { + *scalar_out = scalar_load(&123); + *bool_out = (vec_in == Vec2::ZERO) as u32; + *vec_out = ROT90.transpose() * vec_in; +} diff --git a/tests/compiletests/ui/lang/control_flow/for_range.rs b/tests/compiletests/ui/lang/control_flow/for_range.rs new file mode 100644 index 00000000..ffac1e48 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/for_range.rs @@ -0,0 +1,8 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_for_range(i: u32) { + for _ in 0..i {} +} diff --git a/tests/compiletests/ui/lang/control_flow/for_range_signed.rs b/tests/compiletests/ui/lang/control_flow/for_range_signed.rs new file mode 100644 index 00000000..b1ce7a40 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/for_range_signed.rs @@ -0,0 +1,8 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_for_range_signed(i: i32) { + for _ in 0..i {} +} diff --git a/tests/compiletests/ui/lang/control_flow/for_with_custom_range_iter.rs b/tests/compiletests/ui/lang/control_flow/for_with_custom_range_iter.rs new file mode 100644 index 00000000..a16387e8 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/for_with_custom_range_iter.rs @@ -0,0 +1,31 @@ +// NOTE(eddyb) this tests `for` loop desugaring (with its call to `Iterator::next` +// and matching on the resulting `Option`), without relying on a `Range` iterator. +// More precisely, `Range` used to not compile, due to it using `mem::replace`, +// which, before https://github.com/rust-lang/rust/pull/83022, used to just call +// `mem::swap` (which has a block-wise optimization that can't work on SPIR-V). + +// build-pass + +use core::ops::Range; +use cuda_std::kernel; +use cuda_std::vek::num_traits::Num; + +struct RangeIter(Range); + +impl Iterator for RangeIter { + type Item = T; + fn next(&mut self) -> Option { + let x = self.0.start; + if x >= self.0.end { + None + } else { + self.0.start = x + T::one(); + Some(x) + } + } +} + +#[kernel] +pub unsafe fn test_custom_range_iter(i: i32) { + for _ in RangeIter(0..i) {} +} diff --git a/tests/compiletests/ui/lang/control_flow/if.rs b/tests/compiletests/ui/lang/control_flow/if.rs new file mode 100644 index 00000000..28e30aa7 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/if.rs @@ -0,0 +1,8 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_if(i: i32) { + if i > 0 {} +} diff --git a/tests/compiletests/ui/lang/control_flow/if_else.rs b/tests/compiletests/ui/lang/control_flow/if_else.rs new file mode 100644 index 00000000..be0bd95d --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/if_else.rs @@ -0,0 +1,10 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_if_else(i: i32) { + if i > 0 { + } else { + } +} diff --git a/tests/compiletests/ui/lang/control_flow/if_else_if_else.rs b/tests/compiletests/ui/lang/control_flow/if_else_if_else.rs new file mode 100644 index 00000000..8608acf3 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/if_else_if_else.rs @@ -0,0 +1,11 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_if_else_if_else(i: i32) { + if i > 0 { + } else if i < 0 { + } else { + } +} diff --git a/tests/compiletests/ui/lang/control_flow/if_if.rs b/tests/compiletests/ui/lang/control_flow/if_if.rs new file mode 100644 index 00000000..eb889b8e --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/if_if.rs @@ -0,0 +1,10 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_if_if(i: i32) { + if i > 0 { + if i < 10 {} + } +} diff --git a/tests/compiletests/ui/lang/control_flow/if_return_else.rs b/tests/compiletests/ui/lang/control_flow/if_return_else.rs new file mode 100644 index 00000000..53c7f68c --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/if_return_else.rs @@ -0,0 +1,11 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_if_return_else(i: i32) { + if i < 10 { + return; + } else { + } +} diff --git a/tests/compiletests/ui/lang/control_flow/if_return_else_return.rs b/tests/compiletests/ui/lang/control_flow/if_return_else_return.rs new file mode 100644 index 00000000..d045ced2 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/if_return_else_return.rs @@ -0,0 +1,12 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_if_return_else_return(i: i32) { + if i < 10 { + return; + } else { + return; + } +} diff --git a/tests/compiletests/ui/lang/control_flow/if_while.rs b/tests/compiletests/ui/lang/control_flow/if_while.rs new file mode 100644 index 00000000..7dddc220 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/if_while.rs @@ -0,0 +1,10 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_if_while(i: i32) { + if i == 0 { + while i < 10 {} + } +} diff --git a/tests/compiletests/ui/lang/control_flow/ifx2.rs b/tests/compiletests/ui/lang/control_flow/ifx2.rs new file mode 100644 index 00000000..7cf8867e --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/ifx2.rs @@ -0,0 +1,9 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_ifx2(i: i32) { + if i > 0 {} + if i > 1 {} +} diff --git a/tests/compiletests/ui/lang/control_flow/issue_283.rs b/tests/compiletests/ui/lang/control_flow/issue_283.rs new file mode 100644 index 00000000..eba0abee --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/issue_283.rs @@ -0,0 +1,49 @@ +// build-pass + +use cuda_std::glam::*; +use cuda_std::kernel; + +fn sphere_sdf(p: Vec3) -> f32 { + p.length() - 1.0 +} + +// Global scene to render +fn scene_sdf(p: Vec3) -> f32 { + sphere_sdf(p) +} + +fn render(eye: Vec3, dir: Vec3, start: f32, end: f32) -> f32 { + let max_marching_steps: i32 = 255; + let epsilon: f32 = 0.0001; + + let mut depth = start; + let mut i = 0; + + loop { + if i < max_marching_steps { + break; + } + + let dist = scene_sdf(eye + depth * dir); + + if dist < epsilon { + return depth; + } + + depth += dist; + + if depth >= end { + return end; + } + + i += 1; + } + + end +} + +#[kernel] +pub unsafe fn test_issue_283() { + let v = Vec3::new(1.0, 1.0, 1.0); + render(v, v, 1.0, 2.0); +} diff --git a/tests/compiletests/ui/lang/control_flow/loop.rs b/tests/compiletests/ui/lang/control_flow/loop.rs new file mode 100644 index 00000000..55fa27df --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/loop.rs @@ -0,0 +1,8 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_loop() { + loop {} +} diff --git a/tests/compiletests/ui/lang/control_flow/while.rs b/tests/compiletests/ui/lang/control_flow/while.rs new file mode 100644 index 00000000..88b45b74 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while.rs @@ -0,0 +1,8 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while(i: i32) { + while i < 10 {} +} diff --git a/tests/compiletests/ui/lang/control_flow/while_break.rs b/tests/compiletests/ui/lang/control_flow/while_break.rs new file mode 100644 index 00000000..35cd4671 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_break.rs @@ -0,0 +1,10 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_break(i: i32) { + while i < 10 { + break; + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_continue.rs b/tests/compiletests/ui/lang/control_flow/while_continue.rs new file mode 100644 index 00000000..c8de63e2 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_continue.rs @@ -0,0 +1,10 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_continue(i: i32) { + while i < 10 { + continue; + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_if_break.rs b/tests/compiletests/ui/lang/control_flow/while_if_break.rs new file mode 100644 index 00000000..50b6495a --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_if_break.rs @@ -0,0 +1,12 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_if_break(i: i32) { + while i < 10 { + if i == 0 { + break; + } + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_if_break_else_break.rs b/tests/compiletests/ui/lang/control_flow/while_if_break_else_break.rs new file mode 100644 index 00000000..acdad3ef --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_if_break_else_break.rs @@ -0,0 +1,14 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_if_break_else_break(i: i32) { + while i < 10 { + if i == 0 { + break; + } else { + break; + } + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_if_break_if_break.rs b/tests/compiletests/ui/lang/control_flow/while_if_break_if_break.rs new file mode 100644 index 00000000..2dc862ae --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_if_break_if_break.rs @@ -0,0 +1,15 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_if_break_if_break(i: i32) { + while i < 10 { + if i == 0 { + break; + } + if i == 1 { + break; + } + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_if_continue.rs b/tests/compiletests/ui/lang/control_flow/while_if_continue.rs new file mode 100644 index 00000000..1744efcd --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_if_continue.rs @@ -0,0 +1,12 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_if_continue(i: i32) { + while i < 10 { + if i == 0 { + continue; + } + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_if_continue_else_continue.rs b/tests/compiletests/ui/lang/control_flow/while_if_continue_else_continue.rs new file mode 100644 index 00000000..2c2a659d --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_if_continue_else_continue.rs @@ -0,0 +1,14 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_if_continue_else_continue(i: i32) { + while i < 10 { + if i == 0 { + continue; + } else { + continue; + } + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_return.rs b/tests/compiletests/ui/lang/control_flow/while_return.rs new file mode 100644 index 00000000..d4225c0b --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_return.rs @@ -0,0 +1,10 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_return(i: i32) { + while i < 10 { + return; + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_while.rs b/tests/compiletests/ui/lang/control_flow/while_while.rs new file mode 100644 index 00000000..1762c4f6 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_while.rs @@ -0,0 +1,10 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_while(i: i32) { + while i < 20 { + while i < 10 {} + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_while_break.rs b/tests/compiletests/ui/lang/control_flow/while_while_break.rs new file mode 100644 index 00000000..29e8cf5a --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_while_break.rs @@ -0,0 +1,12 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_while_break(i: i32) { + while i < 20 { + while i < 10 { + break; + } + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_while_continue.rs b/tests/compiletests/ui/lang/control_flow/while_while_continue.rs new file mode 100644 index 00000000..93e5228e --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_while_continue.rs @@ -0,0 +1,12 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_while_continue(i: i32) { + while i < 20 { + while i < 10 { + continue; + } + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_while_if_break.rs b/tests/compiletests/ui/lang/control_flow/while_while_if_break.rs new file mode 100644 index 00000000..201d32a9 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_while_if_break.rs @@ -0,0 +1,14 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_while_if_break(i: i32) { + while i < 20 { + while i < 10 { + if i > 10 { + break; + } + } + } +} diff --git a/tests/compiletests/ui/lang/control_flow/while_while_if_continue.rs b/tests/compiletests/ui/lang/control_flow/while_while_if_continue.rs new file mode 100644 index 00000000..5a511c10 --- /dev/null +++ b/tests/compiletests/ui/lang/control_flow/while_while_if_continue.rs @@ -0,0 +1,14 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_while_while_if_continue(i: i32) { + while i < 20 { + while i < 10 { + if i > 5 { + continue; + } + } + } +} diff --git a/tests/compiletests/ui/lang/core/array/init_array_i16.rs b/tests/compiletests/ui/lang/core/array/init_array_i16.rs new file mode 100644 index 00000000..61eb4b6b --- /dev/null +++ b/tests/compiletests/ui/lang/core/array/init_array_i16.rs @@ -0,0 +1,10 @@ +// Test creating an array. +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_init_array_i16(o: *mut i16) { + let array = [0i16; 4]; + *o = array[1]; +} diff --git a/tests/compiletests/ui/lang/core/array/init_array_i32.rs b/tests/compiletests/ui/lang/core/array/init_array_i32.rs new file mode 100644 index 00000000..4efb24f7 --- /dev/null +++ b/tests/compiletests/ui/lang/core/array/init_array_i32.rs @@ -0,0 +1,10 @@ +// Test creating an array. +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_init_array_i32(o: *mut i32) { + let array = [0i32; 4]; + *o = array[1]; +} diff --git a/tests/compiletests/ui/lang/core/array/init_array_i64.rs b/tests/compiletests/ui/lang/core/array/init_array_i64.rs new file mode 100644 index 00000000..0c161014 --- /dev/null +++ b/tests/compiletests/ui/lang/core/array/init_array_i64.rs @@ -0,0 +1,10 @@ +// Test creating an array. +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_init_array_i64(o: *mut i64) { + let array = [0i64; 4]; + *o = array[1]; +} diff --git a/tests/compiletests/ui/lang/core/array/init_array_i8.rs b/tests/compiletests/ui/lang/core/array/init_array_i8.rs new file mode 100644 index 00000000..b39b274f --- /dev/null +++ b/tests/compiletests/ui/lang/core/array/init_array_i8.rs @@ -0,0 +1,10 @@ +// Test creating an array. +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_init_array_i8(o: *mut i8) { + let array = [0i8; 4]; + *o = array[1]; +} diff --git a/tests/compiletests/ui/lang/core/intrinsics/bswap.rs b/tests/compiletests/ui/lang/core/intrinsics/bswap.rs new file mode 100644 index 00000000..1a8d3567 --- /dev/null +++ b/tests/compiletests/ui/lang/core/intrinsics/bswap.rs @@ -0,0 +1,42 @@ +// Test bswap intrinsic +// build-pass + +#![allow(internal_features)] +#![feature(core_intrinsics)] +#![no_std] + +use core::intrinsics::bswap; +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_bswap() { + let original_i16: i16 = 0x1234; + let swapped_i16 = bswap(original_i16); + + let original_neg_i16: i16 = -0x1234; + let swapped_neg_i16 = bswap(original_neg_i16); + + let original_i32: i32 = 0x12345678; + let swapped_i32 = bswap(original_i32); + + let original_neg_i32: i32 = -0x12345678; + let swapped_neg_i32 = bswap(original_neg_i32); + + let original_zero_i16: i16 = 0; + let swapped_zero_i16 = bswap(original_zero_i16); + + let original_zero_i32: i32 = 0; + let swapped_zero_i32 = bswap(original_zero_i32); + + let original_u8: u8 = 0x12; + let swapped_u8 = bswap(original_u8); + + let original_u16: u16 = 0x1234; + let swapped_u16 = bswap(original_u16); + + let original_u32: u32 = 0x12345678; + let swapped_u32 = bswap(original_u32); + + let original_u64: u64 = 0x123456789ABCDEF0; + let swapped_u64 = bswap(original_u64); +} diff --git a/tests/compiletests/ui/lang/core/intrinsics/leading_zeros.rs b/tests/compiletests/ui/lang/core/intrinsics/leading_zeros.rs new file mode 100644 index 00000000..916df594 --- /dev/null +++ b/tests/compiletests/ui/lang/core/intrinsics/leading_zeros.rs @@ -0,0 +1,47 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_leading_zeros() { + // 8-bit tests + assert!(0b00000000_u8.leading_zeros() == 8); + assert!(0b00000001_u8.leading_zeros() == 7); + assert!(0b00010000_u8.leading_zeros() == 3); + assert!(0b10000000_u8.leading_zeros() == 0); + assert!(0b11111111_u8.leading_zeros() == 0); + + // 16-bit tests + assert!(0x0000_u16.leading_zeros() == 16); + assert!(0x0001_u16.leading_zeros() == 15); + assert!(0x0100_u16.leading_zeros() == 7); + assert!(0x8000_u16.leading_zeros() == 0); + assert!(0xFFFF_u16.leading_zeros() == 0); + + // 32-bit tests + assert!(0x00000000_u32.leading_zeros() == 32); + assert!(0x00000001_u32.leading_zeros() == 31); + assert!(0x00010000_u32.leading_zeros() == 15); + assert!(0x80000000_u32.leading_zeros() == 0); + assert!(0xFFFFFFFF_u32.leading_zeros() == 0); + + // 64-bit tests + assert!(0x0000000000000000_u64.leading_zeros() == 64); + assert!(0x0000000000000001_u64.leading_zeros() == 63); + assert!(0x8000000000000000_u64.leading_zeros() == 0); + assert!(0xFFFFFFFFFFFFFFFF_u64.leading_zeros() == 0); + assert!(0x00000000_12345678_u64.leading_zeros() == 32); + assert!(0x00000000_80000000_u64.leading_zeros() == 32); + assert!(0x00100000_00000000_u64.leading_zeros() == 11); + assert!(0x12345678_00000000_u64.leading_zeros() == 3); + + // Signed integers (should behave the same as unsigned) + assert!(0i8.leading_zeros() == 8); + assert!((-1i8).leading_zeros() == 0); + assert!(0i16.leading_zeros() == 16); + assert!((-1i16).leading_zeros() == 0); + assert!(0i32.leading_zeros() == 32); + assert!((-1i32).leading_zeros() == 0); + assert!(0i64.leading_zeros() == 64); + assert!((-1i64).leading_zeros() == 0); +} diff --git a/tests/compiletests/ui/lang/core/intrinsics/log10.rs b/tests/compiletests/ui/lang/core/intrinsics/log10.rs new file mode 100644 index 00000000..a133c7e8 --- /dev/null +++ b/tests/compiletests/ui/lang/core/intrinsics/log10.rs @@ -0,0 +1,14 @@ +// Test log10 intrinsic +// build-pass + +#![allow(internal_features)] +#![feature(core_intrinsics)] +#![no_std] + +use cuda_std::kernel; +use cuda_std::GpuFloat; + +#[kernel] +pub unsafe fn test_log10(input: *const f32, output: *mut f32) { + *output = (*input).log10(); +} diff --git a/tests/compiletests/ui/lang/core/intrinsics/trailing_zeros.rs b/tests/compiletests/ui/lang/core/intrinsics/trailing_zeros.rs new file mode 100644 index 00000000..9f666074 --- /dev/null +++ b/tests/compiletests/ui/lang/core/intrinsics/trailing_zeros.rs @@ -0,0 +1,47 @@ +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_trailing_zeros() { + // 8-bit tests + assert!(0b00000000_u8.trailing_zeros() == 8); + assert!(0b00000001_u8.trailing_zeros() == 0); + assert!(0b00010000_u8.trailing_zeros() == 4); + assert!(0b10000000_u8.trailing_zeros() == 7); + assert!(0b11111110_u8.trailing_zeros() == 1); + + // 16-bit tests + assert!(0x0000_u16.trailing_zeros() == 16); + assert!(0x0001_u16.trailing_zeros() == 0); + assert!(0x0100_u16.trailing_zeros() == 8); + assert!(0x8000_u16.trailing_zeros() == 15); + assert!(0xFFFE_u16.trailing_zeros() == 1); + + // 32-bit tests + assert!(0x00000000_u32.trailing_zeros() == 32); + assert!(0x00000001_u32.trailing_zeros() == 0); + assert!(0x00010000_u32.trailing_zeros() == 16); + assert!(0x80000000_u32.trailing_zeros() == 31); + assert!(0xFFFFFFFE_u32.trailing_zeros() == 1); + + // 64-bit tests + assert!(0x0000000000000000_u64.trailing_zeros() == 64); + assert!(0x0000000000000001_u64.trailing_zeros() == 0); + assert!(0x8000000000000000_u64.trailing_zeros() == 63); + assert!(0xFFFFFFFFFFFFFFFE_u64.trailing_zeros() == 1); + assert!(0x12340000_00000000_u64.trailing_zeros() == 32); + assert!(0x00000001_00000000_u64.trailing_zeros() == 32); + assert!(0x00000000_00001000_u64.trailing_zeros() == 12); + assert!(0x00000000_80000000_u64.trailing_zeros() == 31); + + // Signed integers (should behave the same as unsigned) + assert!(0i8.trailing_zeros() == 8); + assert!((-1i8).trailing_zeros() == 0); + assert!(0i16.trailing_zeros() == 16); + assert!((-1i16).trailing_zeros() == 0); + assert!(0i32.trailing_zeros() == 32); + assert!((-1i32).trailing_zeros() == 0); + assert!(0i64.trailing_zeros() == 64); + assert!((-1i64).trailing_zeros() == 0); +} diff --git a/tests/compiletests/ui/lang/core/mem/create_unitialized_memory.rs b/tests/compiletests/ui/lang/core/mem/create_unitialized_memory.rs new file mode 100644 index 00000000..0c6226e9 --- /dev/null +++ b/tests/compiletests/ui/lang/core/mem/create_unitialized_memory.rs @@ -0,0 +1,20 @@ +// Test creating uninitialized memory. +// build-pass + +use core::mem::MaybeUninit; +use cuda_std::kernel; + +const MAYBEI32: MaybeUninit<&i32> = MaybeUninit::<&i32>::uninit(); + +pub fn create_uninit_and_write() { + let mut maybei32 = MAYBEI32; + unsafe { + maybei32.as_mut_ptr().write(&0); + } + let _maybei32 = unsafe { maybei32.assume_init() }; +} + +#[kernel] +pub unsafe fn test_uninit_memory() { + create_uninit_and_write(); +} diff --git a/tests/compiletests/ui/lang/core/ptr/allocate_null.rs b/tests/compiletests/ui/lang/core/ptr/allocate_null.rs new file mode 100644 index 00000000..62896dd8 --- /dev/null +++ b/tests/compiletests/ui/lang/core/ptr/allocate_null.rs @@ -0,0 +1,12 @@ +// Tests allocating a null pointer at `const` time. +// build-pass + +use core::ptr::null; +use cuda_std::kernel; + +const NULL_PTR: *const i32 = null(); + +#[kernel] +pub unsafe fn test_allocate_null() { + let _null_ptr = NULL_PTR; +} diff --git a/tests/compiletests/ui/lang/core/ptr/allocate_vec_like.rs b/tests/compiletests/ui/lang/core/ptr/allocate_vec_like.rs new file mode 100644 index 00000000..a502a338 --- /dev/null +++ b/tests/compiletests/ui/lang/core/ptr/allocate_vec_like.rs @@ -0,0 +1,19 @@ +// Tests using a vector like pointer at `const` time. +// build-pass + +#![allow(internal_features)] +#![feature(ptr_internals)] + +use core::ptr::Unique; +use cuda_std::kernel; + +const VEC_LIKE: (Unique, usize, usize) = (Unique::::dangling(), 0, 0); + +pub fn assign_vec_like() { + let _vec_like = VEC_LIKE; +} + +#[kernel] +pub unsafe fn test_allocate_vec_like() { + assign_vec_like(); +} diff --git a/tests/compiletests/ui/lang/core/ref/member_ref_arg.rs b/tests/compiletests/ui/lang/core/ref/member_ref_arg.rs new file mode 100644 index 00000000..93711664 --- /dev/null +++ b/tests/compiletests/ui/lang/core/ref/member_ref_arg.rs @@ -0,0 +1,21 @@ +// build-pass + +use cuda_std::kernel; + +struct S { + x: u32, + y: u32, +} + +#[inline(never)] +fn f(x: &u32) {} + +#[inline(never)] +fn g(xy: (&u32, &u32)) {} + +#[kernel] +pub unsafe fn test_member_ref_arg() { + let s = S { x: 2, y: 2 }; + f(&s.x); + g((&s.x, &s.y)); +} diff --git a/tests/compiletests/ui/lang/core/ref/zst_member_ref_arg.rs b/tests/compiletests/ui/lang/core/ref/zst_member_ref_arg.rs new file mode 100644 index 00000000..a9761380 --- /dev/null +++ b/tests/compiletests/ui/lang/core/ref/zst_member_ref_arg.rs @@ -0,0 +1,19 @@ +// build-pass + +use cuda_std::kernel; + +struct A; +struct B; + +struct S { + x: A, + y: B, +} + +fn f(x: &B) {} + +#[kernel] +pub unsafe fn test_zst_member_ref_arg() { + let s = S { x: A, y: B }; + f(&s.y); +} diff --git a/tests/compiletests/ui/lang/core/unwrap_or.rs b/tests/compiletests/ui/lang/core/unwrap_or.rs new file mode 100644 index 00000000..1deb6858 --- /dev/null +++ b/tests/compiletests/ui/lang/core/unwrap_or.rs @@ -0,0 +1,12 @@ +#![crate_name = "unwrap_or"] + +// unwrap_or generates some memory-bools (as u8). Test to make sure they're fused away. + +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_unwrap_or(out: *mut u32) { + *out = None.unwrap_or(15); +} diff --git a/tests/compiletests/ui/lang/f32/signum.rs b/tests/compiletests/ui/lang/f32/signum.rs new file mode 100644 index 00000000..09beaa23 --- /dev/null +++ b/tests/compiletests/ui/lang/f32/signum.rs @@ -0,0 +1,9 @@ +// Test that `signum` works. +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn test_signum(i: f32, o: *mut f32) { + *o = i.signum(); +} diff --git a/tests/compiletests/ui/lang/u32/bit_reverse.rs b/tests/compiletests/ui/lang/u32/bit_reverse.rs new file mode 100644 index 00000000..f8a8379f --- /dev/null +++ b/tests/compiletests/ui/lang/u32/bit_reverse.rs @@ -0,0 +1,45 @@ +// Test all trailing and leading zeros. No need to test ones, they just call the zero variant with !value + +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn reverse_bits_u8(buffer: *const u8, out: *mut u8) { + *out = (*buffer).reverse_bits(); +} + +#[kernel] +pub unsafe fn reverse_bits_u16(buffer: *const u16, out: *mut u16) { + *out = (*buffer).reverse_bits(); +} + +#[kernel] +pub unsafe fn reverse_bits_u32(buffer: *const u32, out: *mut u32) { + *out = (*buffer).reverse_bits(); +} + +#[kernel] +pub unsafe fn reverse_bits_u64(buffer: *const u64, out: *mut u64) { + *out = (*buffer).reverse_bits(); +} + +#[kernel] +pub unsafe fn reverse_bits_i8(buffer: *const i8, out: *mut i8) { + *out = (*buffer).reverse_bits(); +} + +#[kernel] +pub unsafe fn reverse_bits_i16(buffer: *const i16, out: *mut i16) { + *out = (*buffer).reverse_bits(); +} + +#[kernel] +pub unsafe fn reverse_bits_i32(buffer: *const i32, out: *mut i32) { + *out = (*buffer).reverse_bits(); +} + +#[kernel] +pub unsafe fn reverse_bits_i64(buffer: *const i64, out: *mut i64) { + *out = (*buffer).reverse_bits(); +} diff --git a/tests/compiletests/ui/lang/u32/count_ones.rs b/tests/compiletests/ui/lang/u32/count_ones.rs new file mode 100644 index 00000000..cbb36fcc --- /dev/null +++ b/tests/compiletests/ui/lang/u32/count_ones.rs @@ -0,0 +1,45 @@ +// Test all trailing and leading zeros. No need to test ones, they just call the zero variant with !value + +// build-pass + +use cuda_std::kernel; + +#[kernel] +pub unsafe fn count_ones_u8(buffer: *const u8, out: *mut u32) { + *out = (*buffer).count_ones(); +} + +#[kernel] +pub unsafe fn count_ones_u16(buffer: *const u16, out: *mut u32) { + *out = (*buffer).count_ones(); +} + +#[kernel] +pub unsafe fn count_ones_u32(buffer: *const u32, out: *mut u32) { + *out = (*buffer).count_ones(); +} + +#[kernel] +pub unsafe fn count_ones_u64(buffer: *const u64, out: *mut u32) { + *out = (*buffer).count_ones(); +} + +#[kernel] +pub unsafe fn count_ones_i8(buffer: *const i8, out: *mut u32) { + *out = (*buffer).count_ones(); +} + +#[kernel] +pub unsafe fn count_ones_i16(buffer: *const i16, out: *mut u32) { + *out = (*buffer).count_ones(); +} + +#[kernel] +pub unsafe fn count_ones_i32(buffer: *const i32, out: *mut u32) { + *out = (*buffer).count_ones(); +} + +#[kernel] +pub unsafe fn count_ones_i64(buffer: *const i64, out: *mut u32) { + *out = (*buffer).count_ones(); +} diff --git a/tests/compiletests/ui/shared/shared_memory.rs b/tests/compiletests/ui/shared/shared_memory.rs new file mode 100644 index 00000000..675e2e4b --- /dev/null +++ b/tests/compiletests/ui/shared/shared_memory.rs @@ -0,0 +1,33 @@ +// Test CUDA shared memory allocations compile correctly +// build-pass + +use cuda_std::kernel; +use cuda_std::{shared_array, thread}; + +#[kernel] +pub unsafe fn test_static_shared_memory() { + // Allocate static shared memory for 256 i32 values + let shared_data = shared_array![i32; 256]; + + let tid = thread::thread_idx_x() as usize; + + // Write to shared memory + *shared_data.add(tid) = tid as i32; + + // Synchronize threads before reading + thread::sync_threads(); + + // Read from shared memory + let _value = *shared_data.add(tid); +} + +#[kernel] +pub unsafe fn test_different_types() { + // Test different array types + let _shared_u32 = shared_array![u32; 128]; + let _shared_f32 = shared_array![f32; 64]; + let _shared_u8 = shared_array![u8; 512]; + + // Test arrays of arrays + let _shared_vec3 = shared_array![[f32; 3]; 32]; +} diff --git a/tests/compiletests/ui/thread/thread_functions.rs b/tests/compiletests/ui/thread/thread_functions.rs deleted file mode 100644 index 5f732a4b..00000000 --- a/tests/compiletests/ui/thread/thread_functions.rs +++ /dev/null @@ -1,17 +0,0 @@ -// build-pass - -// This test verifies CUDA thread functions are available and working - -use cuda_std::kernel; -use cuda_std::thread; - -#[kernel] -pub unsafe fn thread_functions_test() { - // Thread identification functions - let _tid = thread::thread_idx_x(); - let _bid = thread::block_idx_x(); - let _bdim = thread::block_dim_x(); - - // Synchronization function - thread::sync_threads(); -} diff --git a/tests/compiletests/ui/thread/thread_indexing.rs b/tests/compiletests/ui/thread/thread_indexing.rs new file mode 100644 index 00000000..3ab21939 --- /dev/null +++ b/tests/compiletests/ui/thread/thread_indexing.rs @@ -0,0 +1,28 @@ +// Test CUDA thread indexing functions compile correctly +// build-pass + +use cuda_std::kernel; +use cuda_std::thread; + +#[kernel] +pub unsafe fn test_thread_indices() { + // Thread indices within block + let _tx = thread::thread_idx_x(); + let _ty = thread::thread_idx_y(); + let _tz = thread::thread_idx_z(); + + // Block indices within grid + let _bx = thread::block_idx_x(); + let _by = thread::block_idx_y(); + let _bz = thread::block_idx_z(); + + // Block dimensions + let _bdx = thread::block_dim_x(); + let _bdy = thread::block_dim_y(); + let _bdz = thread::block_dim_z(); + + // Grid dimensions + let _gdx = thread::grid_dim_x(); + let _gdy = thread::grid_dim_y(); + let _gdz = thread::grid_dim_z(); +} diff --git a/tests/compiletests/ui/thread/thread_sync.rs b/tests/compiletests/ui/thread/thread_sync.rs new file mode 100644 index 00000000..b5db6c27 --- /dev/null +++ b/tests/compiletests/ui/thread/thread_sync.rs @@ -0,0 +1,16 @@ +// Test CUDA thread synchronization functions compile correctly +// build-pass + +use cuda_std::kernel; +use cuda_std::thread; + +#[kernel] +pub unsafe fn test_synchronization() { + // Test thread synchronization + thread::sync_threads(); + + // Test memory fences + thread::device_fence(); + thread::grid_fence(); + thread::system_fence(); +} diff --git a/tests/compiletests/ui/warp/warp_functions.rs b/tests/compiletests/ui/warp/warp_functions.rs new file mode 100644 index 00000000..32af2bec --- /dev/null +++ b/tests/compiletests/ui/warp/warp_functions.rs @@ -0,0 +1,20 @@ +// Test CUDA warp-level functions compile correctly +// build-pass + +use cuda_std::kernel; +use cuda_std::warp; + +#[kernel] +pub unsafe fn test_warp_functions() { + // Test lane ID function + let _lane = warp::lane_id(); + + // Test active mask function + let _mask = warp::activemask(); + + // Test warp sync with full mask + warp::sync_warp(0xFFFFFFFF); + + // Test warp sync with partial mask + warp::sync_warp(0x0000FFFF); +}