Skip to main content

cubecl_core/frontend/element/
cube_elem.rs

1use core::fmt::Debug;
2
3use crate::{
4    self as cubecl, Assign, IntoRuntime,
5    frontend::{CanReadValue, ScalarPartialEq},
6    prelude::{Const, CubeDebug, IntoMut, Size},
7    unexpanded,
8};
9use cubecl_ir::{ConstantValue, ElemType, ExpandValue, features::TypeUsage, interfaces::TypedExt};
10use cubecl_macros::{comptime_type, cube, intrinsic};
11use cubecl_runtime::{client::ComputeClient, runtime::Runtime};
12use enumset::EnumSet;
13use pliron::r#type::TypeHandle;
14
15use crate::frontend::CubeType;
16use crate::ir::Scope;
17
18use super::{NativeAssign, NativeExpand};
19
20/// Form of `CubeType` that encapsulates all primitive types:
21/// Numeric, `UInt`, Bool
22pub trait CubePrimitive:
23    CubeType<ExpandType = NativeExpand<Self>>
24    + NativeAssign
25    + CanReadValue
26    + CubeDebug
27    + Send
28    + Sync
29    + 'static
30    + Clone
31    + Copy
32{
33    type Scalar: Scalar;
34    type Size: Size;
35    type WithScalar<S: Scalar>: CubePrimitive;
36
37    /// Return the element type to use on GPU.
38    fn as_type() -> TypeHandle {
39        unexpanded!()
40    }
41
42    /// Only native element types have a size.
43    fn size() -> usize {
44        size_of::<Self>()
45    }
46
47    /// Only native element types have a size.
48    fn size_bits() -> usize {
49        Self::size() * 8
50    }
51
52    fn from_expand_elem(elem: ExpandValue) -> Self::ExpandType {
53        NativeExpand::new(elem)
54    }
55
56    fn from_const_value(value: ConstantValue) -> Self;
57
58    fn into_lit_unchecked(self) -> Self {
59        self
60    }
61
62    fn packing_factor() -> usize {
63        unexpanded!()
64    }
65
66    fn vector_size() -> usize {
67        unexpanded!()
68    }
69
70    fn __expand_as_type(scope: &Scope) -> TypeHandle;
71
72    fn __expand_size(scope: &Scope) -> usize {
73        Self::__expand_as_type(scope).size(scope.ctx())
74    }
75
76    fn __expand_size_bits(scope: &Scope) -> usize {
77        Self::__expand_size(scope) * 8
78    }
79
80    fn __expand_packing_factor(scope: &Scope) -> usize {
81        Self::__expand_as_type(scope).packing_factor(scope.ctx())
82    }
83
84    fn __expand_vector_size(scope: &Scope) -> usize {
85        Self::__expand_as_type(scope).vector_size(scope.ctx())
86    }
87}
88
89pub trait CubePrimitiveExpand {
90    type Scalar: Clone + IntoMut + CubeDebug + Assign;
91    type WithScalar<S: Scalar>: Clone + IntoMut + CubeDebug + Assign;
92}
93
94impl<T: CubePrimitive> CubePrimitiveExpand for NativeExpand<T> {
95    type Scalar = NativeExpand<T::Scalar>;
96    type WithScalar<S: Scalar> = NativeExpand<T::WithScalar<S>>;
97}
98
99/// Marker trait for scalar primitives. Should be implemented for all scalar `CubePrimitive`s, but
100/// **not** for `Vector` or non-standard primitives like `Barrier`. Alternatively, treat these as
101/// types that can be stored in a [`Vector`]
102pub trait Scalar:
103    CubePrimitive<Scalar = Self, Size = Const<1>>
104    + Default
105    + IntoRuntime
106    + Debug
107    + ScalarPartialEq
108    + Into<ExpandValue>
109{
110    fn elem_type(_scope: &Scope) -> ElemType {
111        Self::elem_type_native()
112    }
113    fn elem_type_native() -> ElemType {
114        unexpanded!()
115    }
116
117    fn supported_uses<R: Runtime>(client: &ComputeClient<R>) -> EnumSet<TypeUsage> {
118        let ty = Self::elem_type_native();
119        client.features().type_usage(ty)
120    }
121}
122
123impl CubeDebug for TypeHandle {}
124impl CubeDebug for ElemType {}
125
126#[cube]
127pub fn elem_type_of<E: CubePrimitive>() -> comptime_type!(ElemType) {
128    intrinsic!(|scope| { E::Scalar::elem_type(scope) })
129}