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                let mut sorted_entries: Vec<_> = self.field_index.iter().collect();
50                // 按value降序排序
51                sorted_entries.sort_by(|a, b| a.1.cmp(b.1));
52                for (name, index) in sorted_entries {
53                    field_type.push((
54                        name.clone(),
55                        self.field_values.borrow()[*index].get_llvm_type(ctx),
56                    ));
57                }
58                Global::struct_type(self.name.clone(), field_type)
59            }
60        }
61    }
62    pub fn with_field(&self, reference: LLVMValueRef, index: usize, value: LLVMValue) -> Self {
63        let mut clone = self.clone();
64        clone.reference = reference;
65        clone.field_values.borrow_mut()[index] = value;
66        clone
67    }
68    pub fn insert(&self, ctx: &Context, idx: usize, value: &LLVMValue) -> StructValue {
69        let builder = ctx.get_builder();
70        builder.build_struct_insert(self, idx, value)
71    }
72    pub fn get_name(&self) -> String {
73        self.name.clone()
74    }
75    pub fn get_field_index(&self, name: &str) -> Option<usize> {
76        self.field_index.get(name).cloned()
77    }
78    pub fn get_field_by_index(&self, ctx: &Context, index: usize) -> Option<LLVMValue> {
79        let r = self.field_values.borrow().get(index).cloned();
80        match r {
81            Some(v) => {
82                if v.is_undef() {
83                    let builder = ctx.get_builder();
84                    let new_value = builder.build_struct_get(self, index);
85                    // 更新本地缓存
86                    self.field_values.borrow_mut()[index] = new_value.clone();
87                    Some(new_value)
88                } else {
89                    Some(v)
90                }
91            }
92            None => None,
93        }
94    }
95    pub fn simply_get_field_by_index(&self, index: usize) -> Option<LLVMValue> {
96        self.field_values.borrow().get(index).cloned()
97    }
98    pub fn set_reference(&mut self, reference: LLVMValueRef) {
99        self.reference = reference;
100    }
101    pub fn is_undef(&self) -> bool {
102        unsafe { LLVMIsUndef(self.reference) == 1 }
103    }
104}
105
106impl From<StructValue> for LLVMValue {
107    fn from(value: StructValue) -> Self {
108        Self::Struct(value)
109    }
110}