pipeline_script/llvm/value/
float.rs1use std::ffi::CString;
2use crate::context::Context;
3use crate::llvm::value::bool::BoolValue;
4use crate::llvm::value::LLVMValue;
5use llvm_sys::core::LLVMIsUndef;
6use llvm_sys::prelude::LLVMValueRef;
7use lazy_static::lazy_static;
8
9lazy_static! {
10 static ref EMPTY_NAME: CString = std::ffi::CString::new("").unwrap();
11}
12#[derive(Clone, Debug)]
13pub struct FloatValue {
14 reference: LLVMValueRef,
15}
16
17impl FloatValue {
18 pub fn new(reference: LLVMValueRef) -> Self {
19 Self { reference }
20 }
21 pub fn get_reference(&self) -> LLVMValueRef {
22 self.reference
23 }
24 pub fn is_undef(&self) -> bool {
25 unsafe { LLVMIsUndef(self.reference) == 1 }
26 }
27
28 pub fn eq(&self, ctx: &Context, other: &FloatValue) -> BoolValue {
29 let builder = ctx.get_builder();
30 builder.build_eq(self.reference, other.reference)
31 }
32
33 pub fn add(&self, ctx: &Context, other: &FloatValue) -> FloatValue {
34 let builder = ctx.get_builder();
35 let result = builder.build_fadd(self.clone().into(), other.clone().into());
36 if let LLVMValue::Float(float_val) = result {
37 float_val
38 } else {
39 panic!("Expected FloatValue from fadd operation")
40 }
41 }
42
43 pub fn mul(&self, ctx: &Context, other: &FloatValue) -> FloatValue {
44 let builder = ctx.get_builder();
45 let result = builder.build_fmul(self.clone().into(), other.clone().into());
46 if let LLVMValue::Float(float_val) = result {
47 float_val
48 } else {
49 panic!("Expected FloatValue from fmul operation")
50 }
51 }
52
53 pub fn neg(&self, ctx: &Context) -> FloatValue {
54 let builder = ctx.get_builder();
55 let result = builder.build_fneg(self.clone().into());
56 if let LLVMValue::Float(float_val) = result {
57 float_val
58 } else {
59 panic!("Expected FloatValue from fneg operation")
60 }
61 }
62
63 pub fn less_than(&self, ctx: &Context, other: &FloatValue) -> BoolValue {
64 let builder = ctx.get_builder();
65 let result = unsafe {
66 llvm_sys::core::LLVMBuildFCmp(
67 builder.get_llvm_builder(),
68 llvm_sys::LLVMRealPredicate::LLVMRealOLT,
69 self.reference,
70 other.reference,
71 EMPTY_NAME.as_ptr(),
72 )
73 };
74 BoolValue::new(result)
75 }
76
77 pub fn greater_than(&self, ctx: &Context, other: &FloatValue) -> BoolValue {
78 let builder = ctx.get_builder();
79 let name = std::ffi::CString::new("").unwrap();
80 let result = unsafe {
81 llvm_sys::core::LLVMBuildFCmp(
82 builder.get_llvm_builder(),
83 llvm_sys::LLVMRealPredicate::LLVMRealOGT,
84 self.reference,
85 other.reference,
86 name.as_ptr(),
87 )
88 };
89 BoolValue::new(result)
90 }
91
92 pub fn to_int32(&self, ctx: &Context) -> crate::llvm::value::int::Int32Value {
93 let builder = ctx.get_builder();
94 let name = std::ffi::CString::new("").unwrap();
95 let result = unsafe {
96 llvm_sys::core::LLVMBuildFPToSI(
97 builder.get_llvm_builder(),
98 self.reference,
99 llvm_sys::core::LLVMInt32Type(),
100 name.as_ptr(),
101 )
102 };
103 crate::llvm::value::int::Int32Value::new(result)
104 }
105
106 pub fn to_double(&self, ctx: &Context) -> crate::llvm::value::double::DoubleValue {
107 let builder = ctx.get_builder();
108 let name = std::ffi::CString::new("").unwrap();
109 let result = unsafe {
110 llvm_sys::core::LLVMBuildFPExt(
111 builder.get_llvm_builder(),
112 self.reference,
113 llvm_sys::core::LLVMDoubleType(),
114 name.as_ptr(),
115 )
116 };
117 crate::llvm::value::double::DoubleValue::new(result)
118 }
119}
120
121impl From<FloatValue> for LLVMValue {
122 fn from(value: FloatValue) -> Self {
123 LLVMValue::Float(value)
124 }
125}