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}