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