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 builder.build_load(element_type, self.reference)
35 }
36 pub fn get_element_type(&self, ctx: &Context) -> LLVMType {
37 self.element.borrow().get_llvm_type(ctx)
38 }
39 pub fn get_llvm_type(&self, ctx: &Context) -> LLVMType {
40 let element_type = self.element.borrow().get_llvm_type(ctx);
41 Global::ref_type(element_type)
42 }
43 pub fn set_reference(&mut self, reference: LLVMValueRef) {
44 self.reference = reference;
45 }
46 pub fn get_struct_field_ptr(&self, ctx: &Context, name: &str) -> Option<LLVMValue> {
47 let element = self.get_value(ctx);
48 if let LLVMValue::Struct(struct_value) = element {
49 if let Some(index) = struct_value.get_field_index(name) {
50 let builder = ctx.get_builder();
51 let field_ptr = builder.build_struct_gep(
52 &struct_value.get_llvm_type(ctx),
53 LLVMValue::Reference(self.clone()),
54 index,
55 );
56 return Some(field_ptr);
57 }
58 }
59 None
60 }
61 pub fn is_undef(&self) -> bool {
82 unsafe { LLVMIsUndef(self.reference) == 1 }
83 }
84}