1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use llvm_sys::core::{LLVMAddIncoming, LLVMCountIncoming, LLVMGetIncomingBlock, LLVMGetIncomingValue};
use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMValueRef};
use std::ffi::CStr;
use crate::basic_block::BasicBlock;
use crate::support::LLVMString;
use crate::values::traits::AsValueRef;
use crate::values::{BasicValue, BasicValueEnum, InstructionValue, Value};
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct PhiValue {
phi_value: Value
}
impl PhiValue {
pub(crate) fn new(value: LLVMValueRef) -> Self {
assert!(!value.is_null());
PhiValue {
phi_value: Value::new(value),
}
}
pub fn add_incoming(&self, incoming: &[(&dyn BasicValue, &BasicBlock)]) {
let (mut values, mut basic_blocks): (Vec<LLVMValueRef>, Vec<LLVMBasicBlockRef>) = {
incoming.iter()
.map(|&(v, bb)| (v.as_value_ref(), bb.basic_block))
.unzip()
};
unsafe {
LLVMAddIncoming(self.as_value_ref(), values.as_mut_ptr(), basic_blocks.as_mut_ptr(), incoming.len() as u32);
}
}
pub fn count_incoming(&self) -> u32 {
unsafe {
LLVMCountIncoming(self.as_value_ref())
}
}
pub fn get_incoming(&self, index: u32) -> Option<(BasicValueEnum, BasicBlock)> {
if index >= self.count_incoming() {
return None;
}
let basic_block = unsafe {
LLVMGetIncomingBlock(self.as_value_ref(), index)
};
let value = unsafe {
LLVMGetIncomingValue(self.as_value_ref(), index)
};
Some((BasicValueEnum::new(value), BasicBlock::new(basic_block).expect("Invalid BasicBlock")))
}
pub fn get_name(&self) -> &CStr {
self.phi_value.get_name()
}
pub fn set_name(&self, name: &str) {
self.phi_value.set_name(name);
}
pub fn is_null(&self) -> bool {
self.phi_value.is_null()
}
pub fn is_undef(&self) -> bool {
self.phi_value.is_undef()
}
pub fn print_to_string(&self) -> LLVMString {
self.phi_value.print_to_string()
}
pub fn print_to_stderr(&self) {
self.phi_value.print_to_stderr()
}
pub fn as_instruction(&self) -> InstructionValue {
self.phi_value.as_instruction().expect("PhiValue should always be a Phi InstructionValue")
}
pub fn replace_all_uses_with(&self, other: &PhiValue) {
self.phi_value.replace_all_uses_with(other.as_value_ref())
}
pub fn as_basic_value(&self) -> BasicValueEnum {
BasicValueEnum::new(self.as_value_ref())
}
}
impl AsValueRef for PhiValue {
fn as_value_ref(&self) -> LLVMValueRef {
self.phi_value.value
}
}