pipeline_script/llvm/value/
pstruct.rs1use 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 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 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}