Skip to main content

inkwell/types/
array_type.rs

1#[allow(deprecated)]
2use llvm_sys::core::LLVMGetArrayLength;
3use llvm_sys::prelude::LLVMTypeRef;
4
5use crate::context::ContextRef;
6use crate::support::LLVMString;
7use crate::types::enums::BasicMetadataTypeEnum;
8use crate::types::traits::AsTypeRef;
9use crate::types::{BasicTypeEnum, FunctionType, PointerType, Type};
10use crate::values::{ArrayValue, IntValue};
11use crate::AddressSpace;
12
13use std::fmt::{self, Display};
14
15/// An `ArrayType` is the type of contiguous constants or variables.
16#[derive(Debug, PartialEq, Eq, Clone, Copy)]
17pub struct ArrayType<'ctx> {
18    array_type: Type<'ctx>,
19}
20
21impl<'ctx> ArrayType<'ctx> {
22    /// Create `ArrayType` from [`LLVMTypeRef`]
23    ///
24    /// # Safety
25    /// Undefined behavior, if referenced type isn't array type
26    pub unsafe fn new(array_type: LLVMTypeRef) -> Self {
27        assert!(!array_type.is_null());
28
29        ArrayType {
30            array_type: Type::new(array_type),
31        }
32    }
33
34    // TODO: impl only for ArrayType<!StructType<Opaque>>
35    /// Gets the size of this `ArrayType`. Value may vary depending on the target architecture.
36    ///
37    /// # Example
38    ///
39    /// ```no_run
40    /// use inkwell::context::Context;
41    ///
42    /// let context = Context::create();
43    /// let i8_type = context.i8_type();
44    /// let i8_array_type = i8_type.array_type(3);
45    /// let i8_array_type_size = i8_array_type.size_of();
46    /// ```
47    pub fn size_of(self) -> Option<IntValue<'ctx>> {
48        self.array_type.size_of()
49    }
50
51    /// Creates a `PointerType` with this `ArrayType` for its element type.
52    ///
53    /// # Example
54    ///
55    /// ```no_run
56    /// use inkwell::context::Context;
57    /// use inkwell::AddressSpace;
58    ///
59    /// let context = Context::create();
60    /// let i8_type = context.i8_type();
61    /// let i8_array_type = i8_type.array_type(3);
62    /// let i8_array_ptr_type = i8_array_type.ptr_type(AddressSpace::default());
63    ///
64    /// #[cfg(feature = "typed-pointers")]
65    /// assert_eq!(i8_array_ptr_type.get_element_type().into_array_type(), i8_array_type);
66    /// ```
67    #[cfg_attr(
68        any(
69            all(feature = "llvm15-0", not(feature = "typed-pointers")),
70            all(feature = "llvm16-0", not(feature = "typed-pointers")),
71            feature = "llvm17-0",
72            feature = "llvm18-1",
73            feature = "llvm19-1",
74            feature = "llvm20-1",
75            feature = "llvm21-1",
76        ),
77        deprecated(
78            note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead."
79        )
80    )]
81    pub fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
82        self.array_type.ptr_type(address_space)
83    }
84
85    /// Gets a reference to the `Context` this `ArrayType` was created in.
86    ///
87    /// # Example
88    ///
89    /// ```no_run
90    /// use inkwell::context::Context;
91    ///
92    /// let context = Context::create();
93    /// let i8_type = context.i8_type();
94    /// let i8_array_type = i8_type.array_type(3);
95    ///
96    /// assert_eq!(i8_array_type.get_context(), context);
97    /// ```
98    pub fn get_context(self) -> ContextRef<'ctx> {
99        self.array_type.get_context()
100    }
101
102    /// Creates a `FunctionType` with this `ArrayType` for its return type.
103    ///
104    /// # Example
105    ///
106    /// ```no_run
107    /// use inkwell::context::Context;
108    ///
109    /// let context = Context::create();
110    /// let i8_type = context.i8_type();
111    /// let i8_array_type = i8_type.array_type(3);
112    /// let fn_type = i8_array_type.fn_type(&[], false);
113    /// ```
114    pub fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> {
115        self.array_type.fn_type(param_types, is_var_args)
116    }
117
118    /// Creates an `ArrayType` with this `ArrayType` for its element type.
119    ///
120    /// # Example
121    ///
122    /// ```no_run
123    /// use inkwell::context::Context;
124    ///
125    /// let context = Context::create();
126    /// let i8_type = context.i8_type();
127    /// let i8_array_type = i8_type.array_type(3);
128    /// let i8_array_array_type = i8_array_type.array_type(3);
129    ///
130    /// assert_eq!(i8_array_array_type.len(), 3);
131    /// assert_eq!(i8_array_array_type.get_element_type().into_array_type(), i8_array_type);
132    /// ```
133    pub fn array_type(self, size: u32) -> ArrayType<'ctx> {
134        self.array_type.array_type(size)
135    }
136
137    /// Creates a constant `ArrayValue` of `ArrayValue`s.
138    ///
139    /// # Example
140    /// ```no_run
141    /// use inkwell::context::Context;
142    ///
143    /// let context = Context::create();
144    /// let f32_type = context.f32_type();
145    /// let f32_array_type = f32_type.array_type(3);
146    /// let f32_array_val = f32_array_type.const_zero();
147    /// let f32_array_array = f32_array_type.const_array(&[f32_array_val, f32_array_val]);
148    ///
149    /// assert!(f32_array_array.is_const());
150    /// ```
151    pub fn const_array(self, values: &[ArrayValue<'ctx>]) -> ArrayValue<'ctx> {
152        unsafe { ArrayValue::new_const_array(&self, values) }
153    }
154
155    /// Creates a constant zero value of this `ArrayType`.
156    ///
157    /// # Example
158    ///
159    /// ```no_run
160    /// use inkwell::context::Context;
161    ///
162    /// let context = Context::create();
163    /// let i8_type = context.i8_type();
164    /// let i8_array_type = i8_type.array_type(3);
165    /// let i8_array_zero = i8_array_type.const_zero();
166    /// ```
167    pub fn const_zero(self) -> ArrayValue<'ctx> {
168        unsafe { ArrayValue::new(self.array_type.const_zero()) }
169    }
170
171    /// Gets the length of this `ArrayType`.
172    ///
173    /// # Example
174    ///
175    /// ```no_run
176    /// use inkwell::context::Context;
177    ///
178    /// let context = Context::create();
179    /// let i8_type = context.i8_type();
180    /// let i8_array_type = i8_type.array_type(3);
181    ///
182    /// assert_eq!(i8_array_type.len(), 3);
183    /// ```
184    pub fn len(self) -> u32 {
185        #[allow(deprecated)]
186        unsafe {
187            LLVMGetArrayLength(self.as_type_ref())
188        }
189    }
190
191    /// Returns `true` if this `ArrayType` contains no elements.
192    pub fn is_empty(self) -> bool {
193        self.len() == 0
194    }
195
196    /// Print the definition of an `ArrayType` to `LLVMString`
197    pub fn print_to_string(self) -> LLVMString {
198        self.array_type.print_to_string()
199    }
200
201    /// Creates an undefined instance of a `ArrayType`.
202    ///
203    /// # Example
204    /// ```no_run
205    /// use inkwell::context::Context;
206    ///
207    /// let context = Context::create();
208    /// let i8_type = context.i8_type();
209    /// let i8_array_type = i8_type.array_type(3);
210    /// let i8_array_undef = i8_array_type.get_undef();
211    ///
212    /// assert!(i8_array_undef.is_undef());
213    /// ```
214    pub fn get_undef(self) -> ArrayValue<'ctx> {
215        unsafe { ArrayValue::new(self.array_type.get_undef()) }
216    }
217
218    /// Creates a poison instance of a `ArrayType`.
219    ///
220    /// # Example
221    /// ```no_run
222    /// use inkwell::context::Context;
223    /// use inkwell::values::AnyValue;
224    ///
225    /// let context = Context::create();
226    /// let i8_type = context.i8_type();
227    /// let i8_array_type = i8_type.array_type(3);
228    /// let i8_array_poison = i8_array_type.get_poison();
229    ///
230    /// assert!(i8_array_poison.is_poison());
231    /// ```
232    #[llvm_versions(12..)]
233    pub fn get_poison(self) -> ArrayValue<'ctx> {
234        unsafe { ArrayValue::new(self.array_type.get_poison()) }
235    }
236
237    // SubType: ArrayType<BT> -> BT?
238    /// Gets the element type of this `ArrayType`.
239    ///
240    /// # Example
241    ///
242    /// ```no_run
243    /// use inkwell::context::Context;
244    ///
245    /// let context = Context::create();
246    /// let i8_type = context.i8_type();
247    /// let i8_array_type = i8_type.array_type(3);
248    ///
249    /// assert_eq!(i8_array_type.get_element_type().into_int_type(), i8_type);
250    /// ```
251    pub fn get_element_type(self) -> BasicTypeEnum<'ctx> {
252        self.array_type.get_element_type().as_basic_type_enum()
253    }
254}
255
256unsafe impl AsTypeRef for ArrayType<'_> {
257    fn as_type_ref(&self) -> LLVMTypeRef {
258        self.array_type.ty
259    }
260}
261
262impl Display for ArrayType<'_> {
263    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
264        write!(f, "{}", self.print_to_string())
265    }
266}