pipeline_script/llvm/value/
float.rs

1use 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}