Coverage Report

Created: 2024-10-16 07:58

/rust/registry/src/index.crates.io-6f17d22bba15001f/inkwell-0.1.1/src/values/float_value.rs
Line
Count
Source (jump to first uncovered line)
1
use llvm_sys::core::{
2
    LLVMConstFCmp, LLVMConstFNeg, LLVMConstFPCast, LLVMConstFPExt, LLVMConstFPToSI, LLVMConstFPToUI, LLVMConstFPTrunc,
3
    LLVMConstRealGetDouble,
4
};
5
use llvm_sys::prelude::LLVMValueRef;
6
7
use std::convert::TryFrom;
8
use std::ffi::CStr;
9
use std::fmt::{self, Display};
10
11
use crate::types::{AsTypeRef, FloatType, IntType};
12
use crate::values::traits::AsValueRef;
13
use crate::values::{InstructionValue, IntValue, Value};
14
use crate::FloatPredicate;
15
16
use super::AnyValue;
17
18
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
19
pub struct FloatValue<'ctx> {
20
    float_value: Value<'ctx>,
21
}
22
23
impl<'ctx> FloatValue<'ctx> {
24
4.13M
    pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
25
4.13M
        assert!(!value.is_null());
26
27
4.13M
        FloatValue {
28
4.13M
            float_value: Value::new(value),
29
4.13M
        }
30
4.13M
    }
31
32
    /// Gets name of the `FloatValue`. If the value is a constant, this will
33
    /// return an empty string.
34
0
    pub fn get_name(&self) -> &CStr {
35
0
        self.float_value.get_name()
36
0
    }
37
38
    /// Set name of the `FloatValue`.
39
0
    pub fn set_name(&self, name: &str) {
40
0
        self.float_value.set_name(name)
41
0
    }
42
43
132k
    pub fn get_type(self) -> FloatType<'ctx> {
44
132k
        unsafe { FloatType::new(self.float_value.get_type()) }
45
132k
    }
46
47
0
    pub fn is_null(self) -> bool {
48
0
        self.float_value.is_null()
49
0
    }
50
51
0
    pub fn is_undef(self) -> bool {
52
0
        self.float_value.is_undef()
53
0
    }
54
55
0
    pub fn print_to_stderr(self) {
56
0
        self.float_value.print_to_stderr()
57
0
    }
58
59
0
    pub fn as_instruction(self) -> Option<InstructionValue<'ctx>> {
60
0
        self.float_value.as_instruction()
61
0
    }
62
63
0
    pub fn const_neg(self) -> Self {
64
0
        unsafe { FloatValue::new(LLVMConstFNeg(self.as_value_ref())) }
65
0
    }
66
67
    #[llvm_versions(4.0..=14.0)]
68
    pub fn const_add(self, rhs: FloatValue<'ctx>) -> Self {
69
        use llvm_sys::core::LLVMConstFAdd;
70
71
        unsafe { FloatValue::new(LLVMConstFAdd(self.as_value_ref(), rhs.as_value_ref())) }
72
    }
73
74
    #[llvm_versions(4.0..=14.0)]
75
    pub fn const_sub(self, rhs: FloatValue<'ctx>) -> Self {
76
        use llvm_sys::core::LLVMConstFSub;
77
78
        unsafe { FloatValue::new(LLVMConstFSub(self.as_value_ref(), rhs.as_value_ref())) }
79
    }
80
81
    #[llvm_versions(4.0..=14.0)]
82
    pub fn const_mul(self, rhs: FloatValue<'ctx>) -> Self {
83
        use llvm_sys::core::LLVMConstFMul;
84
85
        unsafe { FloatValue::new(LLVMConstFMul(self.as_value_ref(), rhs.as_value_ref())) }
86
    }
87
88
    #[llvm_versions(4.0..=14.0)]
89
    pub fn const_div(self, rhs: FloatValue<'ctx>) -> Self {
90
        use llvm_sys::core::LLVMConstFDiv;
91
92
        unsafe { FloatValue::new(LLVMConstFDiv(self.as_value_ref(), rhs.as_value_ref())) }
93
    }
94
95
    #[llvm_versions(4.0..=14.0)]
96
    pub fn const_remainder(self, rhs: FloatValue<'ctx>) -> Self {
97
        use llvm_sys::core::LLVMConstFRem;
98
99
        unsafe { FloatValue::new(LLVMConstFRem(self.as_value_ref(), rhs.as_value_ref())) }
100
    }
101
102
0
    pub fn const_cast(self, float_type: FloatType<'ctx>) -> Self {
103
0
        unsafe { FloatValue::new(LLVMConstFPCast(self.as_value_ref(), float_type.as_type_ref())) }
104
0
    }
