llvm_plugin_inkwell/values/
struct_value.rs1use either::{
2 Either,
3 Either::{Left, Right},
4};
5use llvm_sys::core::{LLVMGetNumOperands, LLVMGetOperand, LLVMIsABasicBlock, LLVMSetOperand, LLVMValueAsBasicBlock};
6use llvm_sys::prelude::LLVMValueRef;
7
8use std::ffi::CStr;
9use std::fmt::{self, Display};
10
11use crate::basic_block::BasicBlock;
12use crate::types::StructType;
13use crate::values::traits::AsValueRef;
14use crate::values::{BasicValue, BasicValueEnum, InstructionValue, Value};
15
16use super::AnyValue;
17
18#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
19pub struct StructValue<'ctx> {
20 struct_value: Value<'ctx>,
21}
22
23impl<'ctx> StructValue<'ctx> {
24 pub(crate) unsafe fn new(value: LLVMValueRef) -> Self {
25 assert!(!value.is_null());
26
27 StructValue {
28 struct_value: Value::new(value),
29 }
30 }
31
32 pub fn get_name(&self) -> &CStr {
35 self.struct_value.get_name()
36 }
37
38 pub fn set_name(&self, name: &str) {
40 self.struct_value.set_name(name)
41 }
42
43 pub fn get_type(self) -> StructType<'ctx> {
44 unsafe { StructType::new(self.struct_value.get_type()) }
45 }
46
47 pub fn is_null(self) -> bool {
48 self.struct_value.is_null()
49 }
50
51 pub fn is_undef(self) -> bool {
52 self.struct_value.is_undef()
53 }
54
55 pub fn print_to_stderr(self) {
56 self.struct_value.print_to_stderr()
57 }
58
59 pub fn as_instruction(self) -> Option<InstructionValue<'ctx>> {
60 self.struct_value.as_instruction()
61 }
62
63 pub fn get_num_operands(self) -> u32 {
64 unsafe { LLVMGetNumOperands(self.as_value_ref()) as u32 }
65 }
66
67 pub fn set_operand<BV: BasicValue<'ctx>>(self, index: u32, val: BV) -> bool {
68 let num_operands = self.get_num_operands();
69
70 if index >= num_operands {
71 return false;
72 }
73
74 unsafe { LLVMSetOperand(self.as_value_ref(), index, val.as_value_ref()) }
75
76 true
77 }
78
79 pub fn get_operand(self, index: u32) -> Option<Either<BasicValueEnum<'ctx>, BasicBlock<'ctx>>> {
80 let num_operands = self.get_num_operands();
81
82 if index >= num_operands {
83 return None;
84 }
85
86 let operand = unsafe { LLVMGetOperand(self.as_value_ref(), index) };
87
88 if operand.is_null() {
89 return None;
90 }
91
92 let is_basic_block = unsafe { !LLVMIsABasicBlock(operand).is_null() };
93
94 if is_basic_block {
95 let bb = unsafe { BasicBlock::new(LLVMValueAsBasicBlock(operand)) };
96
97 Some(Right(bb.expect("BasicBlock should always be valid")))
98 } else {
99 Some(Left(unsafe { BasicValueEnum::new(operand) }))
100 }
101 }
102
103 pub fn replace_all_uses_with(self, other: StructValue<'ctx>) {
104 self.struct_value.replace_all_uses_with(other.as_value_ref())
105 }
106}
107
108unsafe impl AsValueRef for StructValue<'_> {
109 fn as_value_ref(&self) -> LLVMValueRef {
110 self.struct_value.value
111 }
112}
113
114impl Display for StructValue<'_> {
115 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
116 write!(f, "{}", self.print_to_string())
117 }
118}