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    /// Gets the alignment of this `ArrayType`. Value may vary depending on the target architecture.
52    ///
53    /// # Example
54    ///
55    /// ```no_run
56    /// use inkwell::context::Context;
57    ///
58    /// let context = Context::create();
59    /// let i8_type = context.i8_type();
60    /// let i8_array_type = i8_type.array_type(3);
61    /// let i8_array_type_alignment = i8_array_type.get_alignment();
62    /// ```
63    pub fn get_alignment(self) -> IntValue<'ctx> {
64        self.array_type.get_alignment()
65    }
66
67    /// Creates a `PointerType` with this `ArrayType` for its element type.
68    ///
69    /// # Example
70    ///
71    /// ```no_run
72    /// use inkwell::context::Context;
73    /// use inkwell::AddressSpace;
74    ///
75    /// let context = Context::create();
76    /// let i8_type = context.i8_type();
77    /// let i8_array_type = i8_type.array_type(3);
78    /// let i8_array_ptr_type = i8_array_type.ptr_type(AddressSpace::default());
79    ///
80    /// #[cfg(feature = "typed-pointers")]
81    /// assert_eq!(i8_array_ptr_type.get_element_type().into_array_type(), i8_array_type);
82    /// ```
83    #[cfg_attr(
84        any(
85            all(feature = "llvm15-0", not(feature = "typed-pointers")),
86            all(feature = "llvm16-0", not(feature = "typed-pointers")),
87            feature = "llvm17-0",
88            feature = "llvm18-0"
89        ),
90        deprecated(
91            note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead."
92        )
93    )]
94    pub fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
95        self.array_type.ptr_type(address_space)
96    }
97
98    /// Gets a reference to the `Context` this `ArrayType` was created in.
99    ///
100    /// # Example
101    ///
102    /// ```no_run
103    /// use inkwell::context::Context;
104    ///
105    /// let context = Context::create();
106    /// let i8_type = context.i8_type();
107    /// let i8_array_type = i8_type.array_type(3);
108    ///
109    /// assert_eq!(i8_array_type.get_context(), context);
110    /// ```
111    pub fn get_context(self) -> ContextRef<'ctx> {
112        self.array_type.get_context()
113    }
114
115    /// Creates a `FunctionType` with this `ArrayType` for its return type.
116    ///
117    /// # Example
118    ///
119    /// ```no_run
120    /// use inkwell::context::Context;
121    ///
122    /// let context = Context::create();
123    /// let i8_type = context.i8_type();
124    /// let i8_array_type = i8_type.array_type(3);
125    /// let fn_type = i8_array_type.fn_type(&[], false);
126    /// ```
127    pub fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> {
128        self.array_type.fn_type(param_types, is_var_args)
129    }
130
131    /// Creates an `ArrayType` with this `ArrayType` for its element type.
132    ///
133    /// # Example
134    ///
135    /// ```no_run
136    /// use inkwell::context::Context;
137    ///
138    /// let context = Context::create();
139    /// let i8_type = context.i8_type();
140    /// let i8_array_type = i8_type.array_type(3);
141    /// let i8_array_array_type = i8_array_type.array_type(3);
142    ///
143    /// assert_eq!(i8_array_array_type.len(), 3);
144    /// assert_eq!(i8_array_array_type.get_element_type().into_array_type(), i8_array_type);
145    /// ```
146    pub fn array_type(self, size: u32) -> ArrayType<'ctx> {
147        self.array_type.array_type(size)
148    }
149
150    /// Creates a constant `ArrayValue` of `ArrayValue`s.
151    ///
152    /// # Example
153    /// ```no_run
154    /// use inkwell::context::Context;
155    ///
156    /// let context = Context::create();
157    /// let f32_type = context.f32_type();
158    /// let f32_array_type = f32_type.array_type(3);
159    /// let f32_array_val = f32_array_type.const_zero();
160    /// let f32_array_array = f32_array_type.const_array(&[f32_array_val, f32_array_val]);
161    ///
162    /// assert!(f32_array_array.is_const());
163    /// ```
164    pub fn const_array(self, values: &[ArrayValue<'ctx>]) -> ArrayValue<'ctx> {
165        unsafe { ArrayValue::new_const_array(&self, values) }
166    }
167
168    /// Creates a constant zero value of this `ArrayType`.
169    ///
170    /// # Example
171    ///
172    /// ```no_run
173    /// use inkwell::context::Context;
174    ///
175    /// let context = Context::create();
176    /// let i8_type = context.i8_type();
177    /// let i8_array_type = i8_type.array_type(3);
178    /// let i8_array_zero = i8_array_type.const_zero();
179    /// ```
180    pub fn const_zero(self) -> ArrayValue<'ctx> {
181        unsafe { ArrayValue::new(self.array_type.const_zero()) }
182    }
183
184    /// Gets the length of this `ArrayType`.
185    ///
186    /// # Example
187    ///
188    /// ```no_run
189    /// use inkwell::context::Context;
190    ///
191    /// let context = Context::create();
192    /// let i8_type = context.i8_type();
193    /// let i8_array_type = i8_type.array_type(3);
194    ///
195    /// assert_eq!(i8_array_type.len(), 3);
196    /// ```
197    pub fn len(self) -> u32 {
198        #[allow(deprecated)]
199        unsafe {
200            LLVMGetArrayLength(self.as_type_ref())
201        }
202    }
203
204    /// Returns `true` if this `ArrayType` contains no elements.
205    pub fn is_empty(self) -> bool {
206        self.len() == 0
207    }
208
209    /// Print the definition of an `ArrayType` to `LLVMString`
210    pub fn print_to_string(self) -> LLVMString {
211        self.array_type.print_to_string()
212    }
213
214    /// Creates an undefined instance of a `ArrayType`.
215    ///
216    /// # Example
217    /// ```no_run
218    /// use inkwell::context::Context;
219    ///
220    /// let context = Context::create();
221    /// let i8_type = context.i8_type();
222    /// let i8_array_type = i8_type.array_type(3);
223    /// let i8_array_undef = i8_array_type.get_undef();
224    ///
225    /// assert!(i8_array_undef.is_undef());
226    /// ```
227    pub fn get_undef(self) -> ArrayValue<'ctx> {
228        unsafe { ArrayValue::new(self.array_type.get_undef()) }
229    }
230
231    /// Creates a poison instance of a `ArrayType`.
232    ///
233    /// # Example
234    /// ```no_run
235    /// use inkwell::context::Context;
236    /// use inkwell::values::AnyValue;
237    ///
238    /// let context = Context::create();
239    /// let i8_type = context.i8_type();
240    /// let i8_array_type = i8_type.array_type(3);
241    /// let i8_array_poison = i8_array_type.get_poison();
242    ///
243    /// assert!(i8_array_poison.is_poison());
244    /// ```
245    #[llvm_versions(12..)]
246    pub fn get_poison(self) -> ArrayValue<'ctx> {
247        unsafe { ArrayValue::new(self.array_type.get_poison()) }
248    }
249
250    // SubType: ArrayType<BT> -> BT?
251    /// Gets the element type of this `ArrayType`.
252    ///
253    /// # Example
254    ///
255    /// ```no_run
256    /// use inkwell::context::Context;
257    ///
258    /// let context = Context::create();
259    /// let i8_type = context.i8_type();
260    /// let i8_array_type = i8_type.array_type(3);
261    ///
262    /// assert_eq!(i8_array_type.get_element_type().into_int_type(), i8_type);
263    /// ```
264    pub fn get_element_type(self) -> BasicTypeEnum<'ctx> {
265        self.array_type.get_element_type().as_basic_type_enum()
266    }
267}
268
269unsafe impl AsTypeRef for ArrayType<'_> {
270    fn as_type_ref(&self) -> LLVMTypeRef {
271        self.array_type.ty
272    }
273}
274
275impl Display for ArrayType<'_> {
276    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
277        write!(f, "{}", self.print_to_string())
278    }
279}