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