gpu/
print.rs

1use core::marker::Sized;
2
3use num_traits::AsPrimitive;
4
5#[rustc_diagnostic_item = "gpu::printf"]
6#[gpu_codegen::device]
7#[inline(never)]
8pub fn printf(_fmt: &'static str) {
9    unimplemented!()
10}
11
12trait SupportedPrintfArg: AsPrimitive<Self::Output> {
13    const HOLDER: &'static str;
14    type Output: Copy + SupportedPrintfArg;
15}
16
17#[allow(private_bounds)]
18pub trait PushPrintfArg: SupportedPrintfArg + Sized {
19    /// Push an argument to the printf function.
20    fn _push_printf_arg(self, _holder: &'static str);
21
22    #[gpu_codegen::device]
23    #[inline(always)]
24    fn push_printf_arg(self) {
25        self.as_()._push_printf_arg(Self::HOLDER);
26    }
27}
28
29impl<T: SupportedPrintfArg + Sized> PushPrintfArg for T {
30    #[rustc_diagnostic_item = "gpu::print_args"]
31    #[gpu_codegen::device]
32    #[inline(never)]
33    fn _push_printf_arg(self, _holder: &'static str) {
34        // This will be implemented by the macro below.
35        unimplemented!()
36    }
37}
38
39macro_rules! def_push_printf_arg {
40    ($t:ty, $ot: ty, $holder: literal) => {
41        impl SupportedPrintfArg for $t {
42            const HOLDER: &'static str = $holder;
43            type Output = $ot;
44        }
45    };
46    () => {};
47}
48
49def_push_printf_arg!(u8, u32, "%u");
50def_push_printf_arg!(u16, u32, "%u");
51def_push_printf_arg!(u32, u32, "%u");
52def_push_printf_arg!(u64, u64, "%lu");
53def_push_printf_arg!(u128, u128, "%llu");
54def_push_printf_arg!(i8, i32, "%d");
55def_push_printf_arg!(i16, i32, "%d");
56def_push_printf_arg!(i32, i32, "%d");
57def_push_printf_arg!(i64, i64, "%ld");
58def_push_printf_arg!(i128, i128, "%lld");
59def_push_printf_arg!(usize, usize, "%ld");
60def_push_printf_arg!(isize, isize, "%ld");
61def_push_printf_arg!(f32, f32, "%f");
62def_push_printf_arg!(f64, f64, "%f");
63def_push_printf_arg!(bool, u32, "%d");
64
65#[macro_export]
66macro_rules! println {
67    ($fmt:literal) => {{
68        $crate::printf($fmt);
69    }};
70    ($fmt:literal, $($arg:expr),+ $(,)?) => {{
71        use $crate::PushPrintfArg;
72        $(
73            ($arg).push_printf_arg();
74        )+
75        $crate::printf($fmt);
76    }};
77}
78
79#[macro_export]
80macro_rules! println_once {
81    ($($any:tt)*) => {{
82        if $crate::thread_id::<$crate::DimX>() == 0 && $crate::thread_id::<$crate::DimY>() == 0 && $crate::thread_id::<$crate::DimZ>() == 0 && $crate::block_id::<$crate::DimX>() == 0 && $crate::block_id::<$crate::DimY>() == 0 && $crate::block_id::<$crate::DimZ>() == 0 {
83            $crate::println!($($any)*);
84        }
85    }}
86}
87
88#[cfg(debug_assertions)]
89#[macro_export]
90macro_rules! debug_once {
91    ($($any:tt)*) => {{
92        println_once!($($any)*);
93    }}
94}
95
96#[cfg(not(debug_assertions))]
97#[macro_export]
98macro_rules! debug_once {
99    ($($any:tt)*) => {{}};
100}