105
106
0
    pub fn const_to_unsigned_int(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
107
0
        unsafe { IntValue::new(LLVMConstFPToUI(self.as_value_ref(), int_type.as_type_ref())) }
108
0
    }
109
110
0
    pub fn const_to_signed_int(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
111
0
        unsafe { IntValue::new(LLVMConstFPToSI(self.as_value_ref(), int_type.as_type_ref())) }
112
0
    }
113
114
0
    pub fn const_truncate(self, float_type: FloatType<'ctx>) -> FloatValue<'ctx> {
115
0
        unsafe { FloatValue::new(LLVMConstFPTrunc(self.as_value_ref(), float_type.as_type_ref())) }
116
0
    }
117
118
0
    pub fn const_extend(self, float_type: FloatType<'ctx>) -> FloatValue<'ctx> {
119
0
        unsafe { FloatValue::new(LLVMConstFPExt(self.as_value_ref(), float_type.as_type_ref())) }
120
0
    }
121
122
    // SubType: rhs same as lhs; return IntValue<bool>
123
0
    pub fn const_compare(self, op: FloatPredicate, rhs: FloatValue<'ctx>) -> IntValue<'ctx> {
124
0
        unsafe { IntValue::new(LLVMConstFCmp(op.into(), self.as_value_ref(), rhs.as_value_ref())) }
125
0
    }
126
127
    /// Determines whether or not a `FloatValue` is a constant.
128
    ///
129
    /// # Example
130
    ///
131
    /// ```no_run
132
    /// use inkwell::context::Context;
133
    ///
134
    /// let context = Context::create();
135
    /// let f64_type = context.f64_type();
136
    /// let f64_val = f64_type.const_float(1.2);
137
    ///
138
    /// assert!(f64_val.is_const());
139
    /// ```
140
0
    pub fn is_const(self) -> bool {
141
0
        self.float_value.is_const()
142
0
    }
143
144
    /// Obtains a constant `FloatValue`'s value and whether or not it lost info.
145
    ///
146
    /// # Example
147
    ///
148
    /// ```no_run
149
    /// use inkwell::context::Context;
150
    ///
151
    /// let context = Context::create();
152
    /// let f64_type = context.f64_type();
153
    /// let f64_1_2 = f64_type.const_float(1.2);
154
    ///
155
    /// assert_eq!(f64_1_2.get_constant(), Some((1.2, false)));
156
    /// ```
157
0
    pub fn get_constant(self) -> Option<(f64, bool)> {
158
0
        // Nothing bad happens as far as I can tell if we don't check if const
159
0
        // unlike the int versions, but just doing this just in case and for consistency
160
0
        if !self.is_const() {
161
0
            return None;
162
0
        }
163
0
164
0
        let mut lossy = 0;
165
0
        let constant = unsafe { LLVMConstRealGetDouble(self.as_value_ref(), &mut lossy) };
166
0
167
0
        Some((constant, lossy == 1))
168
0
    }
169
170
0
    pub fn replace_all_uses_with(self, other: FloatValue<'ctx>) {
171
0
        self.float_value.replace_all_uses_with(other.as_value_ref())
172
0
    }
173
}
174
175
unsafe impl AsValueRef for FloatValue<'_> {
176
4.16M
    fn as_value_ref(&self) -> LLVMValueRef {
177
4.16M
        self.float_value.value
178
4.16M
    }
<inkwell::values::float_value::FloatValue as inkwell::values::traits::AsValueRef>::as_value_ref
Line
Count
Source
176
2.53M
    fn as_value_ref(&self) -> LLVMValueRef {
177
2.53M
        self.float_value.value
178
2.53M
    }
<inkwell::values::float_value::FloatValue as inkwell::values::traits::AsValueRef>::as_value_ref
Line
Count
Source
176
1.62M
    fn as_value_ref(&self) -> LLVMValueRef {
177
1.62M
        self.float_value.value
178
1.62M
    }
179
}
180
181
impl Display for FloatValue<'_> {
182
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
183
0
        write!(f, "{}", self.print_to_string())
184
0
    }
185
}
186
187
impl<'ctx> TryFrom<InstructionValue<'ctx>> for FloatValue<'ctx> {
188
    type Error = ();
189
190
0
    fn try_from(value: InstructionValue) -> Result<Self, Self::Error> {
191
0
        if value.get_type().is_float_type() {
192
0
            unsafe { Ok(FloatValue::new(value.as_value_ref())) }
193
        } else {
194
0
            Err(())
195
        }
196
0
    }
197
}