/rust/registry/src/index.crates.io-6f17d22bba15001f/inkwell-0.1.1/src/values/ptr_value.rs
Line | Count | Source (jump to first uncovered line) |
1 | | #[llvm_versions(4.0..=14.0)] |
2 | | use llvm_sys::core::{LLVMConstGEP, LLVMConstInBoundsGEP}; |
3 | | #[llvm_versions(15.0..=latest)] |
4 | | use llvm_sys::core::{LLVMConstGEP2, LLVMConstInBoundsGEP2}; |
5 | | |
6 | | use llvm_sys::core::{LLVMConstAddrSpaceCast, LLVMConstPointerCast, LLVMConstPtrToInt}; |
7 | | use llvm_sys::prelude::LLVMValueRef; |
8 | | |
9 | | use std::convert::TryFrom; |
10 | | use std::ffi::CStr; |
11 | | use std::fmt::{self, Display}; |
12 | | |
13 | | use crate::types::{AsTypeRef, BasicType, IntType, PointerType}; |
14 | | use crate::values::{AsValueRef, InstructionValue, IntValue, Value}; |
15 | | |
16 | | use super::AnyValue; |
17 | | |
18 | | #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] |
19 | | pub struct PointerValue<'ctx> { |
20 | | ptr_value: Value<'ctx>, |
21 | | } |
22 | | |
23 | | impl<'ctx> PointerValue<'ctx> { |
24 | 6.49M | pub(crate) unsafe fn new(value: LLVMValueRef) -> Self { |
25 | 6.49M | assert!(!value.is_null()); |
26 | | |
27 | 6.49M | PointerValue { |
28 | 6.49M | ptr_value: Value::new(value), |
29 | 6.49M | } |
30 | 6.49M | } |
31 | | |
32 | | /// Get name of the `PointerValue`. If the value is a constant, this |
33 | | /// will return an empty string. |
34 | 0 | pub fn get_name(&self) -> &CStr { |
35 | 0 | self.ptr_value.get_name() |
36 | 0 | } |
37 | | |
38 | | /// Set name of the `PointerValue`. |
39 | 0 | pub fn set_name(&self, name: &str) { |
40 | 0 | self.ptr_value.set_name(name) |
41 | 0 | } |
42 | | |
43 | 0 | pub fn get_type(self) -> PointerType<'ctx> { |
44 | 0 | unsafe { PointerType::new(self.ptr_value.get_type()) } |
45 | 0 | } |
46 | | |
47 | 0 | pub fn is_null(self) -> bool { |
48 | 0 | self.ptr_value.is_null() |
49 | 0 | } |
50 | | |
51 | 0 | pub fn is_undef(self) -> bool { |
52 | 0 | self.ptr_value.is_undef() |
53 | 0 | } |
54 | | |
55 | | /// Determines whether or not a `PointerValue` is a constant. |
56 | | /// |
57 | | /// # Example |
58 | | /// |
59 | | /// ```no_run |
60 | | /// use inkwell::AddressSpace; |
61 | | /// use inkwell::context::Context; |
62 | | /// |
63 | | /// let context = Context::create(); |
64 | | /// let void_type = context.void_type(); |
65 | | /// ``` |
66 | 0 | pub fn is_const(self) -> bool { |
67 | 0 | self.ptr_value.is_const() |
68 | 0 | } |
69 | | |
70 | 0 | pub fn print_to_stderr(self) { |
71 | 0 | self.ptr_value.print_to_stderr() |
72 | 0 | } |
73 | | |
74 | 0 | pub fn as_instruction(self) -> Option<InstructionValue<'ctx>> { |
75 | 0 | self.ptr_value.as_instruction() |
76 | 0 | } |
77 | | |
78 | | // REVIEW: Should this be on array value too? |
79 | | /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. |
80 | | #[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 | | // REVIEW: Should this be on array value too? |
96 | | /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. |
97 | | #[llvm_versions(15.0..=latest)] |
98 | 0 | pub unsafe fn const_gep<T: BasicType<'ctx>>(self, ty: T, ordered_indexes: &[IntValue<'ctx>]) -> PointerValue<'ctx> { |
99 | 0 | let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); |
100 | 0 |
|
101 | 0 | let value = { |
102 | 0 | LLVMConstGEP2( |
103 | 0 | ty.as_type_ref(), |
104 | 0 | self.as_value_ref(), |
105 | 0 | index_values.as_mut_ptr(), |
106 | 0 | index_values.len() as u32, |
107 | 0 | ) |
108 | 0 | }; |
109 | 0 |
|
110 | 0 | PointerValue::new(value) |
111 | 0 | } |
112 | | |
113 | | /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. |
114 | | #[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 | | /// GEP is very likely to segfault if indexes are used incorrectly, and is therefore an unsafe function. Maybe we can change this in the future. |
130 | | #[llvm_versions(15.0..=latest)] |
131 | 0 | pub unsafe fn const_in_bounds_gep<T: BasicType<'ctx>>( |
132 | 0 | self, |
133 | 0 | ty: T, |
134 | 0 | ordered_indexes: &[IntValue<'ctx>], |
135 | 0 | ) -> PointerValue<'ctx> { |
136 | 0 | let mut index_values: Vec<LLVMValueRef> = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); |
137 | 0 |
|
138 | 0 | let value = { |
139 | 0 | LLVMConstInBoundsGEP2( |
140 | 0 | ty.as_type_ref(), |
141 | 0 | self.as_value_ref(), |
142 | 0 | index_values.as_mut_ptr(), |
143 | 0 | index_values.len() as u32, |
144 | 0 | ) |
145 | 0 | }; |
146 | 0 |
|
147 | 0 | PointerValue::new(value) |
148 | 0 | } |
149 | | } |
150 | | |
151 | | impl<'ctx> PointerValue<'ctx> { |
152 | 0 | pub fn const_to_int(self, int_type: IntType<'ctx>) -> IntValue<'ctx> { |
153 | 0 | unsafe { IntValue::new(LLVMConstPtrToInt(self.as_value_ref(), int_type.as_type_ref())) } |
154 | 0 | } |
155 | | |
156 | 0 | pub fn const_cast(self, ptr_type: PointerType<'ctx>) -> PointerValue<'ctx> { |
157 | 0 | unsafe { PointerValue::new(LLVMConstPointerCast(self.as_value_ref(), ptr_type.as_type_ref())) } |
158 | 0 | } |
159 | | |
160 | 0 | pub fn const_address_space_cast(self, ptr_type: PointerType<'ctx>) -> PointerValue<'ctx> { |
161 | 0 | unsafe { PointerValue::new(LLVMConstAddrSpaceCast(self.as_value_ref(), ptr_type.as_type_ref())) } |
162 | 0 | } |
163 | | |
164 | 0 | pub fn replace_all_uses_with(self, other: PointerValue<'ctx>) { |
165 | 0 | self.ptr_value.replace_all_uses_with(other.as_value_ref()) |
166 | 0 | } |
167 | | } |
168 | | |
169 | | unsafe impl AsValueRef for PointerValue<'_> { |
170 | 7.17M | fn as_value_ref(&self) -> LLVMValueRef { |
171 | 7.17M | self.ptr_value.value |
172 | 7.17M | } <inkwell::values::ptr_value::PointerValue as inkwell::values::traits::AsValueRef>::as_value_ref Line | Count | Source | 170 | 6.75M | fn as_value_ref(&self) -> LLVMValueRef { | 171 | 6.75M | self.ptr_value.value | 172 | 6.75M | } |
<inkwell::values::ptr_value::PointerValue as inkwell::values::traits::AsValueRef>::as_value_ref Line | Count | Source | 170 | 419k | fn as_value_ref(&self) -> LLVMValueRef { | 171 | 419k | self.ptr_value.value | 172 | 419k | } |
|
173 | | } |
174 | | |
175 | | impl Display for PointerValue<'_> { |
176 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
177 | 0 | write!(f, "{}", self.print_to_string()) |
178 | 0 | } |
179 | | } |
180 | | |
181 | | impl<'ctx> TryFrom<InstructionValue<'ctx>> for PointerValue<'ctx> { |
182 | | type Error = (); |
183 | | |
184 | 0 | fn try_from(value: InstructionValue) -> Result<Self, Self::Error> { |
185 | 0 | if value.get_type().is_pointer_type() { |
186 | 0 | unsafe { Ok(PointerValue::new(value.as_value_ref())) } |
187 | | } else { |
188 | 0 | Err(()) |
189 | | } |
190 | 0 | } |
191 | | } |