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        let load = builder.build_load(element_type, self.reference);
35        load
36    }
37    pub fn get_element_type(&self, ctx: &Context) -> LLVMType {
38        self.element.borrow().get_llvm_type(ctx)
39    }
40    pub fn get_llvm_type(&self, ctx: &Context) -> LLVMType {
41        let element_type = self.element.borrow().get_llvm_type(ctx);
42        Global::ref_type(element_type)
43    }
44    pub fn set_reference(&mut self, reference: LLVMValueRef) {
45        self.reference = reference;
46    }
47    pub fn get_struct_field_ptr(&self, ctx: &Context, name: &str) -> Option<LLVMValue> {
48        let element = self.get_value(ctx);
49        if let LLVMValue::Struct(struct_value) = element {
50            if let Some(index) = struct_value.get_field_index(name) {
51                let builder = ctx.get_builder();
52                let field_ptr = builder.build_struct_gep(
53                    &struct_value.get_llvm_type(ctx),
54                    LLVMValue::Reference(self.clone()),
55                    index,
56                );
57                return Some(field_ptr);
58            }
59        }
60        None
61    }
62    // pub fn get_enum_variant_data_ptr(&self, ctx: &Context) -> Option<LLVMValue> {
63    //     let element = self.element.borrow();
64    //     if let LLVMValue::EnumVariant(enum_variant) = &**element {
65    //         // 获取枚举值的引用
66    //         let builder = ctx.get_builder();
67    //         // 获取数据字段的指针(第二个字段,索引为1)
68    //         let element_type =enum_variant.get_llvm_type(ctx);
69    //         dbg!(&element_type);
70    //         let data_ptr = builder.build_struct_gep(
71    //             &element_type,
72    //             LLVMValue::Reference(self.clone()),
73    //             1,
74    //         );
75    //
76    //         dbg!(&data_ptr);
77    //         // todo!();
78    //         return Some(data_ptr);
79    //     }
80    //     None
81    // }
82    pub fn is_undef(&self) -> bool {
83        unsafe { LLVMIsUndef(self.reference) == 1 }
84    }
85}