pipeline_script/llvm/value/
reference.rs

1use crate::context::Context;
2use crate::llvm::global::Global;
3use crate::llvm::types::LLVMType;
4use crate::llvm::value::LLVMValue;
5use llvm_sys::core::LLVMIsUndef;
6use llvm_sys::prelude::LLVMValueRef;
7use std::cell::RefCell;
8use std::rc::Rc;
9
10#[derive(Debug, Clone)]
11pub struct ReferenceValue {
12    reference: LLVMValueRef,
13    element: Rc<RefCell<Box<LLVMValue>>>,
14}
15
16impl ReferenceValue {
17    pub fn new(reference: LLVMValueRef, element: LLVMValue) -> Self {
18        Self {
19            reference,
20            element: Rc::new(RefCell::new(Box::new(element))),
21        }
22    }
23    pub fn get_reference(&self) -> LLVMValueRef {
24        self.reference
25    }
26    pub fn store(&self, ctx: &Context, value: &LLVMValue) {
27        let builder = ctx.get_builder();
28        self.element.replace(Box::new(value.clone()));
29        builder.build_store(self.reference, value);
30    }
31    pub fn get_value(&self, ctx: &Context) -> LLVMValue {
32        let builder = ctx.get_builder();
33        let element_type = self.element.borrow().get_llvm_type(ctx);
34        builder.build_load(element_type, self.reference)
35    }
36    pub fn get_element_type(&self, ctx: &Context) -> LLVMType {
37        self.element.borrow().get_llvm_type(ctx)
38    }
39    pub fn get_llvm_type(&self, ctx: &Context) -> LLVMType {
40        let element_type = self.element.borrow().get_llvm_type(ctx);
41        Global::ref_type(element_type)
42    }
43    pub fn set_reference(&mut self, reference: LLVMValueRef) {
44        self.reference = reference;
45    }
46    pub fn get_struct_field_ptr(&self, ctx: &Context, name: &str) -> Option<LLVMValue> {
47        let element = self.get_value(ctx);
48        if let LLVMValue::Struct(struct_value) = element {
49            if let Some(index) = struct_value.get_field_index(name) {
50                let builder = ctx.get_builder();
51                let field_ptr = builder.build_struct_gep(
52                    &struct_value.get_llvm_type(ctx),
53                    LLVMValue::Reference(self.clone()),
54                    index,
55                );
56                return Some(field_ptr);
57            }
58        }
59        None
60    }
61    // pub fn get_enum_variant_data_ptr(&self, ctx: &Context) -> Option<LLVMValue> {
62    //     let element = self.element.borrow();
63    //     if let LLVMValue::EnumVariant(enum_variant) = &**element {
64    //         // 获取枚举值的引用
65    //         let builder = ctx.get_builder();
66    //         // 获取数据字段的指针(第二个字段,索引为1)
67    //         let element_type =enum_variant.get_llvm_type(ctx);
68    //         dbg!(&element_type);
69    //         let data_ptr = builder.build_struct_gep(
70    //             &element_type,
71    //             LLVMValue::Reference(self.clone()),
72    //             1,
73    //         );
74    //
75    //         dbg!(&data_ptr);
76    //         // todo!();
77    //         return Some(data_ptr);
78    //     }
79    //     None
80    // }
81    pub fn is_undef(&self) -> bool {
82        unsafe { LLVMIsUndef(self.reference) == 1 }
83    }
84}