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}