1use core::borrow::Borrow;
2
3use smallvec::{smallvec, SmallVec};
4
5use super::*;
6use crate::adt::SmallSet;
7
8pub enum ValueRange<'a, const N: usize = 2> {
18 Empty,
20 Owned(SmallVec<[ValueRef; N]>),
22 Borrowed(&'a [ValueRef]),
24 BlockArguments(&'a [BlockArgumentRef]),
26 Operands(&'a [OpOperand]),
28 Results(&'a [OpResultRef]),
30}
31
32impl<const N: usize> Default for ValueRange<'_, N> {
33 fn default() -> Self {
34 Self::Empty
35 }
36}
37
38impl<'values, const N: usize> ValueRange<'values, N> {
39 pub fn is_empty(&self) -> bool {
41 match self {
42 Self::Empty => true,
43 Self::Owned(values) => values.is_empty(),
44 Self::Borrowed(values) => values.is_empty(),
45 Self::BlockArguments(range) => range.is_empty(),
46 Self::Operands(range) => range.is_empty(),
47 Self::Results(range) => range.is_empty(),
48 }
49 }
50
51 pub fn len(&self) -> usize {
53 match self {
54 Self::Empty => 0,
55 Self::Owned(values) => values.len(),
56 Self::Borrowed(values) => values.len(),
57 Self::BlockArguments(range) => range.len(),
58 Self::Operands(range) => range.len(),
59 Self::Results(range) => range.len(),
60 }
61 }
62
63 pub fn slice<'a, 'b: 'a + 'values, R>(&'b self, range: R) -> ValueRange<'a, N>
64 where
65 R: core::slice::SliceIndex<[ValueRef], Output = [ValueRef]>,
66 R: core::slice::SliceIndex<[BlockArgumentRef], Output = [BlockArgumentRef]>,
67 R: core::slice::SliceIndex<[OpOperand], Output = [OpOperand]>,
68 R: core::slice::SliceIndex<[OpResultRef], Output = [OpResultRef]>,
69 {
70 match self {
71 Self::Empty => ValueRange::Empty,
72 Self::Owned(values) => Self::Borrowed(&values[range]),
73 Self::Borrowed(values) => Self::Borrowed(&values[range]),
74 Self::BlockArguments(values) => Self::BlockArguments(&values[range]),
75 Self::Operands(values) => Self::Operands(&values[range]),
76 Self::Results(values) => Self::Results(&values[range]),
77 }
78 }
79
80 pub fn get(&self, index: usize) -> Option<ValueRef> {
82 match self {
83 Self::Empty => None,
84 Self::Owned(values) => values.get(index).cloned(),
85 Self::Borrowed(values) => values.get(index).cloned(),
86 Self::BlockArguments(range) => {
87 range.get(index).map(|operand| operand.borrow().as_value_ref())
88 }
89 Self::Operands(range) => {
90 range.get(index).map(|operand| operand.borrow().as_value_ref())
91 }
92 Self::Results(range) => range.get(index).map(|result| result.borrow().as_value_ref()),
93 }
94 }
95
96 pub fn contains<V>(&self, value: V) -> bool
98 where
99 V: Borrow<ValueRef>,
100 {
101 let value = value.borrow();
102 match self {
103 Self::Empty => false,
104 Self::Owned(values) => values.contains(value),
105 Self::Borrowed(values) => values.contains(value),
106 Self::BlockArguments(args) => args.iter().copied().any(|arg| arg as ValueRef == *value),
107 Self::Operands(operands) => {
108 operands.iter().any(|operand| operand.borrow().as_value_ref() == *value)
109 }
110 Self::Results(results) => {
111 results.iter().copied().any(|result| result as ValueRef == *value)
112 }
113 }
114 }
115
116 pub fn iter(&self) -> ValueRangeIter<'_, N> {
118 match self {
119 Self::Empty => ValueRangeIter::new(ValueRange::Borrowed(&[])),
120 Self::Owned(values) => ValueRangeIter::new(ValueRange::Borrowed(values.as_slice())),
121 Self::Borrowed(values) => ValueRangeIter::new(ValueRange::Borrowed(values)),
122 Self::BlockArguments(values) => ValueRangeIter::new(ValueRange::BlockArguments(values)),
123 Self::Operands(values) => ValueRangeIter::new(ValueRange::Operands(values)),
124 Self::Results(values) => ValueRangeIter::new(ValueRange::Results(values)),
125 }
126 }
127
128 pub fn into_owned(self) -> ValueRange<'static, N> {
130 ValueRange::Owned(self.into_smallvec())
131 }
132
133 pub fn into_smallvec(self) -> SmallVec<[ValueRef; N]> {
135 match self {
136 Self::Empty => smallvec![],
137 Self::Owned(values) => values,
138 Self::Borrowed(values) => SmallVec::from_slice(values),
139 Self::BlockArguments(args) => args.iter().copied().map(|arg| arg as ValueRef).collect(),
140 Self::Operands(operands) => {
141 operands.iter().map(|operand| operand.borrow().as_value_ref()).collect()
142 }
143 Self::Results(results) => {
144 results.iter().copied().map(|result| result as ValueRef).collect()
145 }
146 }
147 }
148
149 pub fn to_vec(&self) -> alloc::vec::Vec<ValueRef> {
151 match self {
152 Self::Empty => Default::default(),
153 Self::Owned(values) => values.to_vec(),
154 Self::Borrowed(values) => values.to_vec(),
155 Self::BlockArguments(args) => args.iter().copied().map(|arg| arg as ValueRef).collect(),
156 Self::Operands(operands) => {
157 operands.iter().map(|operand| operand.borrow().as_value_ref()).collect()
158 }
159 Self::Results(results) => {
160 results.iter().copied().map(|result| result as ValueRef).collect()
161 }
162 }
163 }
164}
165
166impl<const N: usize> core::fmt::Debug for ValueRange<'_, N> {
167 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
168 fmt::Display::fmt(self, f)
169 }
170}
171
172impl<const N: usize> core::fmt::Display for ValueRange<'_, N> {
173 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
174 let mut builder = f.debug_list();
175 for value in self.iter() {
176 builder.entry_with(|f| write!(f, "{value}"));
177 }
178
179 builder.finish()
180 }
181}
182
183impl<const N: usize> FromIterator<ValueRef> for ValueRange<'static, N> {
184 fn from_iter<I>(iter: I) -> Self
185 where
186 I: IntoIterator<Item = ValueRef>,
187 {
188 Self::Owned(SmallVec::from_iter(iter))
189 }
190}
191
192impl<const N: usize> FromIterator<BlockArgumentRef> for ValueRange<'static, N> {
193 fn from_iter<I>(iter: I) -> Self
194 where
195 I: IntoIterator<Item = BlockArgumentRef>,
196 {
197 Self::from_iter(iter.into_iter().map(|arg| arg as ValueRef))
198 }
199}
200
201impl<const N: usize> FromIterator<OpResultRef> for ValueRange<'static, N> {
202 fn from_iter<I>(iter: I) -> Self
203 where
204 I: IntoIterator<Item = OpResultRef>,
205 {
206 Self::from_iter(iter.into_iter().map(|result| result as ValueRef))
207 }
208}
209
210impl<const N: usize> FromIterator<OpOperand> for ValueRange<'static, N> {
211 fn from_iter<I>(iter: I) -> Self
212 where
213 I: IntoIterator<Item = OpOperand>,
214 {
215 Self::from_iter(iter.into_iter().map(|operand| operand.borrow().as_value_ref()))
216 }
217}
218
219impl<'a, const N: usize> IntoIterator for ValueRange<'a, N> {
220 type IntoIter = ValueRangeIter<'a, N>;
221 type Item = ValueRef;
222
223 fn into_iter(self) -> Self::IntoIter {
224 ValueRangeIter::new(self)
225 }
226}
227
228impl<'a, 'b: 'a, const N: usize> IntoIterator for &'a ValueRange<'b, N> {
229 type IntoIter = ValueRangeIter<'a, N>;
230 type Item = ValueRef;
231
232 fn into_iter(self) -> Self::IntoIter {
233 self.iter()
234 }
235}
236
237impl<const N: usize> From<SmallVec<[ValueRef; N]>> for ValueRange<'static, N> {
238 fn from(values: SmallVec<[ValueRef; N]>) -> Self {
239 Self::Owned(SmallVec::from_slice(&values))
240 }
241}
242
243impl<'a, const M: usize, const N: usize> From<&'a SmallVec<[ValueRef; M]>> for ValueRange<'a, N> {
244 fn from(values: &'a SmallVec<[ValueRef; M]>) -> Self {
245 Self::Borrowed(values.as_slice())
246 }
247}
248
249impl<const N: usize> From<SmallSet<ValueRef, N>> for ValueRange<'static, N> {
250 fn from(values: SmallSet<ValueRef, N>) -> Self {
251 Self::Owned(values.into_vec())
252 }
253}
254
255impl<'a, const M: usize, const N: usize> From<&'a SmallSet<ValueRef, M>> for ValueRange<'a, N> {
256 fn from(values: &'a SmallSet<ValueRef, M>) -> Self {
257 Self::Borrowed(values.as_slice())
258 }
259}
260
261impl<'a, const N: usize> From<&'a [ValueRef]> for ValueRange<'a, N> {
262 fn from(values: &'a [ValueRef]) -> Self {
263 Self::Borrowed(values)
264 }
265}
266
267impl<'a, const N: usize> From<BlockArgumentRange<'a>> for ValueRange<'a, N> {
268 fn from(range: BlockArgumentRange<'a>) -> Self {
269 Self::BlockArguments(range.as_slice())
270 }
271}
272
273impl<'a, const N: usize> From<&'a [BlockArgumentRef]> for ValueRange<'a, N> {
274 fn from(range: &'a [BlockArgumentRef]) -> Self {
275 Self::BlockArguments(range)
276 }
277}
278
279impl<'a, const N: usize> From<OpOperandRange<'a>> for ValueRange<'a, N> {
280 fn from(range: OpOperandRange<'a>) -> Self {
281 Self::Operands(range.as_slice())
282 }
283}
284
285impl<'a, const N: usize> From<&'a [OpOperand]> for ValueRange<'a, N> {
286 fn from(range: &'a [OpOperand]) -> Self {
287 Self::Operands(range)
288 }
289}
290
291impl<'a, const N: usize> From<OpResultRange<'a>> for ValueRange<'a, N> {
292 fn from(range: OpResultRange<'a>) -> Self {
293 Self::Results(range.as_slice())
294 }
295}
296
297impl<'a, const N: usize> From<&'a [OpResultRef]> for ValueRange<'a, N> {
298 fn from(range: &'a [OpResultRef]) -> Self {
299 Self::Results(range)
300 }
301}
302
303impl<'a, const N: usize> From<SuccessorOperandRange<'a>> for ValueRange<'a, N> {
304 fn from(range: SuccessorOperandRange<'a>) -> Self {
305 Self::from(range.into_forwarded())
306 }
307}
308
309pub trait AsValueRange {
310 fn as_value_range(&self) -> ValueRange<'_, 2>;
311}
312
313impl<T: AsValueRange> AsValueRange for Option<T> {
314 fn as_value_range(&self) -> ValueRange<'_, 2> {
315 match self.as_ref() {
316 Some(values) => values.as_value_range(),
317 None => ValueRange::Empty,
318 }
319 }
320}
321
322impl AsValueRange for [ValueRef] {
323 fn as_value_range(&self) -> ValueRange<'_, 2> {
324 ValueRange::Borrowed(self)
325 }
326}
327
328impl AsValueRange for [BlockArgumentRef] {
329 fn as_value_range(&self) -> ValueRange<'_, 2> {
330 ValueRange::BlockArguments(self)
331 }
332}
333
334impl AsValueRange for [OpOperand] {
335 fn as_value_range(&self) -> ValueRange<'_, 2> {
336 ValueRange::Operands(self)
337 }
338}
339
340impl AsValueRange for [OpResultRef] {
341 fn as_value_range(&self) -> ValueRange<'_, 2> {
342 ValueRange::Results(self)
343 }
344}
345
346impl AsValueRange for alloc::vec::Vec<ValueRef> {
347 fn as_value_range(&self) -> ValueRange<'_, 2> {
348 ValueRange::Borrowed(self.as_slice())
349 }
350}
351
352impl<const N: usize> AsValueRange for SmallVec<[ValueRef; N]> {
353 fn as_value_range(&self) -> ValueRange<'_, 2> {
354 ValueRange::Borrowed(self.as_slice())
355 }
356}
357
358impl AsValueRange for OpOperandStorage {
359 fn as_value_range(&self) -> ValueRange<'_, 2> {
360 ValueRange::Operands(self.all().as_slice())
361 }
362}
363
364impl AsValueRange for OpResultStorage {
365 fn as_value_range(&self) -> ValueRange<'_, 2> {
366 ValueRange::Results(self.all().as_slice())
367 }
368}
369
370impl AsValueRange for OpOperandRange<'_> {
371 fn as_value_range(&self) -> ValueRange<'_, 2> {
372 ValueRange::Operands(self.as_slice())
373 }
374}
375
376impl AsValueRange for OpOperandRangeMut<'_> {
377 fn as_value_range(&self) -> ValueRange<'_, 2> {
378 ValueRange::Operands(self.as_slice())
379 }
380}
381
382impl AsValueRange for OpResultRange<'_> {
383 fn as_value_range(&self) -> ValueRange<'_, 2> {
384 ValueRange::Results(self.as_slice())
385 }
386}
387
388impl AsValueRange for OpResultRangeMut<'_> {
389 fn as_value_range(&self) -> ValueRange<'_, 2> {
390 ValueRange::Results(self.as_slice())
391 }
392}
393
394impl AsValueRange for BlockArgumentRange<'_> {
395 fn as_value_range(&self) -> ValueRange<'_, 2> {
396 ValueRange::BlockArguments(self.as_slice())
397 }
398}
399
400impl AsValueRange for BlockArgumentRangeMut<'_> {
401 fn as_value_range(&self) -> ValueRange<'_, 2> {
402 ValueRange::BlockArguments(self.as_slice())
403 }
404}
405
406pub struct ValueRangeIter<'a, const N: usize> {
408 range: ValueRange<'a, N>,
409 index: usize,
410}
411
412impl<'a, const N: usize> ValueRangeIter<'a, N> {
413 pub fn new(range: ValueRange<'a, N>) -> Self {
414 Self { range, index: 0 }
415 }
416}
417
418impl<const N: usize> core::iter::FusedIterator for ValueRangeIter<'_, N> {}
419impl<const N: usize> ExactSizeIterator for ValueRangeIter<'_, N> {
420 fn len(&self) -> usize {
421 let len = self.range.len();
422 len.saturating_sub(self.index)
423 }
424}
425impl<const N: usize> Iterator for ValueRangeIter<'_, N> {
426 type Item = ValueRef;
427
428 fn next(&mut self) -> Option<Self::Item> {
429 let len = self.range.len();
430 if self.index >= len {
431 return None;
432 }
433
434 let index = self.index;
435 self.index += 1;
436 match &self.range {
437 ValueRange::Empty => None,
438 ValueRange::Owned(values) => values.get(index).cloned(),
439 ValueRange::Borrowed(values) => values.get(index).cloned(),
440 ValueRange::BlockArguments(range) => {
441 range.get(index).map(|o| o.borrow().as_value_ref())
442 }
443 ValueRange::Operands(range) => range.get(index).map(|o| o.borrow().as_value_ref()),
444 ValueRange::Results(range) => range.get(index).map(|o| o.borrow().as_value_ref()),
445 }
446 }
447}
448
449impl<const N: usize> DoubleEndedIterator for ValueRangeIter<'_, N> {
450 fn next_back(&mut self) -> Option<Self::Item> {
451 let len = self.range.len();
452 let index = len.checked_sub(self.index + 1)?;
453
454 self.index += 1;
455 match &self.range {
456 ValueRange::Empty => None,
457 ValueRange::Owned(values) => values.get(index).cloned(),
458 ValueRange::Borrowed(values) => values.get(index).cloned(),
459 ValueRange::BlockArguments(range) => {
460 range.get(index).map(|o| o.borrow().as_value_ref())
461 }
462 ValueRange::Operands(range) => range.get(index).map(|o| o.borrow().as_value_ref()),
463 ValueRange::Results(range) => range.get(index).map(|o| o.borrow().as_value_ref()),
464 }
465 }
466}