pipeline_script/llvm/value/
pstruct.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::collections::HashMap;
9
10#[derive(Debug, Clone)]
11pub struct StructValue {
12    reference: LLVMValueRef,
13    name: String,
14    pub(crate) field_index: HashMap<String, usize>,
15    // 缓存字段值
16    pub(crate) field_values: RefCell<Vec<LLVMValue>>,
17}
18
19impl StructValue {
20    pub fn new(
21        reference: LLVMValueRef,
22        name: String,
23        field_index: HashMap<String, usize>,
24        field_values: Vec<LLVMValue>,
25    ) -> Self {
26        Self {
27            reference,
28            name,
29            field_index,
30            field_values: RefCell::new(field_values),
31        }
32    }
33    pub fn get_reference(&self) -> LLVMValueRef {
34        self.reference
35    }
36    pub fn get_field(&self, ctx: &Context, name: &str) -> LLVMValue {
37        let index = self.field_index.get(name).unwrap();
38        let builder = ctx.get_builder();
39        builder.build_struct_get(self, *index)
40    }
41    pub fn get_llvm_type(&self, ctx: &Context) -> LLVMType {
42        let llvm_module = ctx.get_llvm_module();
43        let llvm_module = llvm_module.read().unwrap();
44        let ty = llvm_module.get_struct(self.name.clone());
45        match ty {
46            Some((_, t)) => t.clone(),
47            None => {
48                let mut field_type = Vec::new();
49                for (name, index) in &self.field_index {
50                    field_type.push((
51                        name.clone(),
52                        self.field_values.borrow()[*index].get_llvm_type(ctx),
53                    ));
54                }
55                Global::struct_type(self.name.clone(), field_type)
56            }
57        }
58    }
59    pub fn with_field(&self, reference: LLVMValueRef, index: usize, value: LLVMValue) -> Self {
60        let mut clone = self.clone();
61        clone.reference = reference;
62        clone.field_values.borrow_mut()[index] = value;
63        clone
64    }
65    pub fn get_name(&self) -> String {
66        self.name.clone()
67    }
68    pub fn get_field_index(&self, name: &str) -> Option<usize> {
69        self.field_index.get(name).cloned()
70    }
71    pub fn get_field_by_index(&self, ctx: &Context, index: usize) -> Option<LLVMValue> {
72        let r = self.field_values.borrow().get(index).cloned();
73        match r {
74            Some(v) => {
75                if v.is_undef() {
76                    let builder = ctx.get_builder();
77                    let new_value = builder.build_struct_get(self, index);
78                    // 更新本地缓存
79                    self.field_values.borrow_mut()[index] = new_value.clone();
80                    Some(new_value)
81                } else {
82                    Some(v)
83                }
84            }
85            None => None,
86        }
87    }
88    pub fn simply_get_field_by_index(&self, index: usize) -> Option<LLVMValue> {
89        self.field_values.borrow().get(index).cloned()
90    }
91    pub fn set_reference(&mut self, reference: LLVMValueRef) {
92        self.reference = reference;
93    }
94    pub fn is_undef(&self) -> bool {
95        unsafe { LLVMIsUndef(self.reference) == 1 }
96    }
97}
98
99impl From<StructValue> for LLVMValue {
100    fn from(value: StructValue) -> Self {
101        Self::Struct(value)
102    }
103}