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}