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