ruda_kernel/dsl/post_processing/
checked_io.rs1use alloc::{string::String, vec::Vec};
2use ruda_core::ir::{Allocator, Instruction, ManagedVariable, Operation, Operator, Processor, Scope};
3use ruda::runtime::server::ExecutionMode;
4
5use crate::dsl::{
6 define_scalar, define_size,
7 io::{
8 expand_checked_index_assign, expand_validate_index_assign, read_tensor_atomic_checked,
9 read_tensor_atomic_validate, read_tensor_checked, read_tensor_validate,
10 },
11 prelude::Vector,
12};
13
14define_scalar!(ElemA);
15define_size!(SizeA);
16
17#[derive(new, Debug)]
18pub struct CheckedIoProcessor {
19 mode: ExecutionMode,
20 kernel_name: String,
21}
22
23impl Processor for CheckedIoProcessor {
24 fn transform(
25 &self,
26 processing: ruda_core::ir::ScopeProcessing,
27 allocator: Allocator,
28 ) -> ruda_core::ir::ScopeProcessing {
29 match self.mode {
30 ExecutionMode::Checked => self.transform_checked(processing, allocator),
31 ExecutionMode::Unchecked => processing,
32 ExecutionMode::Validate => self.transform_validate(processing, allocator),
33 }
34 }
35}
36
37impl CheckedIoProcessor {
38 fn transform_checked(
39 &self,
40 mut processing: ruda_core::ir::ScopeProcessing,
41 allocator: Allocator,
42 ) -> ruda_core::ir::ScopeProcessing {
43 let mut instructions = Vec::new();
44 core::mem::swap(&mut processing.instructions, &mut instructions);
45
46 for instruction in instructions {
47 let lowered = matches!(instruction.operation, Operation::TypedMemory(_))
48 .then(|| instruction.clone().lower_typed_memory().expect("valid typed memory instruction"));
49 let operation = lowered.as_ref().map_or(&instruction.operation, |instruction| &instruction.operation);
50 if let Operation::Operator(operator) = operation {
51 match operator {
52 Operator::Index(op) => {
53 let has_length = op.list.has_length();
54
55 if has_length {
56 let list = ManagedVariable::Plain(op.list);
57 let index = ManagedVariable::Plain(op.index);
58 let mut scope = Scope::root(false)
59 .with_allocator(allocator.clone())
60 .with_types(processing.typemap.clone());
61 scope.register_type::<ElemA>(op.list.storage_type());
62 scope.register_size::<SizeA>(op.list.vector_size());
63
64 let input = if op.list.ty.is_atomic() {
65 read_tensor_atomic_checked::expand::<ElemA>(
70 &mut scope,
71 list.into(),
72 index.into(),
73 op.unroll_factor,
74 )
75 .expand
76 } else {
77 read_tensor_checked::expand::<Vector<ElemA, SizeA>>(
78 &mut scope,
79 list.into(),
80 index.into(),
81 op.unroll_factor,
82 )
83 .expand
84 };
85 let tmp_processing = scope.process([]);
86
87 for inst in tmp_processing.instructions {
88 processing.instructions.push(instruction.retag_typed_memory(inst));
89 }
90 for var in tmp_processing.variables {
91 processing.variables.push(var);
92 }
93
94 processing
95 .instructions
96 .push(Instruction::new(Operation::Copy(*input), instruction.out()));
97 continue;
98 }
99 }
100 Operator::IndexAssign(op) => {
101 let out = instruction.out();
102
103 if out.has_length() {
104 let mut scope = Scope::root(false)
105 .with_allocator(allocator.clone())
106 .with_types(processing.typemap.clone());
107 expand_checked_index_assign(
108 &mut scope,
109 op.index,
110 op.value,
111 out,
112 op.unroll_factor,
113 );
114
115 let tmp_processing = scope.process([]);
116
117 for inst in tmp_processing.instructions {
118 processing.instructions.push(instruction.retag_typed_memory(inst));
119 }
120 for var in tmp_processing.variables {
121 processing.variables.push(var);
122 }
123
124 continue;
125 }
126 }
127 _ => {}
128 }
129 }
130
131 processing.instructions.push(instruction);
133 }
134 processing
135 }
136
137 fn transform_validate(
138 &self,
139 mut processing: ruda_core::ir::ScopeProcessing,
140 allocator: Allocator,
141 ) -> ruda_core::ir::ScopeProcessing {
142 let mut instructions = Vec::new();
143 core::mem::swap(&mut processing.instructions, &mut instructions);
144
145 for instruction in instructions {
146 let lowered = matches!(instruction.operation, Operation::TypedMemory(_))
147 .then(|| instruction.clone().lower_typed_memory().expect("valid typed memory instruction"));
148 let operation = lowered.as_ref().map_or(&instruction.operation, |instruction| &instruction.operation);
149 if let Operation::Operator(operator) = operation {
150 match operator {
151 Operator::Index(op) => {
152 let has_length = op.list.has_length();
153
154 if has_length {
155 let list = ManagedVariable::Plain(op.list);
156 let index = ManagedVariable::Plain(op.index);
157 let mut scope = Scope::root(false)
158 .with_allocator(allocator.clone())
159 .with_types(processing.typemap.clone());
160 scope.register_type::<ElemA>(op.list.storage_type());
161 scope.register_size::<SizeA>(op.list.vector_size());
162
163 let input = if op.list.ty.is_atomic() {
164 read_tensor_atomic_validate::expand::<ElemA>(
169 &mut scope,
170 list.into(),
171 index.into(),
172 op.unroll_factor,
173 self.kernel_name.clone(),
174 )
175 .expand
176 } else {
177 read_tensor_validate::expand::<Vector<ElemA, SizeA>>(
178 &mut scope,
179 list.into(),
180 index.into(),
181 op.unroll_factor,
182 self.kernel_name.clone(),
183 )
184 .expand
185 };
186 let tmp_processing = scope.process([]);
187
188 for inst in tmp_processing.instructions {
189 processing.instructions.push(instruction.retag_typed_memory(inst));
190 }
191 for var in tmp_processing.variables {
192 processing.variables.push(var);
193 }
194
195 processing
196 .instructions
197 .push(Instruction::new(Operation::Copy(*input), instruction.out()));
198 continue;
199 }
200 }
201 Operator::IndexAssign(op) => {
202 let out = instruction.out();
203
204 if out.has_length() {
205 let mut scope = Scope::root(false)
206 .with_allocator(allocator.clone())
207 .with_types(processing.typemap.clone());
208 expand_validate_index_assign(
209 &mut scope,
210 op.index,
211 op.value,
212 out,
213 op.unroll_factor,
214 &self.kernel_name,
215 );
216
217 let tmp_processing = scope.process([]);
218
219 for inst in tmp_processing.instructions {
220 processing.instructions.push(instruction.retag_typed_memory(inst));
221 }
222 for var in tmp_processing.variables {
223 processing.variables.push(var);
224 }
225
226 continue;
227 }
228 }
229 _ => {}
230 }
231 }
232
233 processing.instructions.push(instruction);
235 }
236 processing
237 }
238}