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 let mut sorted_entries: Vec<_> = self.field_index.iter().collect();
50 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 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}