Skip to main content

melior/dialect/llvm/
type.rs

1//! LLVM types
2
3use crate::{
4    context::Context,
5    ir::{Type, TypeLike},
6};
7use mlir_sys::{
8    mlirLLVMArrayTypeGet, mlirLLVMFunctionTypeGet, mlirLLVMPointerTypeGet,
9    mlirLLVMStructTypeLiteralGet, mlirLLVMVoidTypeGet,
10};
11
12// TODO Check if the `llvm` dialect is loaded on use of those functions.
13
14/// Creates an LLVM array type.
15pub fn array(r#type: Type, len: u32) -> Type {
16    unsafe { Type::from_raw(mlirLLVMArrayTypeGet(r#type.to_raw(), len)) }
17}
18
19/// Creates an LLVM function type.
20pub fn function<'c>(
21    result: Type<'c>,
22    arguments: &[Type<'c>],
23    variadic_arguments: bool,
24) -> Type<'c> {
25    unsafe {
26        Type::from_raw(mlirLLVMFunctionTypeGet(
27            result.to_raw(),
28            arguments.len() as isize,
29            arguments as *const _ as *const _,
30            variadic_arguments,
31        ))
32    }
33}
34
35/// Creates an LLVM opaque pointer type at address space 0.
36#[deprecated(
37    since = "0.11.0",
38    note = "please use the pointer method, all pointers are opaque in LLVM 19"
39)]
40pub fn opaque_pointer(context: &Context) -> Type {
41    pointer(context, 0)
42}
43
44/// Creates an LLVM pointer type in the given address space.
45pub fn pointer(context: &Context, address_space: u32) -> Type {
46    unsafe { Type::from_raw(mlirLLVMPointerTypeGet(context.to_raw(), address_space)) }
47}
48
49/// Creates an LLVM struct type.
50pub fn r#struct<'c>(context: &'c Context, fields: &[Type<'c>], packed: bool) -> Type<'c> {
51    unsafe {
52        Type::from_raw(mlirLLVMStructTypeLiteralGet(
53            context.to_raw(),
54            fields.len() as isize,
55            fields as *const _ as *const _,
56            packed,
57        ))
58    }
59}
60
61/// Creates an LLVM void type.
62pub fn void(context: &Context) -> Type {
63    unsafe { Type::from_raw(mlirLLVMVoidTypeGet(context.to_raw())) }
64}
65
66#[cfg(test)]
67mod tests {
68    use super::*;
69    use crate::{dialect, ir::r#type::IntegerType};
70
71    fn create_context() -> Context {
72        let context = Context::new();
73
74        dialect::DialectHandle::llvm().register_dialect(&context);
75        context.get_or_load_dialect("llvm");
76
77        context
78    }
79
80    #[test]
81    fn pointer() {
82        let context = create_context();
83
84        assert_eq!(
85            super::pointer(&context, 0),
86            Type::parse(&context, "!llvm.ptr").unwrap()
87        );
88    }
89
90    #[test]
91    fn pointer_with_address_space() {
92        let context = create_context();
93
94        assert_eq!(
95            super::pointer(&context, 4),
96            Type::parse(&context, "!llvm.ptr<4>").unwrap()
97        );
98    }
99
100    #[test]
101    fn void() {
102        let context = create_context();
103
104        assert_eq!(
105            super::void(&context),
106            Type::parse(&context, "!llvm.void").unwrap()
107        );
108    }
109
110    #[test]
111    fn array() {
112        let context = create_context();
113        let i32 = IntegerType::new(&context, 32).into();
114
115        assert_eq!(
116            super::array(i32, 4),
117            Type::parse(&context, "!llvm.array<4 x i32>").unwrap()
118        );
119    }
120
121    #[test]
122    fn function() {
123        let context = create_context();
124        let i8 = IntegerType::new(&context, 8).into();
125        let i32 = IntegerType::new(&context, 32).into();
126        let i64 = IntegerType::new(&context, 64).into();
127
128        assert_eq!(
129            super::function(i8, &[i32, i64], false),
130            Type::parse(&context, "!llvm.func<i8 (i32, i64)>").unwrap()
131        );
132    }
133
134    #[test]
135    fn r#struct() {
136        let context = create_context();
137        let i32 = IntegerType::new(&context, 32).into();
138        let i64 = IntegerType::new(&context, 64).into();
139
140        assert_eq!(
141            super::r#struct(&context, &[i32, i64], false),
142            Type::parse(&context, "!llvm.struct<(i32, i64)>").unwrap()
143        );
144    }
145
146    #[test]
147    fn packed_struct() {
148        let context = create_context();
149        let i32 = IntegerType::new(&context, 32).into();
150        let i64 = IntegerType::new(&context, 64).into();
151
152        assert_eq!(
153            super::r#struct(&context, &[i32, i64], true),
154            Type::parse(&context, "!llvm.struct<packed (i32, i64)>").unwrap()
155        );
156    }
157}