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}