pipeline_script/llvm/value/
pointer.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;
8
9#[derive(Debug, Clone)]
10pub struct PointerValue {
11    reference: LLVMValueRef,
12    element: RefCell<Box<LLVMValue>>, // 元素值,如果不确定则初始为undef
13}
14impl PointerValue {
15    pub fn new(reference: LLVMValueRef, element: LLVMValue) -> Self {
16        Self {
17            reference,
18            element: RefCell::new(Box::new(element)),
19        }
20    }
21    pub fn get_reference(&self) -> LLVMValueRef {
22        self.reference
23    }
24    pub fn get_element(&self, ctx: &Context) -> LLVMValue {
25        if self.element.borrow().is_undef() {
26            let builder = ctx.get_builder();
27            let element_type = self.element.borrow().get_llvm_type(ctx);
28            let element = builder.build_load(element_type, self.reference);
29            self.element.replace(Box::new(element));
30        }
31        *self.element.borrow().clone()
32    }
33    pub fn get_element_type(&self, ctx: &Context) -> LLVMType {
34        self.element.borrow().get_llvm_type(ctx)
35    }
36    pub fn get_llvm_type(&self, ctx: &Context) -> LLVMType {
37        let element_type = self.element.borrow().get_llvm_type(ctx);
38        Global::pointer_type(element_type)
39    }
40    pub fn set_reference(&mut self, reference: LLVMValueRef) {
41        self.reference = reference;
42    }
43    pub fn get_struct_field_ptr(&self, ctx: &Context, name: &str) -> Option<LLVMValue> {
44        let element = self.element.borrow();
45        if let LLVMValue::Struct(struct_value) = &**element {
46            if let Some(index) = struct_value.get_field_index(name) {
47                let builder = ctx.get_builder();
48                let field_ptr = builder.build_struct_gep(
49                    &struct_value.get_llvm_type(ctx),
50                    LLVMValue::Pointer(self.clone()),
51                    index,
52                );
53                return Some(field_ptr);
54            }
55        }
56        None
57    }
58    pub fn is_undef(&self) -> bool {
59        unsafe { LLVMIsUndef(self.reference) == 1 }
60    }
61}
62
63impl From<PointerValue> for LLVMValue {
64    fn from(value: PointerValue) -> Self {
65        LLVMValue::Pointer(value)
66    }
67}