inkwell/types/
vec_type.rs

1use llvm_sys::core::{LLVMConstVector, LLVMGetVectorSize};
2use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef};
3
4use crate::context::ContextRef;
5use crate::support::LLVMString;
6use crate::types::enums::BasicMetadataTypeEnum;
7use crate::types::{traits::AsTypeRef, ArrayType, BasicTypeEnum, FunctionType, PointerType, Type};
8use crate::values::{ArrayValue, BasicValue, IntValue, VectorValue};
9use crate::AddressSpace;
10
11use std::fmt::{self, Display};
12
13/// A `VectorType` is the type of a multiple value SIMD constant or variable.
14#[derive(Debug, PartialEq, Eq, Clone, Copy)]
15pub struct VectorType<'ctx> {
16    vec_type: Type<'ctx>,
17}
18
19impl<'ctx> VectorType<'ctx> {
20    /// Create `VectorType` from [`LLVMTypeRef`]
21    ///
22    /// # Safety
23    /// Undefined behavior, if referenced type isn't vector type
24    pub unsafe fn new(vector_type: LLVMTypeRef) -> Self {
25        assert!(!vector_type.is_null());
26
27        VectorType {
28            vec_type: Type::new(vector_type),
29        }
30    }
31
32    // TODO: impl only for VectorType<!StructType<Opaque>>
33    // REVIEW: What about Opaque struct hiding in deeper levels
34    // like VectorType<ArrayType<StructType<Opaque>>>?
35    /// Gets the size of this `VectorType`. 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 f32_type = context.f32_type();
44    /// let f32_vec_type = f32_type.vec_type(3);
45    /// let f32_vec_type_size = f32_vec_type.size_of();
46    /// ```
47    pub fn size_of(self) -> Option<IntValue<'ctx>> {
48        self.vec_type.size_of()
49    }
50
51    /// Gets the alignment of this `VectorType`. 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 f32_type = context.f32_type();
60    /// let f32_vec_type = f32_type.vec_type(7);
61    /// let f32_type_alignment = f32_vec_type.get_alignment();
62    /// ```
63    pub fn get_alignment(self) -> IntValue<'ctx> {
64        self.vec_type.get_alignment()
65    }
66
67    /// Gets the size of this `VectorType`.
68    ///
69    /// # Example
70    ///
71    /// ```no_run
72    /// use inkwell::context::Context;
73    ///
74    /// let context = Context::create();
75    /// let f32_type = context.f32_type();
76    /// let f32_vector_type = f32_type.vec_type(3);
77    ///
78    /// assert_eq!(f32_vector_type.get_size(), 3);
79    /// assert_eq!(f32_vector_type.get_element_type().into_float_type(), f32_type);
80    /// ```
81    pub fn get_size(self) -> u32 {
82        unsafe { LLVMGetVectorSize(self.as_type_ref()) }
83    }
84
85    // REVIEW:
86    // TypeSafety v2 (GH Issue #8) could help here by constraining
87    // sub-types to be the same across the board. For now, we could
88    // have V just be the set of Int & Float and any others that
89    // are valid for Vectors
90    // REVIEW: Maybe we could make this use &self if the vector size
91    // is stored as a const and the input values took a const size?
92    // Something like: values: &[&V; self.size]. Doesn't sound possible though
93    /// Creates a constant `VectorValue`.
94    ///
95    /// # Example
96    /// ```no_run
97    /// use inkwell::context::Context;
98    /// use inkwell::types::VectorType;
99    ///
100    /// let context = Context::create();
101    /// let f32_type = context.f32_type();
102    /// let f32_val = f32_type.const_float(0.);
103    /// let f32_val2 = f32_type.const_float(2.);
104    /// let f32_vec_val = VectorType::const_vector(&[f32_val, f32_val2]);
105    ///
106    /// assert!(f32_vec_val.is_constant_vector());
107    /// ```
108    pub fn const_vector<V: BasicValue<'ctx>>(values: &[V]) -> VectorValue<'ctx> {
109        let mut values: Vec<LLVMValueRef> = values.iter().map(|val| val.as_value_ref()).collect();
110        unsafe { VectorValue::new(LLVMConstVector(values.as_mut_ptr(), values.len() as u32)) }
111    }
112
113    /// Creates a constant zero value of this `VectorType`.
114    ///
115    /// # Example
116    ///
117    /// ```no_run
118    /// use inkwell::context::Context;
119    ///
120    /// let context = Context::create();
121    /// let f32_type = context.f32_type();
122    /// let f32_vec_type = f32_type.vec_type(7);
123    /// let f32_vec_zero = f32_vec_type.const_zero();
124    /// ```
125    pub fn const_zero(self) -> VectorValue<'ctx> {
126        unsafe { VectorValue::new(self.vec_type.const_zero()) }
127    }
128
129    /// Print the definition of a `VectorType` to `LLVMString`.
130    pub fn print_to_string(self) -> LLVMString {
131        self.vec_type.print_to_string()
132    }
133
134    /// Creates an undefined instance of a `VectorType`.
135    ///
136    /// # Example
137    /// ```no_run
138    /// use inkwell::context::Context;
139    /// use inkwell::AddressSpace;
140    ///
141    /// let context = Context::create();
142    /// let f32_type = context.f32_type();
143    /// let f32_vec_type = f32_type.vec_type(3);
144    /// let f32_vec_undef = f32_vec_type.get_undef();
145    ///
146    /// assert!(f32_vec_undef.is_undef());
147    /// ```
148    pub fn get_undef(self) -> VectorValue<'ctx> {
149        unsafe { VectorValue::new(self.vec_type.get_undef()) }
150    }
151
152    /// Creates a poison instance of a `VectorType`.
153    ///
154    /// # Example
155    /// ```no_run
156    /// use inkwell::context::Context;
157    /// use inkwell::AddressSpace;
158    ///
159    /// let context = Context::create();
160    /// let f32_type = context.f32_type();
161    /// let f32_vec_type = f32_type.vec_type(3);
162    /// let f32_vec_poison = f32_vec_type.get_undef();
163    ///
164    /// assert!(f32_vec_poison.is_undef());
165    /// ```
166    #[llvm_versions(12..)]
167    pub fn get_poison(self) -> VectorValue<'ctx> {
168        unsafe { VectorValue::new(self.vec_type.get_poison()) }
169    }
170
171    // SubType: VectorType<BT> -> BT?
172    /// Gets the element type of this `VectorType`.
173    ///
174    /// # Example
175    ///
176    /// ```no_run
177    /// use inkwell::context::Context;
178    ///
179    /// let context = Context::create();
180    /// let f32_type = context.f32_type();
181    /// let f32_vector_type = f32_type.vec_type(3);
182    ///
183    /// assert_eq!(f32_vector_type.get_size(), 3);
184    /// assert_eq!(f32_vector_type.get_element_type().into_float_type(), f32_type);
185    /// ```
186    pub fn get_element_type(self) -> BasicTypeEnum<'ctx> {
187        self.vec_type.get_element_type().as_basic_type_enum()
188    }
189
190    /// Creates a `PointerType` with this `VectorType` for its element type.
191    ///
192    /// # Example
193    ///
194    /// ```no_run
195    /// use inkwell::context::Context;
196    /// use inkwell::AddressSpace;
197    ///
198    /// let context = Context::create();
199    /// let f32_type = context.f32_type();
200    /// let f32_vec_type = f32_type.vec_type(3);
201    /// let f32_vec_ptr_type = f32_vec_type.ptr_type(AddressSpace::default());
202    ///
203    /// #[cfg(feature = "typed-pointers")]
204    /// assert_eq!(f32_vec_ptr_type.get_element_type().into_vector_type(), f32_vec_type);
205    /// ```
206    #[cfg_attr(
207        any(
208            all(feature = "llvm15-0", not(feature = "typed-pointers")),
209            all(feature = "llvm16-0", not(feature = "typed-pointers")),
210            feature = "llvm17-0",
211            feature = "llvm18-0"
212        ),
213        deprecated(
214            note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead."
215        )
216    )]
217    pub fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
218        self.vec_type.ptr_type(address_space)
219    }
220
221    /// Creates a `FunctionType` with this `VectorType` for its return type.
222    ///
223    /// # Example
224    ///
225    /// ```no_run
226    /// use inkwell::context::Context;
227    ///
228    /// let context = Context::create();
229    /// let f32_type = context.f32_type();
230    /// let f32_vec_type = f32_type.vec_type(3);
231    /// let fn_type = f32_vec_type.fn_type(&[], false);
232    /// ```
233    pub fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> {
234        self.vec_type.fn_type(param_types, is_var_args)
235    }
236
237    /// Creates an `ArrayType` with this `VectorType` for its element type.
238    ///
239    /// # Example
240    ///
241    /// ```no_run
242    /// use inkwell::context::Context;
243    ///
244    /// let context = Context::create();
245    /// let f32_type = context.f32_type();
246    /// let f32_vec_type = f32_type.vec_type(3);
247    /// let f32_vec_array_type = f32_vec_type.array_type(3);
248    ///
249    /// assert_eq!(f32_vec_array_type.len(), 3);
250    /// assert_eq!(f32_vec_array_type.get_element_type().into_vector_type(), f32_vec_type);
251    /// ```
252    pub fn array_type(self, size: u32) -> ArrayType<'ctx> {
253        self.vec_type.array_type(size)
254    }
255
256    /// Creates a constant `ArrayValue`.
257    ///
258    /// # Example
259    /// ```no_run
260    /// use inkwell::context::Context;
261    /// use inkwell::types::VectorType;
262    ///
263    /// let context = Context::create();
264    /// let f32_type = context.f32_type();
265    /// let f32_val = f32_type.const_float(0.);
266    /// let f32_val2 = f32_type.const_float(2.);
267    /// let f32_vec_type = f32_type.vec_type(2);
268    /// let f32_vec_val = VectorType::const_vector(&[f32_val, f32_val2]);
269    /// let f32_array = f32_vec_type.const_array(&[f32_vec_val, f32_vec_val]);
270    ///
271    /// assert!(f32_array.is_const());
272    /// ```
273    pub fn const_array(self, values: &[VectorValue<'ctx>]) -> ArrayValue<'ctx> {
274        unsafe { ArrayValue::new_const_array(&self, values) }
275    }
276
277    /// Gets a reference to the `Context` this `VectorType` was created in.
278    ///
279    /// # Example
280    ///
281    /// ```no_run
282    /// use inkwell::context::Context;
283    ///
284    /// let context = Context::create();
285    /// let f32_type = context.f32_type();
286    /// let f32_vec_type = f32_type.vec_type(7);
287    ///
288    /// assert_eq!(f32_vec_type.get_context(), context);
289    /// ```
290    pub fn get_context(self) -> ContextRef<'ctx> {
291        self.vec_type.get_context()
292    }
293}
294
295unsafe impl AsTypeRef for VectorType<'_> {
296    fn as_type_ref(&self) -> LLVMTypeRef {
297        self.vec_type.ty
298    }
299}
300
301impl Display for VectorType<'_> {
302    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303        write!(f, "{}", self.print_to_string())
304    }
305}