1#[macro_use]
4mod r#macro;
5mod function;
6pub mod id;
7mod integer;
8mod mem_ref;
9mod ranked_tensor;
10mod shaped_type_like;
11mod tuple;
12mod type_like;
13
14pub use self::{
15 function::FunctionType, id::TypeId, integer::IntegerType, mem_ref::MemRefType,
16 ranked_tensor::RankedTensorType, shaped_type_like::ShapedTypeLike, tuple::TupleType,
17 type_like::TypeLike,
18};
19use super::Location;
20use crate::{context::Context, string_ref::StringRef, utility::print_callback};
21use mlir_sys::{
22 mlirBF16TypeGet, mlirF16TypeGet, mlirF32TypeGet, mlirF64TypeGet, mlirIndexTypeGet,
23 mlirNoneTypeGet, mlirTypeEqual, mlirTypeParseGet, mlirTypePrint, mlirVectorTypeGet,
24 mlirVectorTypeGetChecked, MlirType,
25};
26use std::{
27 ffi::c_void,
28 fmt::{self, Debug, Display, Formatter},
29 marker::PhantomData,
30};
31
32#[derive(Clone, Copy)]
35pub struct Type<'c> {
36 raw: MlirType,
37 _context: PhantomData<&'c Context>,
38}
39
40impl<'c> Type<'c> {
41 pub fn parse(context: &'c Context, source: &str) -> Option<Self> {
43 unsafe {
44 Self::from_option_raw(mlirTypeParseGet(
45 context.to_raw(),
46 StringRef::new(source).to_raw(),
47 ))
48 }
49 }
50
51 pub fn bfloat16(context: &'c Context) -> Self {
53 unsafe { Self::from_raw(mlirBF16TypeGet(context.to_raw())) }
54 }
55
56 pub fn float16(context: &'c Context) -> Self {
58 unsafe { Self::from_raw(mlirF16TypeGet(context.to_raw())) }
59 }
60
61 pub fn float32(context: &'c Context) -> Self {
63 unsafe { Self::from_raw(mlirF32TypeGet(context.to_raw())) }
64 }
65
66 pub fn float64(context: &'c Context) -> Self {
68 unsafe { Self::from_raw(mlirF64TypeGet(context.to_raw())) }
69 }
70
71 pub fn index(context: &'c Context) -> Self {
73 unsafe { Self::from_raw(mlirIndexTypeGet(context.to_raw())) }
74 }
75
76 pub fn none(context: &'c Context) -> Self {
78 unsafe { Self::from_raw(mlirNoneTypeGet(context.to_raw())) }
79 }
80
81 pub fn vector(dimensions: &[u64], r#type: Self) -> Self {
83 unsafe {
84 Self::from_raw(mlirVectorTypeGet(
85 dimensions.len() as isize,
86 dimensions.as_ptr() as *const i64,
87 r#type.raw,
88 ))
89 }
90 }
91
92 pub fn vector_checked(
94 location: Location<'c>,
95 dimensions: &[u64],
96 r#type: Self,
97 ) -> Option<Self> {
98 unsafe {
99 Self::from_option_raw(mlirVectorTypeGetChecked(
100 location.to_raw(),
101 dimensions.len() as isize,
102 dimensions.as_ptr() as *const i64,
103 r#type.raw,
104 ))
105 }
106 }
107
108 pub unsafe fn from_raw(raw: MlirType) -> Self {
114 Self {
115 raw,
116 _context: Default::default(),
117 }
118 }
119
120 pub unsafe fn from_option_raw(raw: MlirType) -> Option<Self> {
126 if raw.ptr.is_null() {
127 None
128 } else {
129 Some(Self::from_raw(raw))
130 }
131 }
132}
133
134impl<'c> TypeLike<'c> for Type<'c> {
135 fn to_raw(&self) -> MlirType {
136 self.raw
137 }
138}
139
140impl PartialEq for Type<'_> {
141 fn eq(&self, other: &Self) -> bool {
142 unsafe { mlirTypeEqual(self.raw, other.raw) }
143 }
144}
145
146impl Eq for Type<'_> {}
147
148impl Display for Type<'_> {
149 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
150 let mut data = (formatter, Ok(()));
151
152 unsafe {
153 mlirTypePrint(
154 self.raw,
155 Some(print_callback),
156 &mut data as *mut _ as *mut c_void,
157 );
158 }
159
160 data.1
161 }
162}
163
164impl Debug for Type<'_> {
165 fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
166 write!(formatter, "Type(")?;
167 Display::fmt(self, formatter)?;
168 write!(formatter, ")")
169 }
170}
171
172from_subtypes!(
173 Type,
174 FunctionType,
175 IntegerType,
176 MemRefType,
177 RankedTensorType,
178 TupleType
179);
180
181#[cfg(test)]
182mod tests {
183 use crate::test::create_test_context;
184
185 use super::*;
186
187 #[test]
188 fn new() {
189 let context = create_test_context();
190 Type::parse(&context, "f32");
191 }
192
193 #[test]
194 fn integer() {
195 let context = create_test_context();
196
197 assert_eq!(
198 Type::from(IntegerType::new(&context, 42)),
199 Type::parse(&context, "i42").unwrap()
200 );
201 }
202
203 #[test]
204 fn index() {
205 let context = create_test_context();
206
207 assert_eq!(
208 Type::index(&context),
209 Type::parse(&context, "index").unwrap()
210 );
211 }
212
213 #[test]
214 fn vector() {
215 let context = create_test_context();
216
217 assert_eq!(
218 Type::vector(&[42], Type::float64(&context)),
219 Type::parse(&context, "vector<42xf64>").unwrap()
220 );
221 }
222
223 #[test]
224 #[ignore = "SIGABRT on llvm with assertions on"]
225 fn vector_with_invalid_dimension() {
226 let context = create_test_context();
227
228 assert_eq!(
229 Type::vector(&[0], IntegerType::new(&context, 32).into()).to_string(),
230 "vector<0xi32>"
231 );
232 }
233
234 #[test]
235 fn vector_checked() {
236 let context = create_test_context();
237
238 assert_eq!(
239 Type::vector_checked(
240 Location::unknown(&context),
241 &[42],
242 IntegerType::new(&context, 32).into()
243 ),
244 Type::parse(&context, "vector<42xi32>")
245 );
246 }
247
248 #[test]
249 fn vector_checked_fail() {
250 let context = create_test_context();
251
252 assert_eq!(
253 Type::vector_checked(Location::unknown(&context), &[0], Type::index(&context)),
254 None
255 );
256 }
257
258 #[test]
259 fn equal() {
260 let context = create_test_context();
261
262 assert_eq!(Type::index(&context), Type::index(&context));
263 }
264
265 #[test]
266 fn not_equal() {
267 let context = create_test_context();
268
269 assert_ne!(Type::index(&context), Type::float64(&context));
270 }
271
272 #[test]
273 fn display() {
274 let context = create_test_context();
275
276 assert_eq!(Type::index(&context).to_string(), "index");
277 }
278
279 #[test]
280 fn debug() {
281 let context = create_test_context();
282
283 assert_eq!(format!("{:?}", Type::index(&context)), "Type(index)");
284 }
285}