inkwell/values/
float_value.rs1#[llvm_versions(..=17)]
2use crate::types::IntType;
3#[llvm_versions(..=18)]
4use llvm_sys::core::LLVMConstFCmp;
5#[llvm_versions(..=15)]
6use llvm_sys::core::LLVMConstFNeg;
7use llvm_sys::core::LLVMConstRealGetDouble;
8#[llvm_versions(..=17)]
9use llvm_sys::core::{LLVMConstFPCast, LLVMConstFPExt, LLVMConstFPToSI, LLVMConstFPToUI, LLVMConstFPTrunc};
10use llvm_sys::prelude::LLVMValueRef;
11
12use std::convert::TryFrom;
13use std::ffi::CStr;
14use std::fmt::{self, Display};
15
16#[llvm_versions(..=17)]
17use crate::types::AsTypeRef;
18use crate::types::FloatType;
19use crate::values::traits::AsValueRef;
20use crate::values::{InstructionValue, Value};
21
22#[llvm_versions(..=18)]
23use crate::{values::IntValue, FloatPredicate};
24
25use super::AnyValue;
26
27#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
28pub struct FloatValue<'ctx> {
29 float_value: Value<'ctx>,
30}
31
32impl<'ctx> FloatValue<'ctx> {
33 pub unsafe fn new(value: LLVMValueRef) -> Self {
39 assert!(!value.is_null());
40
41 FloatValue {
42 float_value: Value::new(value),
43 }
44 }
45
46 pub fn get_name(&self) -> &CStr {
49 self.float_value.get_name()
50 }
51
52 pub fn set_name(&self, name: &str) {
54 self.float_value.set_name(name)
55 }
56
57 pub fn get_type(self) -> FloatType<'ctx> {
58 unsafe { FloatType::new(self.float_value.get_type()) }
59 }
60
61 pub fn is_null(self) -> bool {
62 self.float_value.is_null()
63 }
64
65 pub fn is_undef(self) -> bool {
66 self.float_value.is_undef()
67 }
68
69 pub fn print_to_stderr(self) {
70 self.float_value.print_to_stderr()
71 }
72
73 pub fn as_instruction(self) -> Option<InstructionValue<'ctx>> {
74 self.float_value.as_instruction()
75 }
76
77 #[llvm_versions(..=15)]
78 pub fn const_neg(self) -> Self {
79 unsafe { FloatValue::new(LLVMConstFNeg(self.as_value_ref())) }
80 }
81
82 #[llvm_versions(..=14)]
83 pub fn const_add(self, rhs: FloatValue<'ctx>) -> Self {
84 use llvm_sys::core::LLVMConstFAdd;
85
86 unsafe { FloatValue::new(LLVMConstFAdd(self.as_value_ref(), rhs.as_value_ref())) }
87 }
88
89 #[llvm_versions(..=14)]
90 pub fn const_sub(self, rhs: FloatValue<'ctx>) -> Self {
91 use llvm_sys::core::LLVMConstFSub;
92
93 unsafe { FloatValue::new(LLVMConstFSub(self.as_value_ref(), rhs.as_value_ref())) }
94 }
95
96 #[llvm_versions(..=14)]
97 pub fn const_mul(self, rhs: FloatValue<'ctx>) -> Self {
98 use llvm_sys::core::LLVMConstFMul;
99
100 unsafe { FloatValue::new(LLVMConstFMul(self.as_value_ref(), rhs.as_value_ref())) }
101 }
102
103 #[llvm_versions(..=14)]
104 pub fn const_div(self, rhs: FloatValue<'ctx>) -> Self {
105 use llvm_sys::core::LLVMConstFDiv;
106
107 unsafe { FloatValue::new(LLVMConstFDiv(self.as_value_ref(), rhs.as_value_ref())) }
108 }
109
110 #[llvm_versions(..=14)]
111 pub fn const_remainder(self, rhs: FloatValue<'ctx>) -> Self {
112 use llvm_sys::core::LLVMConstFRem;
113
114 unsafe { FloatValue::new(LLVMConstFRem(self.as_value_ref(), rhs.as_value_ref())) }
115 }
116
117 #[llvm_versions(..=17)]
118 pub fn const_cast(self, float_type: FloatType<'ctx>) -> Self {
119 unsafe { FloatValue::new(LLVMConstFPCast(self.as_value_ref(), float_type.as_type_ref())) }
120 }
121
122 #[llvm_versions(..=17)]
123 pub fn const_to_unsigned_int(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
124 unsafe { IntValue::new(LLVMConstFPToUI(self.as_value_ref(), int_type.as_type_ref())) }
125 }
126
127 #[llvm_versions(..=17)]
128 pub fn const_to_signed_int(self, int_type: IntType<'ctx>) -> IntValue<'ctx> {
129 unsafe { IntValue::new(LLVMConstFPToSI(self.as_value_ref(), int_type.as_type_ref())) }
130 }
131
132 #[llvm_versions(..=17)]
133 pub fn const_truncate(self, float_type: FloatType<'ctx>) -> FloatValue<'ctx> {
134 unsafe { FloatValue::new(LLVMConstFPTrunc(self.as_value_ref(), float_type.as_type_ref())) }
135 }
136
137 #[llvm_versions(..=17)]
138 pub fn const_extend(self, float_type: FloatType<'ctx>) -> FloatValue<'ctx> {
139 unsafe { FloatValue::new(LLVMConstFPExt(self.as_value_ref(), float_type.as_type_ref())) }
140 }
141
142 #[llvm_versions(..=18)]
144 pub fn const_compare(self, op: FloatPredicate, rhs: FloatValue<'ctx>) -> IntValue<'ctx> {
145 unsafe { IntValue::new(LLVMConstFCmp(op.into(), self.as_value_ref(), rhs.as_value_ref())) }
146 }
147
148 pub fn is_const(self) -> bool {
162 self.float_value.is_const()
163 }
164
165 pub fn get_constant(self) -> Option<(f64, bool)> {
179 if !self.is_const() {
182 return None;
183 }
184
185 let mut lossy = 0;
186 let constant = unsafe { LLVMConstRealGetDouble(self.as_value_ref(), &mut lossy) };
187
188 Some((constant, lossy == 1))
189 }
190
191 pub fn replace_all_uses_with(self, other: FloatValue<'ctx>) {
192 self.float_value.replace_all_uses_with(other.as_value_ref())
193 }
194}
195
196unsafe impl AsValueRef for FloatValue<'_> {
197 fn as_value_ref(&self) -> LLVMValueRef {
198 self.float_value.value
199 }
200}
201
202impl Display for FloatValue<'_> {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 write!(f, "{}", self.print_to_string())
205 }
206}
207
208impl<'ctx> TryFrom<InstructionValue<'ctx>> for FloatValue<'ctx> {
209 type Error = ();
210
211 fn try_from(value: InstructionValue) -> Result<Self, Self::Error> {
212 if value.get_type().is_float_type() {
213 unsafe { Ok(FloatValue::new(value.as_value_ref())) }
214 } else {
215 Err(())
216 }
217 }
218}