Skip to main content

cubecl_core/frontend/operation/
assignation.rs

1use core::ops::{
2    Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
3};
4
5use cubecl_ir::{Scope, Value};
6
7use crate::{
8    frontend::{Array, Tensor},
9    prelude::*,
10};
11use crate::{ir, unexpanded};
12
13type ArrayExpand<E> = NativeExpand<Array<E>>;
14
15pub mod assign {
16    use cubecl_ir::{Memory, StoreOperands};
17    use ir::{Instruction, Operation};
18
19    use crate::prelude::NativeExpand;
20
21    use super::*;
22
23    /// Expand the assign operation.
24    ///
25    /// If you want to assign to a manually initialized const variable, look into
26    /// [`expand_no_check()`].
27    pub fn expand<C: CubeType>(
28        scope: &Scope,
29        input: NativeExpand<C>,
30        output: &mut NativeExpand<C>,
31    ) {
32        if output.expand.is_immutable() {
33            panic!("Can't assign a value to a const variable. Try to use `RuntimeCell`.");
34        }
35
36        expand_no_check(scope, input, output);
37    }
38    /// Expand the assign operation without any check.
39    ///
40    /// You can't assign to a const variable with this [`expand()`].
41    pub fn expand_no_check<C: CubeType>(
42        scope: &Scope,
43        input: NativeExpand<C>,
44        output: &mut NativeExpand<C>,
45    ) {
46        let output = output.expand;
47        let input = input.expand;
48
49        expand_element(scope, input, output);
50    }
51
52    pub fn expand_element(scope: &Scope, mut input: Value, output: Value) {
53        if output.vector_size() > 1 && input.vector_size() == 1 {
54            input = cast_expand_elem(scope, input, output.ty);
55        }
56
57        match (input.ty.is_ptr(), output.ty.is_ptr()) {
58            (true, false) => {
59                // ptr -> value = load
60                scope.register(Instruction::new(Memory::Load(input), output));
61            }
62            (false, true) => {
63                // value -> ptr = store
64                scope.register(Instruction::no_out(Memory::Store(StoreOperands {
65                    ptr: output,
66                    value: input,
67                })));
68            }
69            _ => {
70                // same ty = copy
71                scope.register(Instruction::new(Operation::Copy(input), output));
72            }
73        }
74    }
75}
76
77pub mod index_mut {
78    use super::*;
79
80    macro_rules! impl_index {
81        ($type: ty, $expand: ty) => {
82            impl<E: CubePrimitive> IndexMut<usize> for $type {
83                fn index_mut(&mut self, _idx: usize) -> &mut Self::Output {
84                    unexpanded!()
85                }
86            }
87
88            impl<E: CubePrimitive> IndexMut<Range<usize>> for $type {
89                fn index_mut(&mut self, _idx: Range<usize>) -> &mut Self::Output {
90                    unexpanded!()
91                }
92            }
93
94            impl<E: CubePrimitive> IndexMut<RangeFrom<usize>> for $type {
95                fn index_mut(&mut self, _idx: RangeFrom<usize>) -> &mut Self::Output {
96                    unexpanded!()
97                }
98            }
99
100            impl<E: CubePrimitive> IndexMut<RangeFull> for $type {
101                fn index_mut(&mut self, _idx: RangeFull) -> &mut Self::Output {
102                    unexpanded!()
103                }
104            }
105
106            impl<E: CubePrimitive> IndexMut<RangeInclusive<usize>> for $type {
107                fn index_mut(&mut self, _idx: RangeInclusive<usize>) -> &mut Self::Output {
108                    unexpanded!()
109                }
110            }
111
112            impl<E: CubePrimitive> IndexMut<RangeTo<usize>> for $type {
113                fn index_mut(&mut self, _idx: RangeTo<usize>) -> &mut Self::Output {
114                    unexpanded!()
115                }
116            }
117
118            impl<E: CubePrimitive> IndexMut<RangeToInclusive<usize>> for $type {
119                fn index_mut(&mut self, _idx: RangeToInclusive<usize>) -> &mut Self::Output {
120                    unexpanded!()
121                }
122            }
123
124            impl<E: CubePrimitive> IndexMutExpand<NativeExpand<usize>> for $expand {
125                fn __expand_index_mut_method(
126                    &mut self,
127                    scope: &Scope,
128                    index: NativeExpand<usize>,
129                ) -> &mut E::ExpandType {
130                    self.__expand_as_mut_slice_method(scope)
131                        .__expand_index_mut_method(scope, index)
132                }
133            }
134        };
135    }
136
137    impl_index!(Array<E>, NativeExpand<Array<E>>);
138    impl_index!(Tensor<E>, TensorExpand<E>);
139    impl_index!(Shared<[E]>, NativeExpand<Shared<[E]>>);
140
141    impl_slice_ranges!(ArrayExpand<E>);
142    impl_slice_ranges!(TensorExpand<E>);
143    impl_slice_ranges!(NativeExpand<Shared<[E]>>);
144}
145
146pub mod index {
147    use super::*;
148
149    macro_rules! impl_index {
150        ($type: ty, $expand: ty) => {
151            impl<E: CubePrimitive> Index<usize> for $type {
152                type Output = E;
153
154                fn index(&self, _idx: usize) -> &Self::Output {
155                    unexpanded!()
156                }
157            }
158
159            impl<E: CubePrimitive> Index<Range<usize>> for $type {
160                type Output = [E];
161
162                fn index(&self, _idx: Range<usize>) -> &Self::Output {
163                    unexpanded!()
164                }
165            }
166
167            impl<E: CubePrimitive> Index<RangeFrom<usize>> for $type {
168                type Output = [E];
169
170                fn index(&self, _idx: RangeFrom<usize>) -> &Self::Output {
171                    unexpanded!()
172                }
173            }
174
175            impl<E: CubePrimitive> Index<RangeFull> for $type {
176                type Output = [E];
177
178                fn index(&self, _idx: RangeFull) -> &Self::Output {
179                    unexpanded!()
180                }
181            }
182
183            impl<E: CubePrimitive> Index<RangeInclusive<usize>> for $type {
184                type Output = [E];
185
186                fn index(&self, _idx: RangeInclusive<usize>) -> &Self::Output {
187                    unexpanded!()
188                }
189            }
190
191            impl<E: CubePrimitive> Index<RangeTo<usize>> for $type {
192                type Output = [E];
193
194                fn index(&self, _idx: RangeTo<usize>) -> &Self::Output {
195                    unexpanded!()
196                }
197            }
198
199            impl<E: CubePrimitive> Index<RangeToInclusive<usize>> for $type {
200                type Output = [E];
201
202                fn index(&self, _idx: RangeToInclusive<usize>) -> &Self::Output {
203                    unexpanded!()
204                }
205            }
206
207            impl<E: CubePrimitive> IndexExpand<NativeExpand<usize>> for $expand {
208                type Output = NativeExpand<E>;
209
210                fn __expand_index_method(
211                    &self,
212                    scope: &Scope,
213                    index: NativeExpand<usize>,
214                ) -> &Self::Output {
215                    self.__expand_as_slice_method(scope)
216                        .__expand_index_method(scope, index)
217                }
218            }
219        };
220    }
221
222    impl_index!(Array<E>, NativeExpand<Array<E>>);
223    impl_index!(Tensor<E>, TensorExpand<E>);
224    impl_index!(Shared<[E]>, NativeExpand<Shared<[E]>>);
225}