Skip to main content

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