1mod value_like;
2
3pub use self::value_like::ValueLike;
4use super::{block::BlockArgument, operation::OperationResult, Type};
5use crate::{utility::print_callback, Context};
6use mlir_sys::{mlirValueEqual, mlirValuePrint, MlirValue};
7use std::{
8 ffi::c_void,
9 fmt::{self, Debug, Display, Formatter},
10 marker::PhantomData,
11};
12
13#[derive(Clone, Copy)]
17pub struct Value<'c, 'a> {
18 raw: MlirValue,
19 _context: PhantomData<&'c Context>,
20 _parent: PhantomData<&'a ()>,
21}
22
23impl Value<'_, '_> {
24 pub unsafe fn from_raw(value: MlirValue) -> Self {
30 Self {
31 raw: value,
32 _context: Default::default(),
33 _parent: Default::default(),
34 }
35 }
36}
37
38impl<'c> ValueLike<'c> for Value<'c, '_> {
39 fn to_raw(&self) -> MlirValue {
40 self.raw
41 }
42}
43
44impl PartialEq for Value<'_, '_> {
45 fn eq(&self, other: &Self) -> bool {
46 unsafe { mlirValueEqual(self.raw, other.raw) }
47 }
48}
49
50impl Eq for Value<'_, '_> {}
51
52impl Display for Value<'_, '_> {
53 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
54 let mut data = (formatter, Ok(()));
55
56 unsafe {
57 mlirValuePrint(
58 self.raw,
59 Some(print_callback),
60 &mut data as *mut _ as *mut c_void,
61 );
62 }
63
64 data.1
65 }
66}
67
68impl Debug for Value<'_, '_> {
69 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
70 writeln!(formatter, "Value(")?;
71 Display::fmt(self, formatter)?;
72 write!(formatter, ")")
73 }
74}
75
76from_borrowed_subtypes!(Value, BlockArgument, OperationResult);
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use crate::{
82 ir::{operation::OperationBuilder, Attribute, Block, Identifier, Location},
83 test::create_test_context,
84 Context,
85 };
86
87 #[test]
88 fn r#type() {
89 let context = create_test_context();
90 let location = Location::unknown(&context);
91 let index_type = Type::index(&context);
92
93 let operation = OperationBuilder::new("arith.constant", location)
94 .add_results(&[index_type])
95 .add_attributes(&[(
96 Identifier::new(&context, "value"),
97 Attribute::parse(&context, "0 : index").unwrap(),
98 )])
99 .build()
100 .unwrap();
101
102 assert_eq!(operation.result(0).unwrap().r#type(), index_type);
103 }
104
105 #[test]
106 fn is_operation_result() {
107 let context = create_test_context();
108 let location = Location::unknown(&context);
109 let r#type = Type::index(&context);
110
111 let operation = OperationBuilder::new("arith.constant", location)
112 .add_results(&[r#type])
113 .add_attributes(&[(
114 Identifier::new(&context, "value"),
115 Attribute::parse(&context, "0 : index").unwrap(),
116 )])
117 .build()
118 .unwrap();
119
120 assert!(operation.result(0).unwrap().is_operation_result());
121 }
122
123 #[test]
124 fn is_block_argument() {
125 let context = create_test_context();
126 let r#type = Type::index(&context);
127 let block = Block::new(&[(r#type, Location::unknown(&context))]);
128
129 assert!(block.argument(0).unwrap().is_block_argument());
130 }
131
132 #[test]
133 fn dump() {
134 let context = create_test_context();
135 let location = Location::unknown(&context);
136 let index_type = Type::index(&context);
137
138 let value = OperationBuilder::new("arith.constant", location)
139 .add_results(&[index_type])
140 .add_attributes(&[(
141 Identifier::new(&context, "value"),
142 Attribute::parse(&context, "0 : index").unwrap(),
143 )])
144 .build()
145 .unwrap();
146
147 value.result(0).unwrap().dump();
148 }
149
150 #[test]
151 fn equal() {
152 let context = create_test_context();
153 let location = Location::unknown(&context);
154 let index_type = Type::index(&context);
155
156 let operation = OperationBuilder::new("arith.constant", location)
157 .add_results(&[index_type])
158 .add_attributes(&[(
159 Identifier::new(&context, "value"),
160 Attribute::parse(&context, "0 : index").unwrap(),
161 )])
162 .build()
163 .unwrap();
164 let result = Value::from(operation.result(0).unwrap());
165
166 assert_eq!(result, result);
167 }
168
169 #[test]
170 fn not_equal() {
171 let context = create_test_context();
172 let location = Location::unknown(&context);
173 let index_type = Type::index(&context);
174
175 let operation = || {
176 OperationBuilder::new("arith.constant", location)
177 .add_results(&[index_type])
178 .add_attributes(&[(
179 Identifier::new(&context, "value"),
180 Attribute::parse(&context, "0 : index").unwrap(),
181 )])
182 .build()
183 .unwrap()
184 };
185
186 assert_ne!(
187 Value::from(operation().result(0).unwrap()),
188 operation().result(0).unwrap().into()
189 );
190 }
191
192 #[test]
193 fn display_with_unregistered_dialect() {
194 let context = Context::new();
195 context.set_allow_unregistered_dialects(true);
196
197 let location = Location::unknown(&context);
198 let index_type = Type::index(&context);
199
200 let operation = OperationBuilder::new("arith.constant", location)
201 .add_results(&[index_type])
202 .add_attributes(&[(
203 Identifier::new(&context, "value"),
204 Attribute::parse(&context, "0 : index").unwrap(),
205 )])
206 .build()
207 .unwrap();
208
209 assert_eq!(
210 operation.result(0).unwrap().to_string(),
211 "%0 = \"arith.constant\"() {value = 0 : index} : () -> index\n"
212 );
213 }
214
215 #[test]
216 fn display_with_registered_dialect() {
217 let context = create_test_context();
218
219 let location = Location::unknown(&context);
220 let index_type = Type::index(&context);
221
222 let operation = OperationBuilder::new("arith.constant", location)
223 .add_results(&[index_type])
224 .add_attributes(&[(
225 Identifier::new(&context, "value"),
226 Attribute::parse(&context, "0 : index").unwrap(),
227 )])
228 .build()
229 .unwrap();
230
231 assert_eq!(
232 operation.result(0).unwrap().to_string(),
233 "%c0 = arith.constant 0 : index\n"
234 );
235 }
236
237 #[test]
238 fn debug() {
239 let context = create_test_context();
240
241 let location = Location::unknown(&context);
242 let index_type = Type::index(&context);
243
244 let operation = OperationBuilder::new("arith.constant", location)
245 .add_results(&[index_type])
246 .add_attributes(&[(
247 Identifier::new(&context, "value"),
248 Attribute::parse(&context, "0 : index").unwrap(),
249 )])
250 .build()
251 .unwrap();
252
253 assert_eq!(
254 format!("{:?}", Value::from(operation.result(0).unwrap())),
255 "Value(\n%c0 = arith.constant 0 : index\n)"
256 );
257 }
258}