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}