pipeline_script/llvm/value/
reference.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::rc::Rc;
9
10#[derive(Debug, Clone)]
11pub struct ReferenceValue {
12 reference: LLVMValueRef,
13 element: Rc<RefCell<Box<LLVMValue>>>,
14}
15
16impl ReferenceValue {
17 pub fn new(reference: LLVMValueRef, element: LLVMValue) -> Self {
18 Self {
19 reference,
20 element: Rc::new(RefCell::new(Box::new(element))),
21 }
22 }
23 pub fn get_reference(&self) -> LLVMValueRef {
24 self.reference
25 }
26 pub fn store(&self, ctx: &Context, value: LLVMValue) {
27 let builder = ctx.get_builder();
28 self.element.replace(Box::new(value.clone()));
29 builder.build_store(self.reference, value);
30 }
31 pub fn get_value(&self, ctx: &Context) -> LLVMValue {
32 let builder = ctx.get_builder();
33 let element_type = self.element.borrow().get_llvm_type(ctx);
34 let load = builder.build_load(element_type, self.reference);
35 load
36 }
37 pub fn get_element_type(&self, ctx: &Context) -> LLVMType {
38 self.element.borrow().get_llvm_type(ctx)
39 }
40 pub fn get_llvm_type(&self, ctx: &Context) -> LLVMType {
41 let element_type = self.element.borrow().get_llvm_type(ctx);
42 Global::ref_type(element_type)
43 }
44 pub fn set_reference(&mut self, reference: LLVMValueRef) {
45 self.reference = reference;
46 }
47 pub fn get_struct_field_ptr(&self, ctx: &Context, name: &str) -> Option<LLVMValue> {
48 let element = self.get_value(ctx);
49 if let LLVMValue::Struct(struct_value) = element {
50 if let Some(index) = struct_value.get_field_index(name) {
51 let builder = ctx.get_builder();
52 let field_ptr = builder.build_struct_gep(
53 &struct_value.get_llvm_type(ctx),
54 LLVMValue::Reference(self.clone()),
55 index,
56 );
57 return Some(field_ptr);
58 }
59 }
60 None
61 }
62 pub fn is_undef(&self) -> bool {
83 unsafe { LLVMIsUndef(self.reference) == 1 }
84 }
85}