inkwell/types/scalable_vec_type.rs
1use llvm_sys::core::LLVMGetVectorSize;
2use llvm_sys::prelude::LLVMTypeRef;
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, IntValue, ScalableVectorValue};
9use crate::AddressSpace;
10
11use std::fmt::{self, Display};
12
13/// A `ScalableVectorType` is the type of a scalable multiple value SIMD constant or variable.
14#[derive(Debug, PartialEq, Eq, Clone, Copy)]
15pub struct ScalableVectorType<'ctx> {
16 scalable_vec_type: Type<'ctx>,
17}
18
19impl<'ctx> ScalableVectorType<'ctx> {
20 /// Create `ScalableVectorType` from [`LLVMTypeRef`]
21 ///
22 /// # Safety
23 /// Undefined behavior, if referenced type isn't scalable vector type
24 pub unsafe fn new(scalable_vector_type: LLVMTypeRef) -> Self {
25 assert!(!scalable_vector_type.is_null());
26
27 ScalableVectorType {
28 scalable_vec_type: Type::new(scalable_vector_type),
29 }
30 }
31
32 // TODO: impl only for ScalableVectorType<!StructType<Opaque>>
33 // REVIEW: What about Opaque struct hiding in deeper levels
34 // like ScalableVectorType<ArrayType<StructType<Opaque>>>?
35 /// Gets the size of this `ScalableVectorType`. Value may vary depending on the target architecture.
36 ///
37 /// # Example
38 ///
39 /// ```ignore
40 /// use inkwell::context::Context;
41 ///
42 /// let context = Context::create();
43 /// let f32_type = context.f32_type();
44 /// let f32_scalable_vec_type = f32_type.scalable_vec_type(3);
45 /// let f32_scalable_vec_type_size = f32_scalable_vec_type.size_of();
46 /// ```
47 pub fn size_of(self) -> Option<IntValue<'ctx>> {
48 self.scalable_vec_type.size_of()
49 }
50
51 /// Gets the size of this `ScalableVectorType`.
52 ///
53 /// # Example
54 ///
55 /// ```ignore
56 /// use inkwell::context::Context;
57 ///
58 /// let context = Context::create();
59 /// let f32_type = context.f32_type();
60 /// let f32_scalable_vector_type = f32_type.scalable_vec_type(3);
61 ///
62 /// assert_eq!(f32_scalable_vector_type.get_size(), 3);
63 /// assert_eq!(f32_scalable_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 /// Creates a constant zero value of this `ScalableVectorType`.
70 ///
71 /// # Example
72 ///
73 /// ```ignore
74 /// use inkwell::context::Context;
75 ///
76 /// let context = Context::create();
77 /// let f32_type = context.f32_type();
78 /// let f32_scalable_vec_type = f32_type.scalable_vec_type(7);
79 /// let f32_scalable_vec_zero = f32_scalable_vec_type.const_zero();
80 /// ```
81 pub fn const_zero(self) -> ScalableVectorValue<'ctx> {
82 unsafe { ScalableVectorValue::new(self.scalable_vec_type.const_zero()) }
83 }
84
85 /// Print the definition of a `ScalableVectorType` to `LLVMString`.
86 pub fn print_to_string(self) -> LLVMString {
87 self.scalable_vec_type.print_to_string()
88 }
89
90 /// Creates an undefined instance of a `ScalableVectorType`.
91 ///
92 /// # Example
93 /// ```ignore
94 /// use inkwell::context::Context;
95 /// use inkwell::AddressSpace;
96 ///
97 /// let context = Context::create();
98 /// let f32_type = context.f32_type();
99 /// let f32_scalable_vec_type = f32_type.scalable_vec_type(3);
100 /// let f32_scalable_vec_undef = f32_scalable_vec_type.get_undef();
101 ///
102 /// assert!(f32_scalable_vec_undef.is_undef());
103 /// ```
104 pub fn get_undef(self) -> ScalableVectorValue<'ctx> {
105 unsafe { ScalableVectorValue::new(self.scalable_vec_type.get_undef()) }
106 }
107
108 /// Creates a poison instance of a `ScalableVectorType`.
109 ///
110 /// # Example
111 /// ```ignore
112 /// use inkwell::context::Context;
113 /// use inkwell::AddressSpace;
114 ///
115 /// let context = Context::create();
116 /// let f32_type = context.f32_type();
117 /// let f32_scalable_vec_type = f32_type.scalable_vec_type(3);
118 /// let f32_scalable_vec_poison = f32_scalable_vec_type.get_undef();
119 ///
120 /// assert!(f32_scalable_vec_poison.is_undef());
121 /// ```
122 #[llvm_versions(12..)]
123 pub fn get_poison(self) -> ScalableVectorValue<'ctx> {
124 unsafe { ScalableVectorValue::new(self.scalable_vec_type.get_poison()) }
125 }
126
127 // SubType: ScalableVectorType<BT> -> BT?
128 /// Gets the element type of this `ScalableVectorType`.
129 ///
130 /// # Example
131 ///
132 /// ```ignore
133 /// use inkwell::context::Context;
134 ///
135 /// let context = Context::create();
136 /// let f32_type = context.f32_type();
137 /// let f32_scalable_vector_type = f32_type.scalable_vec_type(3);
138 ///
139 /// assert_eq!(f32_scalable_vector_type.get_size(), 3);
140 /// assert_eq!(f32_scalable_vector_type.get_element_type().into_float_type(), f32_type);
141 /// ```
142 pub fn get_element_type(self) -> BasicTypeEnum<'ctx> {
143 self.scalable_vec_type.get_element_type().as_basic_type_enum()
144 }
145
146 /// Creates a `PointerType` with this `ScalableVectorType` for its element type.
147 ///
148 /// # Example
149 ///
150 /// ```ignore
151 /// use inkwell::context::Context;
152 /// use inkwell::AddressSpace;
153 ///
154 /// let context = Context::create();
155 /// let f32_type = context.f32_type();
156 /// let f32_scalable_vec_type = f32_type.scalable_vec_type(3);
157 /// let f32_scalable_vec_ptr_type = f32_scalable_vec_type.ptr_type(AddressSpace::default());
158 ///
159 /// #[cfg(feature = "typed-pointers")]
160 /// assert_eq!(f32_scalable_vec_ptr_type.get_element_type().into_scalable_vector_type(), f32_scalable_vec_type);
161 /// ```
162 #[cfg_attr(
163 any(
164 all(feature = "llvm15-0", not(feature = "typed-pointers")),
165 all(feature = "llvm16-0", not(feature = "typed-pointers")),
166 feature = "llvm17-0",
167 feature = "llvm18-1",
168 feature = "llvm19-1",
169 feature = "llvm20-1",
170 feature = "llvm21-1",
171 ),
172 deprecated(
173 note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead."
174 )
175 )]
176 pub fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
177 self.scalable_vec_type.ptr_type(address_space)
178 }
179
180 /// Creates a `FunctionType` with this `ScalableVectorType` for its return type.
181 ///
182 /// # Example
183 ///
184 /// ```ignore
185 /// use inkwell::context::Context;
186 ///
187 /// let context = Context::create();
188 /// let f32_type = context.f32_type();
189 /// let f32_scalable_vec_type = f32_type.scalable_vec_type(3);
190 /// let fn_type = f32_scalable_vec_type.fn_type(&[], false);
191 /// ```
192 pub fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> {
193 self.scalable_vec_type.fn_type(param_types, is_var_args)
194 }
195
196 /// Creates an `ArrayType` with this `ScalableVectorType` for its element type.
197 ///
198 /// # Example
199 ///
200 /// ```ignore
201 /// use inkwell::context::Context;
202 ///
203 /// let context = Context::create();
204 /// let f32_type = context.f32_type();
205 /// let f32_scalable_vec_type = f32_type.scalable_vec_type(3);
206 /// let f32_scalable_vec_array_type = f32_scalable_vec_type.array_type(3);
207 ///
208 /// assert_eq!(f32_scalable_vec_array_type.len(), 3);
209 /// assert_eq!(f32_scalable_vec_array_type.get_element_type().into_scalable_vector_type(), f32_scalable_vec_type);
210 /// ```
211 pub fn array_type(self, size: u32) -> ArrayType<'ctx> {
212 self.scalable_vec_type.array_type(size)
213 }
214
215 /// Creates a constant `ArrayValue`.
216 ///
217 /// # Example
218 /// ```ignore
219 /// use inkwell::context::Context;
220 /// use inkwell::types::ScalableVectorType;
221 ///
222 /// let context = Context::create();
223 /// let f32_type = context.f32_type();
224 /// let f32_val = f32_type.const_float(0.);
225 /// let f32_val2 = f32_type.const_float(2.);
226 /// let f32_scalable_vec_type = f32_type.scalable_vec_type(2);
227 /// let f32_scalable_vec_val = f32_scalable_vec_type.const_zero();
228 /// let f32_array = f32_scalable_vec_type.const_array(&[f32_scalable_vec_val, f32_scalable_vec_val]);
229 ///
230 /// assert!(f32_array.is_const());
231 /// ```
232 pub fn const_array(self, values: &[ScalableVectorValue<'ctx>]) -> ArrayValue<'ctx> {
233 unsafe { ArrayValue::new_const_array(&self, values) }
234 }
235
236 /// Gets a reference to the `Context` this `ScalableVectorType` was created in.
237 ///
238 /// # Example
239 ///
240 /// ```ignore
241 /// use inkwell::context::Context;
242 ///
243 /// let context = Context::create();
244 /// let f32_type = context.f32_type();
245 /// let f32_scalable_vec_type = f32_type.scalable_vec_type(7);
246 ///
247 /// assert_eq!(f32_scalable_vec_type.get_context(), context);
248 /// ```
249 pub fn get_context(self) -> ContextRef<'ctx> {
250 self.scalable_vec_type.get_context()
251 }
252}
253
254unsafe impl AsTypeRef for ScalableVectorType<'_> {
255 fn as_type_ref(&self) -> LLVMTypeRef {
256 self.scalable_vec_type.ty
257 }
258}
259
260impl Display for ScalableVectorType<'_> {
261 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262 write!(f, "{}", self.print_to_string())
263 }
264}