inkwell/values/
array_value.rs1#[llvm_versions(..17)]
2use llvm_sys::core::LLVMConstArray;
3#[llvm_versions(17..)]
4use llvm_sys::core::LLVMConstArray2 as LLVMConstArray;
5use llvm_sys::core::{LLVMGetAsString, LLVMIsAConstantArray, LLVMIsAConstantDataArray, LLVMIsConstantString};
6use llvm_sys::prelude::LLVMTypeRef;
7use llvm_sys::prelude::LLVMValueRef;
8
9use std::ffi::CStr;
10use std::fmt::{self, Display};
11
12use crate::types::{ArrayType, AsTypeRef};
13use crate::values::traits::{AnyValue, AsValueRef};
14use crate::values::{InstructionValue, Value};
15
16#[derive(PartialEq, Eq, Clone, Copy, Hash)]
18pub struct ArrayValue<'ctx> {
19 array_value: Value<'ctx>,
20}
21
22impl<'ctx> ArrayValue<'ctx> {
23 pub unsafe fn new(value: LLVMValueRef) -> Self {
29 assert!(!value.is_null());
30
31 ArrayValue {
32 array_value: Value::new(value),
33 }
34 }
35
36 pub unsafe fn new_const_array<T: AsTypeRef, V: AsValueRef>(ty: &T, values: &[V]) -> Self {
42 let values = values.iter().map(V::as_value_ref).collect::<Vec<_>>();
43 Self::new_raw_const_array(ty.as_type_ref(), &values)
44 }
45
46 pub unsafe fn new_raw_const_array(ty: LLVMTypeRef, values: &[LLVMValueRef]) -> Self {
52 unsafe { Self::new(LLVMConstArray(ty, values.as_ptr().cast_mut(), values.len() as _)) }
53 }
54
55 pub fn get_name(&self) -> &CStr {
58 self.array_value.get_name()
59 }
60
61 pub fn set_name(&self, name: &str) {
63 self.array_value.set_name(name)
64 }
65
66 pub fn get_type(self) -> ArrayType<'ctx> {
68 unsafe { ArrayType::new(self.array_value.get_type()) }
69 }
70
71 pub fn is_null(self) -> bool {
73 self.array_value.is_null()
74 }
75
76 pub fn is_undef(self) -> bool {
78 self.array_value.is_undef()
79 }
80
81 pub fn print_to_stderr(self) {
83 self.array_value.print_to_stderr()
84 }
85
86 pub fn as_instruction(self) -> Option<InstructionValue<'ctx>> {
88 self.array_value.as_instruction()
89 }
90
91 pub fn replace_all_uses_with(self, other: ArrayValue<'ctx>) {
94 self.array_value.replace_all_uses_with(other.as_value_ref())
95 }
96
97 pub fn is_const(self) -> bool {
112 self.array_value.is_const()
113 }
114
115 pub fn is_const_string(self) -> bool {
129 unsafe { LLVMIsConstantString(self.as_value_ref()) == 1 }
130 }
131
132 pub fn as_const_string(&self) -> Option<&[u8]> {
149 let mut len = 0;
150 let ptr = unsafe { LLVMGetAsString(self.as_value_ref(), &mut len) };
151
152 if ptr.is_null() {
153 None
154 } else {
155 unsafe { Some(std::slice::from_raw_parts(ptr.cast(), len)) }
156 }
157 }
158
159 #[deprecated = "llvm strings can contain internal NULs, and this function truncates such values, use as_const_string instead"]
176 pub fn get_string_constant(&self) -> Option<&CStr> {
177 let mut len = 0;
178 let ptr = unsafe { LLVMGetAsString(self.as_value_ref(), &mut len) };
179
180 if ptr.is_null() {
181 None
182 } else {
183 unsafe { Some(CStr::from_ptr(ptr)) }
184 }
185 }
186}
187
188unsafe impl AsValueRef for ArrayValue<'_> {
189 fn as_value_ref(&self) -> LLVMValueRef {
190 self.array_value.value
191 }
192}
193
194impl Display for ArrayValue<'_> {
195 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196 write!(f, "{}", self.print_to_string())
197 }
198}
199
200impl fmt::Debug for ArrayValue<'_> {
201 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
202 let llvm_value = self.print_to_string();
203 let llvm_type = self.get_type();
204 let name = self.get_name();
205 let is_const = self.is_const();
206 let is_null = self.is_null();
207 let is_const_array = unsafe { !LLVMIsAConstantArray(self.as_value_ref()).is_null() };
208 let is_const_data_array = unsafe { !LLVMIsAConstantDataArray(self.as_value_ref()).is_null() };
209
210 f.debug_struct("ArrayValue")
211 .field("name", &name)
212 .field("address", &self.as_value_ref())
213 .field("is_const", &is_const)
214 .field("is_const_array", &is_const_array)
215 .field("is_const_data_array", &is_const_data_array)
216 .field("is_null", &is_null)
217 .field("llvm_value", &llvm_value)
218 .field("llvm_type", &llvm_type)
219 .finish()
220 }
221}