Skip to main content

inkwell/values/
vec_value.rs

1#[llvm_versions(..=16)]
2use llvm_sys::core::LLVMConstSelect;
3#[allow(deprecated)]
4use llvm_sys::core::LLVMGetElementAsConstant;
5use llvm_sys::core::{
6    LLVMConstExtractElement, LLVMConstInsertElement, LLVMConstShuffleVector, LLVMIsAConstantDataVector,
7    LLVMIsAConstantVector,
8};
9use llvm_sys::prelude::LLVMValueRef;
10
11use std::ffi::CStr;
12use std::fmt::{self, Display};
13
14use crate::types::VectorType;
15use crate::values::traits::AsValueRef;
16use crate::values::{BasicValue, BasicValueEnum, InstructionValue, IntValue, Value};
17
18use super::AnyValue;
19
20#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
21pub struct VectorValue<'ctx> {
22    vec_value: Value<'ctx>,
23}
24
25impl<'ctx> VectorValue<'ctx> {
26    /// Get a value from an [LLVMValueRef].
27    ///
28    /// # Safety
29    ///
30    /// The ref must be valid and of type vector.
31    pub unsafe fn new(vector_value: LLVMValueRef) -> Self {
32        assert!(!vector_value.is_null());
33
34        VectorValue {
35            vec_value: Value::new(vector_value),
36        }
37    }
38
39    /// Determines whether or not a `VectorValue` is a constant.
40    ///
41    /// # Example
42    ///
43    /// ```no_run
44    /// use inkwell::context::Context;
45    ///
46    /// let context = Context::create();
47    /// let i8_type = context.i8_type();
48    /// let i8_vec_type = i8_type.vec_type(3);
49    /// let i8_vec_zero = i8_vec_type.const_zero();
50    ///
51    /// assert!(i8_vec_zero.is_const());
52    /// ```
53    pub fn is_const(self) -> bool {
54        self.vec_value.is_const()
55    }
56
57    pub fn is_constant_vector(self) -> bool {
58        unsafe { !LLVMIsAConstantVector(self.as_value_ref()).is_null() }
59    }
60
61    pub fn is_constant_data_vector(self) -> bool {
62        unsafe { !LLVMIsAConstantDataVector(self.as_value_ref()).is_null() }
63    }
64
65    pub fn print_to_stderr(self) {
66        self.vec_value.print_to_stderr()
67    }
68
69    /// Gets the name of a `VectorValue`. If the value is a constant, this will
70    /// return an empty string.
71    pub fn get_name(&self) -> &CStr {
72        self.vec_value.get_name()
73    }
74
75    /// Set name of the `VectorValue`.
76    pub fn set_name(&self, name: &str) {
77        self.vec_value.set_name(name)
78    }
79
80    pub fn get_type(self) -> VectorType<'ctx> {
81        unsafe { VectorType::new(self.vec_value.get_type()) }
82    }
83
84    pub fn is_null(self) -> bool {
85        self.vec_value.is_null()
86    }
87
88    pub fn is_undef(self) -> bool {
89        self.vec_value.is_undef()
90    }
91
92    pub fn as_instruction(self) -> Option<InstructionValue<'ctx>> {
93        self.vec_value.as_instruction()
94    }
95
96    pub fn const_extract_element(self, index: IntValue<'ctx>) -> BasicValueEnum<'ctx> {
97        unsafe { BasicValueEnum::new(LLVMConstExtractElement(self.as_value_ref(), index.as_value_ref())) }
98    }
99
100    // SubTypes: value should really be T in self: VectorValue<T> I think
101    pub fn const_insert_element<BV: BasicValue<'ctx>>(self, index: IntValue<'ctx>, value: BV) -> BasicValueEnum<'ctx> {
102        unsafe {
103            BasicValueEnum::new(LLVMConstInsertElement(
104                self.as_value_ref(),
105                value.as_value_ref(),
106                index.as_value_ref(),
107            ))
108        }
109    }
110
111    pub fn replace_all_uses_with(self, other: VectorValue<'ctx>) {
112        self.vec_value.replace_all_uses_with(other.as_value_ref())
113    }
114
115    // TODOC: Value seems to be zero initialized if index out of bounds
116    // SubType: VectorValue<BV> -> BV
117    #[allow(deprecated)]
118    pub fn get_element_as_constant(self, index: u32) -> BasicValueEnum<'ctx> {
119        unsafe { BasicValueEnum::new(LLVMGetElementAsConstant(self.as_value_ref(), index)) }
120    }
121
122    // SubTypes: self can only be VectoValue<IntValue<bool>>
123    #[llvm_versions(..=16)]
124    pub fn const_select<BV: BasicValue<'ctx>>(self, then: BV, else_: BV) -> BasicValueEnum<'ctx> {
125        unsafe {
126            BasicValueEnum::new(LLVMConstSelect(
127                self.as_value_ref(),
128                then.as_value_ref(),
129                else_.as_value_ref(),
130            ))
131        }
132    }
133
134    // SubTypes: <V: VectorValue<T, Const>> self: V, right: V, mask: V -> V
135    pub fn const_shuffle_vector(self, right: VectorValue<'ctx>, mask: VectorValue<'ctx>) -> VectorValue<'ctx> {
136        unsafe {
137            VectorValue::new(LLVMConstShuffleVector(
138                self.as_value_ref(),
139                right.as_value_ref(),
140                mask.as_value_ref(),
141            ))
142        }
143    }
144}
145
146unsafe impl AsValueRef for VectorValue<'_> {
147    fn as_value_ref(&self) -> LLVMValueRef {
148        self.vec_value.value
149    }
150}
151
152impl Display for VectorValue<'_> {
153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154        write!(f, "{}", self.print_to_string())
155    }
156}