midenc_hir/ir/
operands.rs1use core::fmt;
2
3use super::Context;
4use crate::{EntityRef, OperationRef, Type, UnsafeIntrusiveEntityRef, Value, ValueId, ValueRef};
5
6pub type OpOperand = UnsafeIntrusiveEntityRef<OpOperandImpl>;
7pub type OpOperandList = crate::EntityList<OpOperandImpl>;
8#[allow(unused)]
9pub type OpOperandIter<'a> = crate::EntityIter<'a, OpOperandImpl>;
10#[allow(unused)]
11pub type OpOperandCursor<'a> = crate::EntityCursor<'a, OpOperandImpl>;
12#[allow(unused)]
13pub type OpOperandCursorMut<'a> = crate::EntityCursorMut<'a, OpOperandImpl>;
14
15pub struct OpOperandImpl {
17 pub value: Option<ValueRef>,
19 pub owner: OperationRef,
21 pub index: u8,
23}
24impl OpOperandImpl {
25 #[inline]
26 pub fn new(value: ValueRef, owner: OperationRef, index: u8) -> Self {
27 Self {
28 value: Some(value),
29 owner,
30 index,
31 }
32 }
33
34 #[track_caller]
35 pub fn value(&self) -> EntityRef<'_, dyn Value> {
36 self.value.as_ref().expect("operand is unlinked").borrow()
37 }
38
39 #[inline]
40 pub const fn as_value_ref(&self) -> ValueRef {
41 self.value.unwrap()
42 }
43
44 #[inline]
45 pub fn as_operand_ref(&self) -> OpOperand {
46 unsafe { OpOperand::from_raw(self) }
47 }
48
49 pub fn owner(&self) -> EntityRef<'_, crate::Operation> {
50 self.owner.borrow()
51 }
52
53 pub fn ty(&self) -> crate::Type {
54 self.value().ty().clone()
55 }
56
57 pub fn operand_group(&self) -> u8 {
58 let owner = self.owner.borrow();
59 let operands = owner.operands();
60 let operand_index = self.index as usize;
61 let group_index = operands
62 .groups()
63 .position(|group| group.range().contains(&operand_index))
64 .expect("broken operand reference!");
65 group_index as u8
66 }
67
68 pub fn set(&mut self, mut value: ValueRef) {
71 let this = self.as_operand_ref();
72 if let Some(mut prev) = self.value.take() {
73 unsafe {
74 let mut prev = prev.borrow_mut();
75 prev.uses_mut().cursor_mut_from_ptr(this).remove();
76 }
77 }
78 self.value = Some(value);
79 value.borrow_mut().insert_use(this);
80 }
81}
82impl fmt::Debug for OpOperand {
83 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
84 fmt::Debug::fmt(&*self.borrow(), f)
85 }
86}
87impl fmt::Debug for OpOperandImpl {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 #[derive(Debug)]
90 #[allow(unused)]
91 struct ValueInfo<'a> {
92 id: ValueId,
93 ty: &'a Type,
94 }
95
96 let value = self.value.map(|value| value.borrow());
97 let value = value.as_ref().map(|value| ValueInfo {
98 id: value.id(),
99 ty: value.ty(),
100 });
101 f.debug_struct("OpOperand")
102 .field("index", &self.index)
103 .field("value", &value)
104 .finish_non_exhaustive()
105 }
106}
107impl crate::Spanned for OpOperandImpl {
108 fn span(&self) -> crate::SourceSpan {
109 self.value().span()
110 }
111}
112impl crate::Entity for OpOperandImpl {}
113impl crate::EntityListItem for OpOperandImpl {}
114impl crate::StorableEntity for OpOperandImpl {
115 #[inline(always)]
116 fn index(&self) -> usize {
117 self.index as usize
118 }
119
120 unsafe fn set_index(&mut self, index: usize) {
121 self.index = index.try_into().expect("too many operands");
122 }
123
124 fn unlink(&mut self) {
125 if !self.as_operand_ref().is_linked() {
126 return;
127 }
128 if let Some(mut value) = self.value.take() {
129 let ptr = self.as_operand_ref();
130 let mut value = value.borrow_mut();
131 let uses = value.uses_mut();
132 unsafe {
133 let mut cursor = uses.cursor_mut_from_ptr(ptr);
134 cursor.remove();
135 }
136 }
137 }
138}
139
140pub type OpOperandStorage = crate::EntityStorage<OpOperand, 1>;
141pub type OpOperandRange<'a> = crate::EntityRange<'a, OpOperand>;
142pub type OpOperandRangeMut<'a> = crate::EntityRangeMut<'a, OpOperand, 1>;
143
144impl OpOperandRangeMut<'_> {
145 pub fn set_operands<I>(&mut self, operands: I, owner: OperationRef, context: &Context)
146 where
147 I: IntoIterator<Item = ValueRef>,
148 {
149 let mut operands = operands.into_iter().enumerate();
150 let mut num_operands = 0;
151 while let Some((index, value)) = operands.next() {
152 if let Some(operand_ref) = self.get_mut(index) {
153 num_operands += 1;
154 let mut operand = operand_ref.borrow_mut();
155 if operand.value.is_some_and(|v| v == value) {
157 continue;
158 }
159 operand.set(value);
161 } else {
162 self.extend(core::iter::once((index, value)).chain(operands).map(|(_, value)| {
164 num_operands += 1;
165 context.make_operand(value, owner, 0)
166 }));
167 break;
168 }
169 }
170
171 if num_operands < self.len() {
173 for _ in 0..(self.len() - num_operands) {
174 let _ = self.pop();
175 }
176 }
177 }
178}