Coverage Report

Created: 2024-10-16 07:58

/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
}