1use crate::{
2 constant::{Constant, ConstantValue},
3 error::{anyhow, Error, Result},
4 spirv::Op,
5 ty::{ScalarType, Type},
6};
7use fnv::FnvHashMap as HashMap;
8
9type InstrId = u32;
10
11fn const_id_not_found(id: InstrId) -> Error {
12 anyhow!("constant id {} not found", id)
13}
14fn evaluation_failed(op: Op, result_ty: &Type, operands: &[ConstantValue]) -> Error {
15 anyhow!("cannot evaluate {op:?} with {operands:?} as {result_ty:?}")
16}
17fn broken_expr_tree(id: InstrId) -> Error {
18 anyhow!("broken expression tree at id {}", id)
19}
20
21#[derive(Default)]
22pub struct Evaluator {
23 ext_instr_set: HashMap<InstrId, String>,
24 values: HashMap<InstrId, Constant>,
25}
26impl Evaluator {
27 pub fn new() -> Self {
28 Self {
29 ext_instr_set: HashMap::default(),
30 values: HashMap::default(),
31 }
32 }
33
34 pub fn import_ext_instr_set(&mut self, id: InstrId, name: String) -> Result<()> {
35 use std::collections::hash_map::Entry;
36 match self.ext_instr_set.entry(id) {
37 Entry::Vacant(entry) => {
38 entry.insert(name);
39 Ok(())
40 }
41 Entry::Occupied(_) => Err(anyhow!("extended instruction set id {} already exists", id)),
42 }
43 }
44 pub fn get_ext_instr_set_name(&mut self, id: InstrId) -> Result<&str> {
45 self.ext_instr_set
46 .get(&id)
47 .ok_or(anyhow!("missing extended instruction set id {}", id))
48 .map(|s| s.as_str())
49 }
50
51 pub fn set(&mut self, id: InstrId, constant: Constant) -> Result<&Constant> {
52 use std::collections::hash_map::Entry;
53 match self.values.entry(id) {
54 Entry::Vacant(entry) => Ok(entry.insert(constant)),
55 Entry::Occupied(_) => Err(anyhow!("constant id {} already exists", id)),
56 }
57 }
58 pub fn get(&self, id: InstrId) -> Result<&Constant> {
59 self.values.get(&id).ok_or(const_id_not_found(id))
60 }
61
62 pub fn get_value(&self, id: InstrId) -> Result<&ConstantValue> {
63 self.get(id).map(|c| &c.value)
64 }
65
66 pub fn iter(&self) -> impl Iterator<Item = (&InstrId, &Constant)> {
67 self.values.iter()
68 }
69
70 pub fn evaluate(
71 op: spirv::Op,
72 result_ty: &Type,
73 operands: &[ConstantValue],
74 ) -> Result<ConstantValue> {
75 let value = match op {
76 Op::ConvertFToS => {
78 let x = match operands {
79 [ConstantValue::F32(x)] => *x,
80 _ => return Err(evaluation_failed(op, result_ty, operands)),
81 };
82 match result_ty {
83 Type::Scalar(ScalarType::Integer {
84 bits: 32,
85 is_signed: true,
86 }) => ConstantValue::S32(x.0 as i32),
87 _ => return Err(evaluation_failed(op, result_ty, operands)),
88 }
89 }
90 Op::ConvertFToU => {
91 let x = match operands {
92 [ConstantValue::F32(x)] => *x,
93 _ => return Err(evaluation_failed(op, result_ty, operands)),
94 };
95 match result_ty {
96 Type::Scalar(ScalarType::Integer {
97 bits: 32,
98 is_signed: false,
99 }) => ConstantValue::U32(x.0 as u32),
100 _ => return Err(evaluation_failed(op, result_ty, operands)),
101 }
102 }
103 Op::ConvertSToF => {
104 let x = match operands {
105 [ConstantValue::S32(x)] => *x,
106 _ => return Err(evaluation_failed(op, result_ty, operands)),
107 };
108 match result_ty {
109 Type::Scalar(ScalarType::Float { bits: 32 }) => {
110 ConstantValue::F32((x as f32).into())
111 }
112 _ => return Err(evaluation_failed(op, result_ty, operands)),
113 }
114 }
115 Op::ConvertUToF => {
116 let x = match operands {
117 [ConstantValue::U32(x)] => *x,
118 _ => return Err(evaluation_failed(op, result_ty, operands)),
119 };
120 match result_ty {
121 Type::Scalar(ScalarType::Float { bits: 32 }) => {
122 ConstantValue::F32((x as f32).into())
123 }
124 _ => return Err(evaluation_failed(op, result_ty, operands)),
125 }
126 }
127 Op::SConvert => {
128 let x = match operands {
129 [ConstantValue::S32(x)] => *x,
130 _ => return Err(evaluation_failed(op, result_ty, operands)),
131 };
132 match result_ty {
133 Type::Scalar(ScalarType::Integer {
134 bits: 32,
135 is_signed: true,
136 }) => ConstantValue::S32(x),
137 _ => return Err(evaluation_failed(op, result_ty, operands)),
138 }
139 }
140 Op::UConvert => {
141 let x = match operands {
142 [ConstantValue::U32(x)] => *x,
143 _ => return Err(evaluation_failed(op, result_ty, operands)),
144 };
145 match result_ty {
146 Type::Scalar(ScalarType::Integer {
147 bits: 32,
148 is_signed: false,
149 }) => ConstantValue::U32(x),
150 _ => return Err(evaluation_failed(op, result_ty, operands)),
151 }
152 }
153 Op::FConvert => {
154 let x = match operands {
155 [ConstantValue::F32(x)] => *x,
156 _ => return Err(evaluation_failed(op, result_ty, operands)),
157 };
158 match result_ty {
159 Type::Scalar(ScalarType::Float { bits: 32 }) => ConstantValue::F32(x),
160 _ => return Err(evaluation_failed(op, result_ty, operands)),
161 }
162 }
163 Op::Bitcast => {
164 let bits = match operands {
165 [ConstantValue::U32(x)] => x.to_ne_bytes(),
166 [ConstantValue::S32(x)] => x.to_ne_bytes(),
167 [ConstantValue::F32(x)] => x.to_ne_bytes(),
168 _ => return Err(evaluation_failed(op, result_ty, operands)),
169 };
170 match result_ty {
171 Type::Scalar(ScalarType::Integer {
172 bits: 32,
173 is_signed: true,
174 }) => ConstantValue::S32(i32::from_ne_bytes(bits)),
175 Type::Scalar(ScalarType::Integer {
176 bits: 32,
177 is_signed: false,
178 }) => ConstantValue::U32(u32::from_ne_bytes(bits)),
179 Type::Scalar(ScalarType::Float { bits: 32 }) => {
180 ConstantValue::F32(f32::from_ne_bytes(bits).into())
181 }
182 _ => return Err(evaluation_failed(op, result_ty, operands)),
183 }
184 }
185 Op::SNegate => {
187 let a = match operands {
188 [ConstantValue::S32(x)] => *x,
189 _ => return Err(evaluation_failed(op, result_ty, operands)),
190 };
191 match result_ty {
192 Type::Scalar(ScalarType::Integer {
193 bits: 32,
194 is_signed: true,
195 }) => ConstantValue::S32(-a),
196 _ => return Err(evaluation_failed(op, result_ty, operands)),
197 }
198 }
199 Op::FNegate => {
200 let a = match operands {
201 [ConstantValue::F32(x)] => *x,
202 _ => return Err(evaluation_failed(op, result_ty, operands)),
203 };
204 match result_ty {
205 Type::Scalar(ScalarType::Float { bits: 32 }) => ConstantValue::F32(-a),
206 _ => return Err(evaluation_failed(op, result_ty, operands)),
207 }
208 }
209 Op::IAdd => {
210 let (a, b) = match operands {
211 [ConstantValue::S32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
212 [ConstantValue::S32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
213 [ConstantValue::U32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
214 [ConstantValue::U32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
215 _ => return Err(evaluation_failed(op, result_ty, operands)),
216 };
217 match result_ty {
218 Type::Scalar(ScalarType::Integer {
219 bits: 32,
220 is_signed: true,
221 }) => ConstantValue::S32((a + b) as i32),
222 Type::Scalar(ScalarType::Integer {
223 bits: 32,
224 is_signed: false,
225 }) => ConstantValue::U32((a + b) as u32),
226 _ => return Err(evaluation_failed(op, result_ty, operands)),
227 }
228 }
229 Op::FAdd => {
230 let (a, b) = match operands {
231 [ConstantValue::F32(x), ConstantValue::F32(y)] => (*x, *y),
232 _ => return Err(evaluation_failed(op, result_ty, operands)),
233 };
234 match result_ty {
235 Type::Scalar(ScalarType::Float { bits: 32 }) => ConstantValue::F32(a + b),
236 _ => return Err(evaluation_failed(op, result_ty, operands)),
237 }
238 }
239 Op::ISub => {
240 let (a, b) = match operands {
241 [ConstantValue::S32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
242 [ConstantValue::S32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
243 [ConstantValue::U32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
244 [ConstantValue::U32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
245 _ => return Err(evaluation_failed(op, result_ty, operands)),
246 };
247 match result_ty {
248 Type::Scalar(ScalarType::Integer {
249 bits: 32,
250 is_signed: true,
251 }) => ConstantValue::S32(((a - b) & 0xffffffff) as i32),
252 Type::Scalar(ScalarType::Integer {
253 bits: 32,
254 is_signed: false,
255 }) => ConstantValue::U32(((a - b) & 0xffffffff) as u32),
256 _ => return Err(evaluation_failed(op, result_ty, operands)),
257 }
258 }
259 Op::FSub => {
260 let (a, b) = match operands {
261 [ConstantValue::F32(x), ConstantValue::F32(y)] => (*x, *y),
262 _ => return Err(evaluation_failed(op, result_ty, operands)),
263 };
264 match result_ty {
265 Type::Scalar(ScalarType::Float { bits: 32 }) => ConstantValue::F32(a - b),
266 _ => return Err(evaluation_failed(op, result_ty, operands)),
267 }
268 }
269 Op::IMul => {
270 let (a, b) = match operands {
271 [ConstantValue::S32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
272 [ConstantValue::S32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
273 [ConstantValue::U32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
274 [ConstantValue::U32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
275 _ => return Err(evaluation_failed(op, result_ty, operands)),
276 };
277 match result_ty {
278 Type::Scalar(ScalarType::Integer {
279 bits: 32,
280 is_signed: true,
281 }) => ConstantValue::S32(((a * b) & 0xffffffff) as i32),
282 Type::Scalar(ScalarType::Integer {
283 bits: 32,
284 is_signed: false,
285 }) => ConstantValue::U32(((a * b) & 0xffffffff) as u32),
286 _ => return Err(evaluation_failed(op, result_ty, operands)),
287 }
288 }
289 Op::FMul => {
290 let (a, b) = match operands {
291 [ConstantValue::F32(x), ConstantValue::F32(y)] => (*x, *y),
292 _ => return Err(evaluation_failed(op, result_ty, operands)),
293 };
294 match result_ty {
295 Type::Scalar(ScalarType::Float { bits: 32 }) => ConstantValue::F32(a * b),
296 _ => return Err(evaluation_failed(op, result_ty, operands)),
297 }
298 }
299 Op::UDiv => {
300 let (a, b) = match operands {
301 [ConstantValue::S32(x), ConstantValue::S32(y)] => (*x as u64, *y as u64),
302 [ConstantValue::S32(x), ConstantValue::U32(y)] => (*x as u64, *y as u64),
303 [ConstantValue::U32(x), ConstantValue::S32(y)] => (*x as u64, *y as u64),
304 [ConstantValue::U32(x), ConstantValue::U32(y)] => (*x as u64, *y as u64),
305 _ => return Err(evaluation_failed(op, result_ty, operands)),
306 };
307 match result_ty {
308 Type::Scalar(ScalarType::Integer {
309 bits: 32,
310 is_signed: true,
311 }) => ConstantValue::S32(((a / b) & 0xffffffff) as i32),
312 Type::Scalar(ScalarType::Integer {
313 bits: 32,
314 is_signed: false,
315 }) => ConstantValue::U32(((a / b) & 0xffffffff) as u32),
316 _ => return Err(evaluation_failed(op, result_ty, operands)),
317 }
318 }
319 Op::SDiv => {
320 let (a, b) = match operands {
321 [ConstantValue::S32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
322 [ConstantValue::S32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
323 [ConstantValue::U32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
324 [ConstantValue::U32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
325 _ => return Err(evaluation_failed(op, result_ty, operands)),
326 };
327 match result_ty {
328 Type::Scalar(ScalarType::Integer {
329 bits: 32,
330 is_signed: true,
331 }) => ConstantValue::S32(((a / b) & 0xffffffff) as i32),
332 Type::Scalar(ScalarType::Integer {
333 bits: 32,
334 is_signed: false,
335 }) => ConstantValue::U32(((a / b) & 0xffffffff) as u32),
336 _ => return Err(evaluation_failed(op, result_ty, operands)),
337 }
338 }
339 Op::FDiv => {
340 let (a, b) = match operands {
341 [ConstantValue::F32(x), ConstantValue::F32(y)] => (*x, *y),
342 _ => return Err(evaluation_failed(op, result_ty, operands)),
343 };
344 match result_ty {
345 Type::Scalar(ScalarType::Float { bits: 32 }) => ConstantValue::F32(a / b),
346 _ => return Err(evaluation_failed(op, result_ty, operands)),
347 }
348 }
349 Op::UMod => {
350 let (a, b) = match operands {
351 [ConstantValue::S32(x), ConstantValue::S32(y)] => (*x as u64, *y as u64),
352 [ConstantValue::S32(x), ConstantValue::U32(y)] => (*x as u64, *y as u64),
353 [ConstantValue::U32(x), ConstantValue::S32(y)] => (*x as u64, *y as u64),
354 [ConstantValue::U32(x), ConstantValue::U32(y)] => (*x as u64, *y as u64),
355 _ => return Err(evaluation_failed(op, result_ty, operands)),
356 };
357 match result_ty {
358 Type::Scalar(ScalarType::Integer {
359 bits: 32,
360 is_signed: true,
361 }) => ConstantValue::S32(((a % b) & 0xffffffff) as i32),
362 Type::Scalar(ScalarType::Integer {
363 bits: 32,
364 is_signed: false,
365 }) => ConstantValue::U32(((a % b) & 0xffffffff) as u32),
366 _ => return Err(evaluation_failed(op, result_ty, operands)),
367 }
368 }
369 Op::SRem => {
370 let (a, b) = match operands {
371 [ConstantValue::S32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
372 [ConstantValue::S32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
373 [ConstantValue::U32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
374 [ConstantValue::U32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
375 _ => return Err(evaluation_failed(op, result_ty, operands)),
376 };
377 match result_ty {
378 Type::Scalar(ScalarType::Integer {
379 bits: 32,
380 is_signed: true,
381 }) => ConstantValue::S32(((a % b) & 0xffffffff) as i32),
382 _ => return Err(evaluation_failed(op, result_ty, operands)),
383 }
384 }
385 Op::SMod => {
386 let (a, b) = match operands {
387 [ConstantValue::S32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
388 [ConstantValue::S32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
389 [ConstantValue::U32(x), ConstantValue::S32(y)] => (*x as i64, *y as i64),
390 [ConstantValue::U32(x), ConstantValue::U32(y)] => (*x as i64, *y as i64),
391 _ => return Err(evaluation_failed(op, result_ty, operands)),
392 };
393 match result_ty {
394 Type::Scalar(ScalarType::Integer {
395 bits: 32,
396 is_signed: true,
397 }) => ConstantValue::S32((a.rem_euclid(b) & 0xffffffff) as i32),
398 _ => return Err(evaluation_failed(op, result_ty, operands)),
399 }
400 }
401 Op::FRem => {
402 let (a, b) = match operands {
403 [ConstantValue::F32(x), ConstantValue::F32(y)] => (*x, *y),
404 _ => return Err(evaluation_failed(op, result_ty, operands)),
405 };
406 match result_ty {
407 Type::Scalar(ScalarType::Float { bits: 32 }) => ConstantValue::F32(a % b),
408 _ => return Err(evaluation_failed(op, result_ty, operands)),
409 }
410 }
411 Op::FMod => {
412 let (a, b) = match operands {
413 [ConstantValue::F32(x), ConstantValue::F32(y)] => (*x, *y),
414 _ => return Err(evaluation_failed(op, result_ty, operands)),
415 };
416 match result_ty {
417 Type::Scalar(ScalarType::Float { bits: 32 }) => {
418 ConstantValue::F32(a.rem_euclid(*b).into())
419 }
420 _ => return Err(evaluation_failed(op, result_ty, operands)),
421 }
422 }
423 Op::ShiftRightLogical => {
425 if operands.len() != 2 {
426 return Err(evaluation_failed(op, result_ty, operands));
427 }
428 let base = match operands[0] {
429 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
430 ConstantValue::U32(x) => x,
431 _ => return Err(evaluation_failed(op, result_ty, operands)),
432 };
433 let shift = match operands[1] {
434 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
435 ConstantValue::U32(x) => x,
436 _ => return Err(evaluation_failed(op, result_ty, operands)),
437 };
438 match result_ty {
439 Type::Scalar(ScalarType::Integer {
440 bits: 32,
441 is_signed: true,
442 }) => ConstantValue::S32(i32::from_ne_bytes((base >> shift).to_ne_bytes())),
443 Type::Scalar(ScalarType::Integer {
444 bits: 32,
445 is_signed: false,
446 }) => ConstantValue::U32(base >> shift),
447 _ => return Err(evaluation_failed(op, result_ty, operands)),
448 }
449 }
450 Op::ShiftRightArithmetic => {
451 if operands.len() != 2 {
452 return Err(evaluation_failed(op, result_ty, operands));
453 }
454 let base = match operands[0] {
456 ConstantValue::S32(x) => x,
457 ConstantValue::U32(x) => i32::from_ne_bytes(x.to_ne_bytes()),
458 _ => return Err(evaluation_failed(op, result_ty, operands)),
459 };
460 let shift = match operands[1] {
461 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
462 ConstantValue::U32(x) => x,
463 _ => return Err(evaluation_failed(op, result_ty, operands)),
464 };
465 match result_ty {
466 Type::Scalar(ScalarType::Integer {
467 bits: 32,
468 is_signed: true,
469 }) => ConstantValue::S32(base >> shift),
470 Type::Scalar(ScalarType::Integer {
471 bits: 32,
472 is_signed: false,
473 }) => ConstantValue::U32(u32::from_ne_bytes((base >> shift).to_ne_bytes())),
474 _ => return Err(evaluation_failed(op, result_ty, operands)),
475 }
476 }
477 Op::ShiftLeftLogical => {
478 if operands.len() != 2 {
479 return Err(evaluation_failed(op, result_ty, operands));
480 }
481 let base = match operands[0] {
482 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
483 ConstantValue::U32(x) => x,
484 _ => return Err(evaluation_failed(op, result_ty, operands)),
485 };
486 let shift = match operands[1] {
487 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
488 ConstantValue::U32(x) => x,
489 _ => return Err(evaluation_failed(op, result_ty, operands)),
490 };
491 match result_ty {
492 Type::Scalar(ScalarType::Integer {
493 bits: 32,
494 is_signed: true,
495 }) => ConstantValue::S32(i32::from_ne_bytes((base << shift).to_ne_bytes())),
496 Type::Scalar(ScalarType::Integer {
497 bits: 32,
498 is_signed: false,
499 }) => ConstantValue::U32(base << shift),
500 _ => return Err(evaluation_failed(op, result_ty, operands)),
501 }
502 }
503 Op::BitwiseOr => {
504 if operands.len() != 2 {
505 return Err(evaluation_failed(op, result_ty, operands));
506 }
507 let x = match operands[0] {
508 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
509 ConstantValue::U32(x) => x,
510 _ => return Err(evaluation_failed(op, result_ty, operands)),
511 };
512 let y = match operands[1] {
513 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
514 ConstantValue::U32(x) => x,
515 _ => return Err(evaluation_failed(op, result_ty, operands)),
516 };
517 match result_ty {
518 Type::Scalar(ScalarType::Integer {
519 bits: 32,
520 is_signed: true,
521 }) => ConstantValue::S32(i32::from_ne_bytes((x | y).to_ne_bytes())),
522 Type::Scalar(ScalarType::Integer {
523 bits: 32,
524 is_signed: false,
525 }) => ConstantValue::U32(x | y),
526 _ => return Err(evaluation_failed(op, result_ty, operands)),
527 }
528 }
529 Op::BitwiseXor => {
530 if operands.len() != 2 {
531 return Err(evaluation_failed(op, result_ty, operands));
532 }
533 let x = match operands[0] {
534 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
535 ConstantValue::U32(x) => x,
536 _ => return Err(evaluation_failed(op, result_ty, operands)),
537 };
538 let y = match operands[1] {
539 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
540 ConstantValue::U32(x) => x,
541 _ => return Err(evaluation_failed(op, result_ty, operands)),
542 };
543 match result_ty {
544 Type::Scalar(ScalarType::Integer {
545 bits: 32,
546 is_signed: true,
547 }) => ConstantValue::S32(i32::from_ne_bytes((x ^ y).to_ne_bytes())),
548 Type::Scalar(ScalarType::Integer {
549 bits: 32,
550 is_signed: false,
551 }) => ConstantValue::U32(x ^ y),
552 _ => return Err(evaluation_failed(op, result_ty, operands)),
553 }
554 }
555 Op::BitwiseAnd => {
556 if operands.len() != 2 {
557 return Err(evaluation_failed(op, result_ty, operands));
558 }
559 let x = match operands[0] {
560 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
561 ConstantValue::U32(x) => x,
562 _ => return Err(evaluation_failed(op, result_ty, operands)),
563 };
564 let y = match operands[1] {
565 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
566 ConstantValue::U32(x) => x,
567 _ => return Err(evaluation_failed(op, result_ty, operands)),
568 };
569 match result_ty {
570 Type::Scalar(ScalarType::Integer {
571 bits: 32,
572 is_signed: true,
573 }) => ConstantValue::S32(i32::from_ne_bytes((x & y).to_ne_bytes())),
574 Type::Scalar(ScalarType::Integer {
575 bits: 32,
576 is_signed: false,
577 }) => ConstantValue::U32(x & y),
578 _ => return Err(evaluation_failed(op, result_ty, operands)),
579 }
580 }
581 Op::Not => {
582 if operands.len() != 1 {
583 return Err(evaluation_failed(op, result_ty, operands));
584 }
585 let x = match operands[0] {
586 ConstantValue::S32(x) => u32::from_ne_bytes(x.to_ne_bytes()),
587 ConstantValue::U32(x) => x,
588 _ => return Err(evaluation_failed(op, result_ty, operands)),
589 };
590 match result_ty {
591 Type::Scalar(ScalarType::Integer {
592 bits: 32,
593 is_signed: true,
594 }) => ConstantValue::S32(i32::from_ne_bytes((!x).to_ne_bytes())),
595 Type::Scalar(ScalarType::Integer {
596 bits: 32,
597 is_signed: false,
598 }) => ConstantValue::U32(!x),
599 _ => return Err(evaluation_failed(op, result_ty, operands)),
600 }
601 }
602 _ => return Err(evaluation_failed(op, result_ty, operands)),
603 };
604 Ok(value)
605 }
606
607 pub fn interpret(
608 &mut self,
609 op: spirv::Op,
610 result_id: InstrId,
611 result_ty: &Type,
612 operand_ids: &[InstrId],
613 ) -> Result<&Constant> {
614 let mut operands = Vec::new();
615 for operand in operand_ids.iter() {
616 if let Ok(operand) = self.get_value(*operand) {
617 operands.push(operand.to_owned());
618 } else {
619 return Err(broken_expr_tree(result_id));
620 }
621 }
622
623 let value = Self::evaluate(op, result_ty, &operands)?;
624 self.set(result_id, Constant::new_itm(result_ty.clone(), value))
625 }
626
627 pub fn constants(&self) -> Vec<Constant> {
628 let mut out: Vec<_> = self.values.iter().collect();
629 out.sort_by_key(|c| c.0);
630 out.into_iter().map(|c| c.1.clone()).collect()
631 }
632}