inkwell/values/
ptr_value.rs
1#[cfg(all(feature = "typed-pointers", not(feature = "llvm16-0")))]
2#[cfg_attr(feature = "llvm15-0", allow(deprecated))]
3use llvm_sys::core::{LLVMConstGEP, LLVMConstInBoundsGEP};
4#[cfg(any(not(feature = "typed-pointers"), feature = "llvm16-0"))]
5use llvm_sys::core::{LLVMConstGEP2, LLVMConstInBoundsGEP2};
6
7use llvm_sys::core::{LLVMConstAddrSpaceCast, LLVMConstPointerCast, LLVMConstPtrToInt};
8use llvm_sys::prelude::LLVMValueRef;
9
10use std::convert::TryFrom;
11use std::ffi::CStr;
12use std::fmt::{self, Display};
13
14#[cfg(not(feature = "typed-pointers"))]
15use crate::types::BasicType;
16use crate::types::{AsTypeRef, IntType, PointerType};
17use crate::values::{AsValueRef, InstructionValue, IntValue, Value};
18
19use super::AnyValue;
20
21#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
22pub struct PointerValue<'ctx> {
23 ptr_value: Value<'ctx>,
24}
25
26impl<'ctx> PointerValue<'ctx> {
27 pub unsafe fn new(value: LLVMValueRef) -> Self {
33 assert!(!value.is_null());
34
35 PointerValue {
36 ptr_value: Value::new(value),
37 }
38 }
39
40 pub fn get_name(&self) -> &CStr {
43 self.ptr_value.get_name()
44 }
45
46 pub fn set_name(&self, name: &str) {
48 self.ptr_value.set_name(name)
49 }
50
51 pub fn get_type(self) -> PointerType<'ctx> {
52 unsafe { PointerType::new(self.ptr_value.get_type()) }
53 }
54
55 pub fn is_null(self) -> bool {
56 self.ptr_value.is_null()
57 }
58
59 pub fn is_undef(self) -> bool {
60 self.ptr_value.is_undef()
61 }
62
63 pub fn is_const(self) -> bool {
75 self.ptr_value.is_const()
76 }
77
78 pub fn print_to_stderr(self) {
79 self.ptr_value.print_to_stderr()
80 }
81
82 pub fn as_instruction(self) -> Option<InstructionValue<'ctx>> {
83 self.ptr_value.as_instruction()
84 }
85
86 #[cfg(feature = "typed-pointers")]
89 pub unsafe fn const_gep(self, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> {
90 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
91
92 #[cfg(not(feature = "llvm16-0"))]
93 #[cfg_attr(feature = "llvm15-0", allow(deprecated))]
94 let value = {
95 LLVMConstGEP(
96 self.as_value_ref(),
97 index_values.as_mut_ptr(),
98 index_values.len() as u32,
99 )
100 };
101 #[cfg(feature = "llvm16-0")]
102 let value = {
103 LLVMConstGEP2(
104 self.get_type().get_element_type().as_type_ref(),
105 self.as_value_ref(),
106 index_values.as_mut_ptr(),
107 index_values.len() as u32,
108 )
109 };
110
111 PointerValue::new(value)
112 }
113
114 #[cfg(not(feature = "typed-pointers"))]
117 pub unsafe fn const_gep<T: BasicType<'ctx>>(self, ty: T, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> {
118 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
119
120 let value = {
121 LLVMConstGEP2(
122 ty.as_type_ref(),
123 self.as_value_ref(),
124 index_values.as_mut_ptr(),
125 index_values.len() as u32,
126 )
127 };
128
129 PointerValue::new(value)
130 }
131
132 #[cfg(feature = "typed-pointers")]
134 pub unsafe fn const_in_bounds_gep(self, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> {
135 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
136
137 #[cfg(not(feature = "llvm16-0"))]
138 #[cfg_attr(feature = "llvm15-0", allow(deprecated))]
139 let value = {
140 LLVMConstInBoundsGEP(
141 self.as_value_ref(),
142 index_values.as_mut_ptr(),
143 index_values.len() as u32,
144 )
145 };
146 #[cfg(feature = "llvm16-0")]
147 let value = {
148 LLVMConstInBoundsGEP2(
149 self.get_type().get_element_type().as_type_ref(),
150 self.as_value_ref(),
151 index_values.as_mut_ptr(),
152 index_values.len() as u32,
153 )
154 };
155
156 PointerValue::new(value)
157 }
158
159 #[cfg(not(feature = "typed-pointers"))]
161 pub unsafe fn const_in_bounds_gep<T: BasicType<'ctx>>(
162 self,
163 ty: T,
164 ordered_indexes: &[IntValue<'ctx>],
165 ) -> PointerValue<'ctx> {
166 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
167
168 let value = {
169 LLVMConstInBoundsGEP2(
170 ty.as_type_ref(),
171 self.as_value_ref(),
172 index_values.as_mut_ptr(),
173 index_values.len() as u32,
174 )
175 };
176
177 PointerValue::new(value)
178 }
179}
180
181impl<'ctx> PointerValue<'ctx> {
182 pub fn const_to_int(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
183 unsafe { IntValue::new(LLVMConstPtrToInt(self.as_value_ref(), int_type.as_type_ref())) }
184 }
185
186 pub fn const_cast(self, ptr_type: PointerType<'ctx>) -> PointerValue<'ctx> {
187 unsafe { PointerValue::new(LLVMConstPointerCast(self.as_value_ref(), ptr_type.as_type_ref())) }
188 }
189
190 pub fn const_address_space_cast(self, ptr_type: PointerType<'ctx>) -> PointerValue<'ctx> {
191 unsafe { PointerValue::new(LLVMConstAddrSpaceCast(self.as_value_ref(), ptr_type.as_type_ref())) }
192 }
193
194 pub fn replace_all_uses_with(self, other: PointerValue<'ctx>) {
195 self.ptr_value.replace_all_uses_with(other.as_value_ref())
196 }
197}
198
199unsafe impl AsValueRef for PointerValue<'_> {
200 fn as_value_ref(&self) -> LLVMValueRef {
201 self.ptr_value.value
202 }
203}
204
205impl Display for PointerValue<'_> {
206 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207 write!(f, "{}", self.print_to_string())
208 }
209}
210
211impl<'ctx> TryFrom<InstructionValue<'ctx>> for PointerValue<'ctx> {
212 type Error = ();
213
214 fn try_from(value: InstructionValue) -> Result<Self, Self::Error> {
215 if value.get_type().is_pointer_type() {
216 unsafe { Ok(PointerValue::new(value.as_value_ref())) }
217 } else {
218 Err(())
219 }
220 }
221}