1mod aliasing;
2mod range;
3mod stack;
4
5use core::{any::Any, fmt};
6
7pub use self::{
8 aliasing::ValueOrAlias,
9 range::{AsValueRange, ValueRange},
10 stack::StackOperand,
11};
12use super::*;
13use crate::{DynHash, DynPartialEq};
14
15#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
17#[repr(transparent)]
18pub struct ValueId(u32);
19impl ValueId {
20 pub const fn from_u32(id: u32) -> Self {
21 Self(id)
22 }
23
24 pub const fn as_u32(&self) -> u32 {
25 self.0
26 }
27}
28impl EntityId for ValueId {
29 #[inline(always)]
30 fn as_usize(&self) -> usize {
31 self.0 as usize
32 }
33}
34impl fmt::Debug for ValueId {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 write!(f, "v{}", &self.0)
37 }
38}
39impl fmt::Display for ValueId {
40 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41 write!(f, "v{}", &self.0)
42 }
43}
44
45pub trait Value:
52 Any
53 + EntityWithId<Id = ValueId>
54 + Spanned
55 + Usable<Use = OpOperandImpl>
56 + fmt::Debug
57 + fmt::Display
58 + DynPartialEq
59 + DynHash
60{
61 fn set_span(&mut self, span: SourceSpan);
63 fn ty(&self) -> &Type;
65 fn set_type(&mut self, ty: Type);
67 fn get_defining_op(&self) -> Option<OperationRef>;
71 fn parent_region(&self) -> Option<RegionRef> {
73 self.parent_block().and_then(|block| block.parent())
74 }
75 fn parent_block(&self) -> Option<BlockRef>;
77 fn is_used_outside_of_block(&self, block: &BlockRef) -> bool {
79 self.iter_uses()
80 .any(|user| user.owner.parent().is_some_and(|blk| !BlockRef::ptr_eq(&blk, block)))
81 }
82 fn replace_all_uses_with(&mut self, mut replacement: ValueRef) {
84 let mut cursor = self.uses_mut().front_mut();
85 while let Some(mut user) = cursor.as_pointer() {
86 {
88 let mut user = user.borrow_mut();
89 user.value = Some(replacement);
90 }
91 cursor.remove();
93 replacement.borrow_mut().insert_use(user);
95 }
96 }
97 fn replace_all_uses_except(&mut self, mut replacement: ValueRef, exceptions: &[OperationRef]) {
99 let mut cursor = self.uses_mut().front_mut();
100 while let Some(mut user) = cursor.as_pointer() {
101 {
103 let mut user = user.borrow_mut();
104 if exceptions.contains(&user.owner) {
105 cursor.move_next();
106 continue;
107 }
108 user.value = Some(replacement);
109 }
110 cursor.remove();
112 replacement.borrow_mut().insert_use(user);
114 }
115 }
116}
117
118impl dyn Value {
119 #[inline]
120 pub fn is<T: Value>(&self) -> bool {
121 (self as &dyn Any).is::<T>()
122 }
123
124 #[inline]
125 pub fn downcast_ref<T: Value>(&self) -> Option<&T> {
126 (self as &dyn Any).downcast_ref::<T>()
127 }
128
129 #[inline]
130 pub fn downcast_mut<T: Value>(&mut self) -> Option<&mut T> {
131 (self as &mut dyn Any).downcast_mut::<T>()
132 }
133
134 pub fn replace_uses_with_if<F>(&mut self, mut replacement: ValueRef, should_replace: F)
136 where
137 F: Fn(&OpOperandImpl) -> bool,
138 {
139 let mut cursor = self.uses_mut().front_mut();
140 while let Some(mut user) = cursor.as_pointer() {
141 {
143 let mut user = user.borrow_mut();
144 if !should_replace(&user) {
145 cursor.move_next();
146 continue;
147 }
148 user.value = Some(replacement);
149 }
150 cursor.remove();
152 replacement.borrow_mut().insert_use(user);
154 }
155 }
156}
157
158macro_rules! value_impl {
160 (
161 $(#[$outer:meta])*
162 $vis:vis struct $ValueKind:ident {
163 $(#[doc $($owner_doc_args:tt)*])*
164 owner: $OwnerTy:ty,
165 $(#[doc $($index_doc_args:tt)*])*
166 index: u8,
167 $(
168 $(#[$inner:ident $($args:tt)*])*
169 $Field:ident: $FieldTy:ty,
170 )*
171 }
172
173 fn get_defining_op(&$GetDefiningOpSelf:ident) -> Option<OperationRef> $GetDefiningOp:block
174
175 fn parent_block(&$ParentBlockSelf:ident) -> Option<BlockRef> $ParentBlock:block
176
177 $($t:tt)*
178 ) => {
179 $(#[$outer])*
180 #[derive(Spanned)]
181 $vis struct $ValueKind {
182 id: ValueId,
183 #[span]
184 span: SourceSpan,
185 ty: Type,
186 uses: OpOperandList,
187 owner: $OwnerTy,
188 index: u8,
189 $(
190 $(#[$inner $($args)*])*
191 $Field: $FieldTy
192 ),*
193 }
194
195
196 impl $ValueKind {
197 pub fn new(
198 span: SourceSpan,
199 id: ValueId,
200 ty: Type,
201 owner: $OwnerTy,
202 index: u8,
203 $(
204 $Field: $FieldTy
205 ),*
206 ) -> Self {
207 Self {
208 id,
209 ty,
210 span,
211 uses: Default::default(),
212 owner,
213 index,
214 $(
215 $Field
216 ),*
217 }
218 }
219
220 $(#[doc $($owner_doc_args)*])*
221 pub fn owner(&self) -> $OwnerTy {
222 self.owner.clone()
223 }
224
225 $(#[doc $($index_doc_args)*])*
226 pub fn index(&self) -> usize {
227 self.index as usize
228 }
229 }
230
231 impl Value for $ValueKind {
232 fn ty(&self) -> &Type {
233 &self.ty
234 }
235
236 fn set_span(&mut self, span: SourceSpan) {
237 self.span = span;
238 }
239
240 fn set_type(&mut self, ty: Type) {
241 self.ty = ty;
242 }
243
244 fn get_defining_op(&$GetDefiningOpSelf) -> Option<OperationRef> $GetDefiningOp
245
246 fn parent_block(&$ParentBlockSelf) -> Option<BlockRef> $ParentBlock
247 }
248
249 impl Entity for $ValueKind {}
250 impl EntityWithId for $ValueKind {
251 type Id = ValueId;
252
253 #[inline(always)]
254 fn id(&self) -> Self::Id {
255 self.id
256 }
257 }
258
259 impl EntityParent<OpOperandImpl> for $ValueKind {
260 fn offset() -> usize {
261 core::mem::offset_of!($ValueKind, uses)
262 }
263 }
264
265 impl Usable for $ValueKind {
266 type Use = OpOperandImpl;
267
268 #[inline(always)]
269 fn uses(&self) -> &OpOperandList {
270 &self.uses
271 }
272
273 #[inline(always)]
274 fn uses_mut(&mut self) -> &mut OpOperandList {
275 &mut self.uses
276 }
277 }
278
279
280 impl Eq for $ValueKind {}
281
282 impl PartialEq for $ValueKind {
283 fn eq(&self, other: &Self) -> bool {
284 self.id == other.id
285 }
286 }
287
288 impl Ord for $ValueKind {
289 fn cmp(&self, other: &Self) -> core::cmp::Ordering {
290 self.id.cmp(&other.id)
291 }
292 }
293
294 impl PartialOrd for $ValueKind {
295 fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
296 Some(self.cmp(other))
297 }
298 }
299
300 impl core::hash::Hash for $ValueKind {
301 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
302 self.id.hash(state);
303 }
304 }
305
306 impl fmt::Display for $ValueKind {
307 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
308 use crate::formatter::PrettyPrint;
309
310 self.pretty_print(f)
311 }
312 }
313
314 impl fmt::Debug for $ValueKind {
315 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
316 let mut builder = f.debug_struct(stringify!($ValueKind));
317 builder
318 .field("id", &self.id)
319 .field("ty", &self.ty)
320 .field("index", &self.index)
321 .field("is_used", &(!self.uses.is_empty()));
322
323 $(
324 builder.field(stringify!($Field), &self.$Field);
325 )*
326
327 builder.finish_non_exhaustive()
328 }
329 }
330
331 $($t)*
332 }
333}
334
335pub type ValueRef = UnsafeEntityRef<dyn Value>;
337pub type BlockArgumentRef = UnsafeEntityRef<BlockArgument>;
339pub type OpResultRef = UnsafeEntityRef<OpResult>;
341
342value_impl!(
343 pub struct BlockArgument {
345 owner: BlockRef,
347 index: u8,
349 }
350
351 fn get_defining_op(&self) -> Option<OperationRef> {
352 None
353 }
354
355 fn parent_block(&self) -> Option<BlockRef> {
356 Some(self.owner)
357 }
358);
359
360impl BlockArgument {
361 #[inline]
362 pub fn as_value_ref(&self) -> ValueRef {
363 self.as_block_argument_ref() as ValueRef
364 }
365
366 #[inline]
367 pub fn as_block_argument_ref(&self) -> BlockArgumentRef {
368 unsafe { BlockArgumentRef::from_raw(self) }
369 }
370}
371
372impl crate::formatter::PrettyPrint for BlockArgument {
373 fn render(&self) -> crate::formatter::Document {
374 use crate::formatter::*;
375
376 display(self.id) + const_text(": ") + self.ty.render()
377 }
378}
379
380impl StorableEntity for BlockArgument {
381 #[inline(always)]
382 fn index(&self) -> usize {
383 self.index as usize
384 }
385
386 unsafe fn set_index(&mut self, index: usize) {
387 self.index = index.try_into().expect("too many block arguments");
388 }
389}
390
391pub type BlockArgumentRange<'a> = crate::EntityRange<'a, BlockArgumentRef>;
392pub type BlockArgumentRangeMut<'a> = crate::EntityRangeMut<'a, BlockArgumentRef, 1>;
393
394value_impl!(
395 pub struct OpResult {
397 owner: OperationRef,
399 index: u8,
401 }
402
403 fn get_defining_op(&self) -> Option<OperationRef> {
404 Some(self.owner)
405 }
406
407 fn parent_block(&self) -> Option<BlockRef> {
408 self.owner.parent()
409 }
410);
411
412impl OpResult {
413 #[inline]
414 pub fn as_value_ref(&self) -> ValueRef {
415 unsafe { ValueRef::from_raw(self as &dyn Value) }
416 }
417
418 #[inline]
419 pub fn as_op_result_ref(&self) -> OpResultRef {
420 unsafe { OpResultRef::from_raw(self) }
421 }
422}
423
424impl crate::formatter::PrettyPrint for OpResult {
425 #[inline]
426 fn render(&self) -> crate::formatter::Document {
427 use crate::formatter::*;
428
429 display(self.id)
430 }
431}
432
433impl StorableEntity for OpResult {
434 #[inline(always)]
435 fn index(&self) -> usize {
436 self.index as usize
437 }
438
439 unsafe fn set_index(&mut self, index: usize) {
440 self.index = index.try_into().expect("too many op results");
441 }
442
443 fn unlink(&mut self) {
447 let uses = self.uses_mut();
448 uses.clear();
449 }
450}
451
452pub type OpResultStorage = crate::EntityStorage<OpResultRef, 1>;
453pub type OpResultRange<'a> = crate::EntityRange<'a, OpResultRef>;
454pub type OpResultRangeMut<'a> = crate::EntityRangeMut<'a, OpResultRef, 1>;