llvm_plugin_inkwell/values/
ptr_value.rs1#[llvm_versions(4.0..=14.0)]
2use llvm_sys::core::{LLVMConstGEP, LLVMConstInBoundsGEP};
3#[llvm_versions(15.0..=latest)]
4use llvm_sys::core::{LLVMConstGEP2, LLVMConstInBoundsGEP2};
5
6use llvm_sys::core::{LLVMConstAddrSpaceCast, LLVMConstPointerCast, LLVMConstPtrToInt};
7use llvm_sys::prelude::LLVMValueRef;
8
9use std::convert::TryFrom;
10use std::ffi::CStr;
11use std::fmt::{self, Display};
12
13use crate::types::{AsTypeRef, BasicType, IntType, PointerType};
14use crate::values::{AsValueRef, InstructionValue, IntValue, Value};
15
16use super::AnyValue;
17
18#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
19pub struct PointerValue<'ctx> {
20 ptr_value: Value<'ctx>,
21}
22
23impl<'ctx> PointerValue<'ctx> {
24 pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
25 assert!(!value.is_null());
26
27 PointerValue {
28 ptr_value: Value::new(value),
29 }
30 }
31
32 pub fn get_name(&self) -> &CStr {
35 self.ptr_value.get_name()
36 }
37
38 pub fn set_name(&self, name: &str) {
40 self.ptr_value.set_name(name)
41 }
42
43 pub fn get_type(self) -> PointerType<'ctx> {
44 unsafe { PointerType::new(self.ptr_value.get_type()) }
45 }
46
47 pub fn is_null(self) -> bool {
48 self.ptr_value.is_null()
49 }
50
51 pub fn is_undef(self) -> bool {
52 self.ptr_value.is_undef()
53 }
54
55 pub fn is_const(self) -> bool {
67 self.ptr_value.is_const()
68 }
69
70 pub fn print_to_stderr(self) {
71 self.ptr_value.print_to_stderr()
72 }
73
74 pub fn as_instruction(self) -> Option<InstructionValue<'ctx>> {
75 self.ptr_value.as_instruction()
76 }
77
78 #[llvm_versions(4.0..=14.0)]
81 pub unsafe fn const_gep(self, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> {
82 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
83
84 let value = {
85 LLVMConstGEP(
86 self.as_value_ref(),
87 index_values.as_mut_ptr(),
88 index_values.len() as u32,
89 )
90 };
91
92 PointerValue::new(value)
93 }
94
95 #[llvm_versions(15.0..=latest)]
98 pub unsafe fn const_gep<T: BasicType<'ctx>>(self, ty: T, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> {
99 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
100
101 let value = {
102 LLVMConstGEP2(
103 ty.as_type_ref(),
104 self.as_value_ref(),
105 index_values.as_mut_ptr(),
106 index_values.len() as u32,
107 )
108 };
109
110 PointerValue::new(value)
111 }
112
113 #[llvm_versions(4.0..=14.0)]
115 pub unsafe fn const_in_bounds_gep(self, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> {
116 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
117
118 let value = {
119 LLVMConstInBoundsGEP(
120 self.as_value_ref(),
121 index_values.as_mut_ptr(),
122 index_values.len() as u32,
123 )
124 };
125
126 PointerValue::new(value)
127 }
128
129 #[llvm_versions(15.0..=latest)]
131 pub unsafe fn const_in_bounds_gep<T: BasicType<'ctx>>(
132 self,
133 ty: T,
134 ordered_indexes: &[IntValue<'ctx>],
135 ) -> PointerValue<'ctx> {
136 let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect();
137
138 let value = {
139 LLVMConstInBoundsGEP2(
140 ty.as_type_ref(),
141 self.as_value_ref(),
142 index_values.as_mut_ptr(),
143 index_values.len() as u32,
144 )
145 };
146
147 PointerValue::new(value)
148 }
149}
150
151impl<'ctx> PointerValue<'ctx> {
152 pub fn const_to_int(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
153 unsafe { IntValue::new(LLVMConstPtrToInt(self.as_value_ref(), int_type.as_type_ref())) }
154 }
155
156 pub fn const_cast(self, ptr_type: PointerType<'ctx>) -> PointerValue<'ctx> {
157 unsafe { PointerValue::new(LLVMConstPointerCast(self.as_value_ref(), ptr_type.as_type_ref())) }
158 }
159
160 pub fn const_address_space_cast(self, ptr_type: PointerType<'ctx>) -> PointerValue<'ctx> {
161 unsafe { PointerValue::new(LLVMConstAddrSpaceCast(self.as_value_ref(), ptr_type.as_type_ref())) }
162 }
163
164 pub fn replace_all_uses_with(self, other: PointerValue<'ctx>) {
165 self.ptr_value.replace_all_uses_with(other.as_value_ref())
166 }
167}
168
169unsafe impl AsValueRef for PointerValue<'_> {
170 fn as_value_ref(&self) -> LLVMValueRef {
171 self.ptr_value.value
172 }
173}
174
175impl Display for PointerValue<'_> {
176 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177 write!(f, "{}", self.print_to_string())
178 }
179}
180
181impl<'ctx> TryFrom<InstructionValue<'ctx>> for PointerValue<'ctx> {
182 type Error = ();
183
184 fn try_from(value: InstructionValue) -> Result<Self, Self::Error> {
185 if value.get_type().is_pointer_type() {
186 unsafe { Ok(PointerValue::new(value.as_value_ref())) }
187 } else {
188 Err(())
189 }
190 }
191}