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}