pipeline_script/llvm/value/
mod.rs

1pub mod array;
2pub mod bool;
3pub mod double;
4pub mod float;
5pub mod fucntion;
6pub mod int;
7pub mod penum;
8pub mod pointer;
9pub mod pstruct;
10pub mod reference;
11
12use crate::context::Context;
13use crate::llvm::types::LLVMType;
14use crate::llvm::value::array::ArrayValue;
15use crate::llvm::value::bool::BoolValue;
16use crate::llvm::value::double::DoubleValue;
17use crate::llvm::value::float::FloatValue;
18use crate::llvm::value::fucntion::FunctionValue;
19use crate::llvm::value::int::{Int16Value, Int32Value, Int64Value, Int8Value};
20use crate::llvm::value::penum::EnumVariantValue;
21use crate::llvm::value::pointer::PointerValue;
22use crate::llvm::value::pstruct::StructValue;
23use crate::llvm::value::reference::ReferenceValue;
24use llvm_sys::core::{
25    LLVMConstString, LLVMGetIntTypeWidth, LLVMGetTypeKind, LLVMGetUndef, LLVMTypeOf, LLVMVoidType,
26};
27use llvm_sys::prelude::LLVMValueRef;
28use llvm_sys::LLVMTypeKind;
29use std::ffi::{c_uint, CString};
30
31#[derive(Clone, Debug)]
32pub enum LLVMValue {
33    String(LLVMValueRef),
34    Bool(BoolValue),
35    Int8(Int8Value),
36    Int16(Int16Value),
37    Int32(Int32Value),
38    Int64(Int64Value),
39    Float(FloatValue),
40    Double(DoubleValue),
41    Pointer(PointerValue),
42    Array(ArrayValue),
43    Struct(StructValue),
44    // Undef(LLVMValueRef),
45    Function(FunctionValue),
46    Reference(ReferenceValue),
47    EnumVariant(EnumVariantValue),
48    Unit,
49}
50
51impl From<&str> for LLVMValue {
52    fn from(value: &str) -> Self {
53        let str = CString::new(value).unwrap();
54        let c = unsafe { LLVMConstString(str.as_ptr(), value.len() as c_uint, 0) };
55        LLVMValue::String(c)
56    }
57}
58
59impl From<LLVMValueRef> for LLVMValue {
60    fn from(value: LLVMValueRef) -> Self {
61        let ty = unsafe { LLVMTypeOf(value) };
62        let type_kind = unsafe { LLVMGetTypeKind(ty) };
63        match type_kind {
64            LLVMTypeKind::LLVMIntegerTypeKind => {
65                let width = unsafe { LLVMGetIntTypeWidth(ty) };
66                let width = width as i8;
67
68                match width {
69                    1 => LLVMValue::Bool(BoolValue::new(value)),
70                    8 => LLVMValue::Int8(Int8Value::new(value)),
71                    16 => LLVMValue::Int16(Int16Value::new(value)),
72                    32 => LLVMValue::Int32(Int32Value::new(value)),
73                    64 => LLVMValue::Int64(Int64Value::new(value)),
74                    _ => {
75                        todo!()
76                    }
77                }
78            }
79            // LLVMTypeKind::LLVMPointerTypeKind => {
80            //     LLVMValue::Pointer(PointerValue::new(value, LLVMGetUndef(ty)))
81            // }
82            // LLVMTypeKind::LLVMArrayTypeKind => LLVMValue::Array(value),
83            LLVMTypeKind::LLVMDoubleTypeKind => LLVMValue::Double(DoubleValue::new(value)),
84            LLVMTypeKind::LLVMVoidTypeKind => LLVMValue::Unit,
85            // LLVMTypeKind::LLVMStructTypeKind => LLVMValue::Struct(StructValue::new(value, UNNAMED.into(), HashMap::new(), ty)),
86            LLVMTypeKind::LLVMFloatTypeKind => LLVMValue::Float(FloatValue::new(value)),
87            t => {
88                println!("{t:?}");
89                todo!()
90            }
91        }
92    }
93}
94
95impl From<ReferenceValue> for LLVMValue {
96    fn from(value: ReferenceValue) -> Self {
97        LLVMValue::Reference(value)
98    }
99}
100
101impl LLVMValue {
102    pub fn id(&self) -> i32 {
103        match self {
104            LLVMValue::Unit => 0,
105            LLVMValue::Bool(_) => 1,
106            LLVMValue::Int8(_) => 3,
107            LLVMValue::Int16(_) => 5,
108            LLVMValue::Int32(_) => 7,
109            LLVMValue::Int64(_) => 9,
110            LLVMValue::Float(_) => 11,
111            LLVMValue::Double(_) => 13,
112            LLVMValue::String(_) => 15,
113            t => {
114                panic!("Unknown type: {:?}", t)
115            }
116        }
117    }
118    pub fn as_llvm_value_ref(&self) -> LLVMValueRef {
119        unsafe {
120            match self {
121                LLVMValue::String(i) => *i,
122                LLVMValue::Float(i) => i.get_reference(),
123                LLVMValue::Double(i) => i.get_reference(),
124                LLVMValue::Int64(i) => i.get_reference(),
125                LLVMValue::Int32(i) => i.get_reference(),
126                LLVMValue::Int16(i) => i.get_reference(),
127                LLVMValue::Int8(i) => i.get_reference(),
128                LLVMValue::Bool(i) => i.get_reference(),
129                LLVMValue::Pointer(i) => i.get_reference(),
130                LLVMValue::Array(i) => i.get_reference(),
131                LLVMValue::Struct(i) => i.get_reference(),
132                LLVMValue::Reference(i) => i.get_reference(),
133                LLVMValue::Unit => LLVMGetUndef(LLVMVoidType()),
134                LLVMValue::Function(i) => i.get_reference(),
135                LLVMValue::EnumVariant(i) => i.get_reference(),
136            }
137        }
138    }
139    // pub fn as_enum_variant(&self) -> Option<&EnumVariantValue> {
140    //     match self {
141    //         LLVMValue::EnumVariant(v) => Some(v),
142    //         _ => None,
143    //     }
144    // }
145    pub fn as_int32(&self) -> Option<&Int32Value> {
146        match self {
147            LLVMValue::Int32(v) => Some(v),
148            _ => None,
149        }
150    }
151    pub fn as_bool(&self) -> Option<&BoolValue> {
152        match self {
153            LLVMValue::Bool(v) => Some(v),
154            _ => None,
155        }
156    }
157    pub fn is_float(&self) -> bool {
158        matches!(self, LLVMValue::Float(_))
159    }
160    pub fn is_double(&self) -> bool {
161        matches!(self, LLVMValue::Double(_))
162    }
163    pub fn as_float(&self) -> Option<&FloatValue> {
164        match self {
165            LLVMValue::Float(v) => Some(v),
166            _ => None,
167        }
168    }
169    pub fn as_double(&self) -> Option<&DoubleValue> {
170        match self {
171            LLVMValue::Double(v) => Some(v),
172            _ => None,
173        }
174    }
175    pub fn as_reference(&self) -> Option<&ReferenceValue> {
176        match self {
177            LLVMValue::Reference(v) => Some(v),
178            _ => None,
179        }
180    }
181    pub fn as_array(&self) -> Option<&ArrayValue> {
182        match self {
183            LLVMValue::Array(v) => Some(v),
184            _ => None,
185        }
186    }
187    pub fn as_pointer(&self) -> Option<&PointerValue> {
188        match self {
189            LLVMValue::Pointer(v) => Some(v),
190            _ => None,
191        }
192    }
193    pub fn as_struct(&self) -> Option<&StructValue> {
194        match self {
195            LLVMValue::Struct(v) => Some(v),
196            _ => None,
197        }
198    }
199    pub fn as_function(&self) -> Option<FunctionValue> {
200        match self {
201            LLVMValue::Function(v) => Some(v.clone()),
202            _ => None,
203        }
204    }
205    pub fn is_reference(&self) -> bool {
206        matches!(self, LLVMValue::Reference(_))
207    }
208    pub fn is_struct(&self) -> bool {
209        matches!(self, LLVMValue::Struct(_))
210    }
211    pub fn is_pointer(&self) -> bool {
212        matches!(self, LLVMValue::Pointer(_))
213    }
214    pub fn is_function(&self) -> bool {
215        matches!(self, LLVMValue::Function(_))
216    }
217    pub fn is_array(&self) -> bool {
218        matches!(self, LLVMValue::Array(_))
219    }
220    pub fn get_llvm_type(&self, ctx: &Context) -> LLVMType {
221        let ty = unsafe { LLVMTypeOf(self.as_llvm_value_ref()) };
222        match self {
223            LLVMValue::Bool(_) => LLVMType::Int1(ty),
224            LLVMValue::Int8(_) => LLVMType::Int8(ty),
225            LLVMValue::Int16(_) => LLVMType::Int16(ty),
226            LLVMValue::Int32(_) => LLVMType::Int32(ty),
227            LLVMValue::Int64(_) => LLVMType::Int64(ty),
228            LLVMValue::Float(_) => LLVMType::Float(ty),
229            LLVMValue::Double(_) => LLVMType::Double(ty),
230            LLVMValue::Pointer(pointer_value) => pointer_value.get_llvm_type(ctx),
231            LLVMValue::Array(array) => LLVMType::Array(Box::new(array.get_element_type()), ty),
232            LLVMValue::Struct(struct_value) => struct_value.get_llvm_type(ctx),
233            LLVMValue::Unit => LLVMType::Unit(ty),
234            LLVMValue::String(_) => LLVMType::String(ty),
235            LLVMValue::Function(function_value) => function_value.get_llvm_type(ctx),
236            LLVMValue::Reference(reference_value) => reference_value.get_llvm_type(ctx),
237            LLVMValue::EnumVariant(enum_variant_value) => enum_variant_value.get_llvm_type(ctx),
238        }
239    }
240    pub fn is_unit(&self) -> bool {
241        matches!(self, LLVMValue::Unit)
242    }
243    pub fn is_undef(&self) -> bool {
244        match self {
245            LLVMValue::Bool(v) => v.is_undef(),
246            LLVMValue::Int8(v) => v.is_undef(),
247            LLVMValue::Int16(v) => v.is_undef(),
248            LLVMValue::Int32(v) => v.is_undef(),
249            LLVMValue::Int64(v) => v.is_undef(),
250            LLVMValue::Float(v) => v.is_undef(),
251            LLVMValue::Double(v) => v.is_undef(),
252            LLVMValue::Pointer(v) => v.is_undef(),
253            LLVMValue::Reference(v) => v.is_undef(),
254            LLVMValue::Struct(v) => v.is_undef(),
255            LLVMValue::Array(v) => v.is_undef(),
256            LLVMValue::EnumVariant(v) => v.is_undef(),
257            LLVMValue::Function(v) => v.is_undef(),
258            LLVMValue::Unit => false,
259            LLVMValue::String(_) => false,
260        }
261    }
262}