Skip to main content

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}