Skip to main content

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