inkwell/types/
ptr_type.rs

1use llvm_sys::core::LLVMGetPointerAddressSpace;
2#[llvm_versions(15..)]
3use llvm_sys::core::LLVMPointerTypeIsOpaque;
4use llvm_sys::prelude::LLVMTypeRef;
5
6use crate::context::ContextRef;
7use crate::support::LLVMString;
8use crate::types::traits::AsTypeRef;
9#[cfg(feature = "typed-pointers")]
10use crate::types::AnyTypeEnum;
11use crate::types::{ArrayType, FunctionType, ScalableVectorType, Type, VectorType};
12use crate::values::{ArrayValue, IntValue, PointerValue};
13use crate::AddressSpace;
14
15use crate::types::enums::BasicMetadataTypeEnum;
16use std::fmt::{self, Display};
17
18/// A `PointerType` is the type of a pointer constant or variable.
19#[derive(Debug, PartialEq, Eq, Clone, Copy)]
20pub struct PointerType<'ctx> {
21    ptr_type: Type<'ctx>,
22}
23
24impl<'ctx> PointerType<'ctx> {
25    /// Create `PointerType` from [`LLVMTypeRef`]
26    ///
27    /// # Safety
28    /// Undefined behavior, if referenced type isn't pointer type
29    pub unsafe fn new(ptr_type: LLVMTypeRef) -> Self {
30        assert!(!ptr_type.is_null());
31
32        PointerType {
33            ptr_type: Type::new(ptr_type),
34        }
35    }
36
37    /// Gets the size of this `PointerType`. Value may vary depending on the target architecture.
38    ///
39    /// # Example
40    ///
41    /// ```no_run
42    /// use inkwell::context::Context;
43    /// use inkwell::AddressSpace;
44    ///
45    /// let context = Context::create();
46    /// let f32_type = context.f32_type();
47    /// #[cfg(feature = "typed-pointers")]
48    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
49    /// #[cfg(not(feature = "typed-pointers"))]
50    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
51    /// let f32_ptr_type_size = f32_ptr_type.size_of();
52    /// ```
53    pub fn size_of(self) -> IntValue<'ctx> {
54        self.ptr_type.size_of().unwrap()
55    }
56
57    /// Gets the alignment of this `PointerType`. Value may vary depending on the target architecture.
58    ///
59    /// # Example
60    ///
61    /// ```no_run
62    /// use inkwell::context::Context;
63    /// use inkwell::AddressSpace;
64    ///
65    /// let context = Context::create();
66    /// let f32_type = context.f32_type();
67    /// #[cfg(feature = "typed-pointers")]
68    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
69    /// #[cfg(not(feature = "typed-pointers"))]
70    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
71    /// let f32_ptr_type_alignment = f32_ptr_type.get_alignment();
72    /// ```
73    pub fn get_alignment(self) -> IntValue<'ctx> {
74        self.ptr_type.get_alignment()
75    }
76
77    /// Creates a `PointerType` with this `PointerType` for its element type.
78    ///
79    /// # Example
80    ///
81    /// ```no_run
82    /// use inkwell::context::Context;
83    /// use inkwell::AddressSpace;
84    ///
85    /// let context = Context::create();
86    /// let f32_type = context.f32_type();
87    /// #[cfg(feature = "typed-pointers")]
88    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
89    /// #[cfg(not(feature = "typed-pointers"))]
90    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
91    /// let f32_ptr_ptr_type = f32_ptr_type.ptr_type(AddressSpace::default());
92    ///
93    /// #[cfg(feature = "typed-pointers")]
94    /// assert_eq!(f32_ptr_ptr_type.get_element_type().into_pointer_type(), f32_ptr_type);
95    /// ```
96    #[cfg_attr(
97        any(
98            all(feature = "llvm15-0", not(feature = "typed-pointers")),
99            all(feature = "llvm16-0", not(feature = "typed-pointers")),
100            feature = "llvm17-0",
101            feature = "llvm18-0"
102        ),
103        deprecated(
104            note = "Starting from version 15.0, LLVM doesn't differentiate between pointer types. Use Context::ptr_type instead."
105        )
106    )]
107    pub fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
108        self.ptr_type.ptr_type(address_space)
109    }
110
111    /// Gets a reference to the `Context` this `PointerType` was created in.
112    ///
113    /// # Example
114    ///
115    /// ```no_run
116    /// use inkwell::context::Context;
117    /// use inkwell::AddressSpace;
118    ///
119    /// let context = Context::create();
120    /// let f32_type = context.f32_type();
121    /// #[cfg(feature = "typed-pointers")]
122    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
123    /// #[cfg(not(feature = "typed-pointers"))]
124    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
125    ///
126    /// assert_eq!(f32_ptr_type.get_context(), context);
127    /// ```
128    // TODO: Move to AnyType trait
129    pub fn get_context(self) -> ContextRef<'ctx> {
130        self.ptr_type.get_context()
131    }
132
133    /// Creates a `FunctionType` with this `PointerType` for its return type.
134    ///
135    /// # Example
136    ///
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    /// #[cfg(feature = "typed-pointers")]
144    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
145    /// #[cfg(not(feature = "typed-pointers"))]
146    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
147    /// let fn_type = f32_ptr_type.fn_type(&[], false);
148    /// ```
149    pub fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> {
150        self.ptr_type.fn_type(param_types, is_var_args)
151    }
152
153    /// Creates an `ArrayType` with this `PointerType` for its element type.
154    ///
155    /// # Example
156    ///
157    /// ```no_run
158    /// use inkwell::context::Context;
159    /// use inkwell::AddressSpace;
160    ///
161    /// let context = Context::create();
162    /// let f32_type = context.f32_type();
163    /// #[cfg(feature = "typed-pointers")]
164    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
165    /// #[cfg(not(feature = "typed-pointers"))]
166    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
167    /// let f32_ptr_array_type = f32_ptr_type.array_type(3);
168    ///
169    /// assert_eq!(f32_ptr_array_type.len(), 3);
170    /// assert_eq!(f32_ptr_array_type.get_element_type().into_pointer_type(), f32_ptr_type);
171    /// ```
172    pub fn array_type(self, size: u32) -> ArrayType<'ctx> {
173        self.ptr_type.array_type(size)
174    }
175
176    /// Gets the `AddressSpace` a `PointerType` was created with.
177    ///
178    /// # Example
179    ///
180    /// ```no_run
181    /// use inkwell::context::Context;
182    /// use inkwell::AddressSpace;
183    ///
184    /// let context = Context::create();
185    /// let f32_type = context.f32_type();
186    /// #[cfg(feature = "typed-pointers")]
187    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
188    /// #[cfg(not(feature = "typed-pointers"))]
189    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
190    ///
191    /// assert_eq!(f32_ptr_type.get_address_space(), AddressSpace::default());
192    /// ```
193    pub fn get_address_space(self) -> AddressSpace {
194        let addr_space = unsafe { LLVMGetPointerAddressSpace(self.as_type_ref()) };
195
196        AddressSpace(addr_space)
197    }
198
199    /// Print the definition of a `PointerType` to `LLVMString`.
200    pub fn print_to_string(self) -> LLVMString {
201        self.ptr_type.print_to_string()
202    }
203
204    /// Creates a null `PointerValue` of this `PointerType`.
205    /// It will be automatically assigned this `PointerType`'s `Context`.
206    ///
207    /// # Example
208    /// ```no_run
209    /// use inkwell::AddressSpace;
210    /// use inkwell::context::Context;
211    ///
212    /// // Local Context
213    /// let context = Context::create();
214    /// let f32_type = context.f32_type();
215    /// #[cfg(feature = "typed-pointers")]
216    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
217    /// #[cfg(not(feature = "typed-pointers"))]
218    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
219    /// let f32_ptr_null = f32_ptr_type.const_null();
220    ///
221    /// assert!(f32_ptr_null.is_null());
222    /// ```
223    pub fn const_null(self) -> PointerValue<'ctx> {
224        unsafe { PointerValue::new(self.ptr_type.const_zero()) }
225    }
226
227    // REVIEW: Unlike the other const_zero functions, this one becomes null instead of a 0 value. Maybe remove?
228    /// Creates a constant null value of this `PointerType`.
229    /// This is practically the same as calling `const_null` for this particular type and
230    /// so this function may be removed in the future.
231    ///
232    /// # Example
233    ///
234    /// ```no_run
235    /// use inkwell::AddressSpace;
236    /// use inkwell::context::Context;
237    ///
238    /// let context = Context::create();
239    /// let f32_type = context.f32_type();
240    /// #[cfg(feature = "typed-pointers")]
241    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
242    /// #[cfg(not(feature = "typed-pointers"))]
243    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
244    /// let f32_ptr_zero = f32_ptr_type.const_zero();
245    /// ```
246    pub fn const_zero(self) -> PointerValue<'ctx> {
247        unsafe { PointerValue::new(self.ptr_type.const_zero()) }
248    }
249
250    /// Creates an undefined instance of a `PointerType`.
251    ///
252    /// # Example
253    /// ```no_run
254    /// use inkwell::context::Context;
255    /// use inkwell::AddressSpace;
256    ///
257    /// let context = Context::create();
258    /// let f32_type = context.f32_type();
259    /// #[cfg(feature = "typed-pointers")]
260    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
261    /// #[cfg(not(feature = "typed-pointers"))]
262    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
263    /// let f32_ptr_undef = f32_ptr_type.get_undef();
264    ///
265    /// assert!(f32_ptr_undef.is_undef());
266    /// ```
267    pub fn get_undef(self) -> PointerValue<'ctx> {
268        unsafe { PointerValue::new(self.ptr_type.get_undef()) }
269    }
270
271    /// Creates a poison instance of a `PointerType`.
272    ///
273    /// # Example
274    /// ```no_run
275    /// use inkwell::context::Context;
276    /// use inkwell::AddressSpace;
277    /// use inkwell::values::AnyValue;
278    ///
279    /// let context = Context::create();
280    /// let f32_type = context.f32_type();
281    /// #[cfg(feature = "typed-pointers")]
282    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
283    /// #[cfg(not(feature = "typed-pointers"))]
284    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
285    /// let f32_ptr_undef = f32_ptr_type.get_poison();
286    ///
287    /// assert!(f32_ptr_undef.is_poison());
288    /// ```
289    #[llvm_versions(12..)]
290    pub fn get_poison(self) -> PointerValue<'ctx> {
291        unsafe { PointerValue::new(self.ptr_type.get_poison()) }
292    }
293
294    /// Creates a `VectorType` with this `PointerType` for its element type.
295    ///
296    /// # Example
297    ///
298    /// ```no_run
299    /// use inkwell::context::Context;
300    /// use inkwell::AddressSpace;
301    ///
302    /// let context = Context::create();
303    /// let f32_type = context.f32_type();
304    /// #[cfg(feature = "typed-pointers")]
305    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
306    /// #[cfg(not(feature = "typed-pointers"))]
307    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
308    /// let f32_ptr_vec_type = f32_ptr_type.vec_type(3);
309    ///
310    /// assert_eq!(f32_ptr_vec_type.get_size(), 3);
311    /// assert_eq!(f32_ptr_vec_type.get_element_type().into_pointer_type(), f32_ptr_type);
312    /// ```
313    pub fn vec_type(self, size: u32) -> VectorType<'ctx> {
314        self.ptr_type.vec_type(size)
315    }
316
317    /// Creates a `ScalableVectorType` with this `PointerType` for its element type.
318    ///
319    /// # Example
320    ///
321    /// ```no_run
322    /// use inkwell::context::Context;
323    /// use inkwell::AddressSpace;
324    ///
325    /// let context = Context::create();
326    /// let f32_type = context.f32_type();
327    /// #[cfg(feature = "typed-pointers")]
328    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
329    /// #[cfg(not(feature = "typed-pointers"))]
330    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
331    /// let f32_ptr_scalable_vec_type = f32_ptr_type.scalable_vec_type(3);
332    ///
333    /// assert_eq!(f32_ptr_scalable_vec_type.get_size(), 3);
334    /// assert_eq!(f32_ptr_scalable_vec_type.get_element_type().into_pointer_type(), f32_ptr_type);
335    /// ```
336    #[llvm_versions(12..)]
337    pub fn scalable_vec_type(self, size: u32) -> ScalableVectorType<'ctx> {
338        self.ptr_type.scalable_vec_type(size)
339    }
340
341    // SubType: PointerrType<BT> -> BT?
342    /// Gets the element type of this `PointerType`.
343    ///
344    /// # Example
345    ///
346    /// ```no_run
347    /// use inkwell::context::Context;
348    /// use inkwell::AddressSpace;
349    ///
350    /// let context = Context::create();
351    /// let f32_type = context.f32_type();
352    /// #[cfg(feature = "typed-pointers")]
353    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
354    /// #[cfg(not(feature = "typed-pointers"))]
355    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
356    ///
357    /// assert_eq!(f32_ptr_type.get_element_type().into_float_type(), f32_type);
358    /// ```
359    #[llvm_versions(..=16)]
360    #[cfg(feature = "typed-pointers")]
361    pub fn get_element_type(self) -> AnyTypeEnum<'ctx> {
362        self.ptr_type.get_element_type()
363    }
364
365    /// Creates a constant `ArrayValue`.
366    ///
367    /// # Example
368    /// ```no_run
369    /// use inkwell::context::Context;
370    /// use inkwell::AddressSpace;
371    ///
372    /// let context = Context::create();
373    /// let f32_type = context.f32_type();
374    /// #[cfg(feature = "typed-pointers")]
375    /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::default());
376    /// #[cfg(not(feature = "typed-pointers"))]
377    /// let f32_ptr_type = context.ptr_type(AddressSpace::default());
378    /// let f32_ptr_val = f32_ptr_type.const_null();
379    /// let f32_ptr_array = f32_ptr_type.const_array(&[f32_ptr_val, f32_ptr_val]);
380    ///
381    /// assert!(f32_ptr_array.is_const());
382    /// ```
383    pub fn const_array(self, values: &[PointerValue<'ctx>]) -> ArrayValue<'ctx> {
384        unsafe { ArrayValue::new_const_array(&self, values) }
385    }
386
387    /// Determine whether this pointer is opaque.
388    #[llvm_versions(15..)]
389    pub fn is_opaque(self) -> bool {
390        unsafe { LLVMPointerTypeIsOpaque(self.ptr_type.ty) != 0 }
391    }
392}
393
394unsafe impl AsTypeRef for PointerType<'_> {
395    fn as_type_ref(&self) -> LLVMTypeRef {
396        self.ptr_type.ty
397    }
398}
399
400impl Display for PointerType<'_> {
401    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402        write!(f, "{}", self.print_to_string())
403    }
404}