llvm_lib/core/values/constants/composite.rs
1//! Functions in this group operate on composite constants.
2
3use super::ValueRef;
4use crate::core::context::ContextRef;
5use crate::core::types::TypeRef;
6use crate::{CInt, CStr, CString, CUint, GetRef, SizeT};
7use llvm_sys::core;
8
9/// Create a `ConstantDataSequential` and initialize it with a string.
10///
11/// # Details
12///
13/// Creates a constant string value in a specified LLVM context.
14///
15/// This function wraps the `LLVMConstStringInContext2` function from the LLVM core library. It generates a constant
16/// string value within the specified LLVM context (`context`) using the provided string slice (`string`). The function
17/// also allows you to specify whether the string should be null-terminated.
18///
19/// # Parameters
20///
21/// - `context`: A reference to the LLVM context (`ContextRef`) in which the constant string should be created.
22/// - `string`: A string slice that represents the content of the constant string. This string will be used to generate the LLVM constant.
23/// - `dont_null_terminate`: A boolean value indicating whether the string should not be null-terminated. If `true`, the string will not be null-terminated; if `false`, a null terminator will be added.
24///
25/// # Returns
26///
27/// Returns an instance of `ValueRef`, which encapsulates the constant string value created in the specified context.
28#[must_use]
29pub fn const_string_in_context2(
30 context: &ContextRef,
31 string: &str,
32 dont_null_terminate: bool,
33) -> ValueRef {
34 let c_string = CString::from(string);
35 unsafe {
36 ValueRef(core::LLVMConstStringInContext2(
37 context.get_ref(),
38 c_string.as_ptr(),
39 *SizeT::from(string.len()),
40 *CInt::from(dont_null_terminate),
41 ))
42 }
43}
44
45/// Create a `ConstantDataSequential` with string content in the global context.
46///
47/// This is the same as `const_string_in_context` except it operates on the
48/// global context.
49///
50/// # Details
51///
52/// Creates a constant string value in the global LLVM context.
53///
54/// This function wraps the `LLVMConstString` function from the LLVM core library. It generates a constant
55/// string value within the global LLVM context using the provided string slice (`string`). The function
56/// also allows you to specify whether the string should be null-terminated. This function is similar to
57/// `const_string_in_context`, but it operates on the global context instead of a specified context.
58///
59/// # Parameters
60///
61/// - `string`: A string slice that represents the content of the constant string. This string will be used to generate the LLVM constant.
62/// - `dont_null_terminate`: A boolean value indicating whether the string should not be null-terminated. If `true`, the string will not be null-terminated; if `false`, a null terminator will be added.
63///
64/// # Returns
65///
66/// Returns an instance of `ValueRef`, which encapsulates the constant string value created in the global context.
67#[must_use]
68pub fn const_string(string: &str, dont_null_terminate: bool) -> ValueRef {
69 let c_string = CString::from(string);
70 unsafe {
71 ValueRef(core::LLVMConstString(
72 c_string.as_ptr(),
73 *CUint::from(string.len()),
74 *CInt::from(dont_null_terminate),
75 ))
76 }
77}
78
79/// Returns true if the specified constant is an array of `i8`.
80///
81/// # Details
82///
83/// Checks if the value is a constant string.
84///
85/// This function wraps the `LLVMIsConstantString` function from the LLVM core library. It determines whether
86/// the value represented by `ValueRef` is a constant string. This is useful when you need to verify if a particular
87/// LLVM value is a constant string within the IR.
88///
89/// # Returns
90///
91/// Returns `true` if the value is a constant string, otherwise returns `false`.
92#[must_use]
93pub fn is_constant_string(val: &ValueRef) -> bool {
94 unsafe { core::LLVMIsConstantString(val.get_ref()) != 0 }
95}
96
97/// Get the given constant data sequential as a string.
98///
99/// # Details
100///
101/// Retrieves the value as a string if the value is a constant string.
102///
103/// This function wraps the `LLVMGetAsString` function from the LLVM core library. It attempts to extract the value
104/// represented by `ValueRef` as a string if it is a constant string. The function returns `None` if the value is not a
105/// constant string, or `Some(String)` containing the string representation if it is.
106///
107/// # Returns
108///
109/// Returns an `Option<String>`:
110/// - `Some(String)` containing the string representation of the constant if it is a constant string.
111/// - `None` if the value is not a constant string.
112#[must_use]
113pub fn get_as_string(val: &ValueRef) -> Option<String> {
114 unsafe {
115 let mut length = 0;
116 let c_str = core::LLVMGetAsString(val.get_ref(), &mut length);
117 if c_str.is_null() {
118 None
119 } else {
120 Some(CStr::new(c_str).to_string())
121 }
122 }
123}
124
125/// Create an anonymous `ConstantStruct` with the specified values.
126///
127/// # Details
128///
129/// Creates a constant struct value in a specified LLVM context.
130///
131/// This function wraps the `LLVMConstStructInContext` function from the LLVM core library. It generates a constant
132/// struct value within the specified LLVM context (`context`) using an array of constant values (`constant_vals`).
133/// The `packed` parameter allows you to specify whether the struct should be packed, meaning that its fields are
134/// laid out without padding.
135///
136/// # Parameters
137///
138/// - `context`: A reference to the LLVM context [`ContextRef`] in which the constant struct should be created.
139/// - `constant_vals`: A slice of constant values &[`ValueRef`] that will be used as the fields of the struct. Each element in this slice corresponds to a field in the struct.
140/// - `packed`: A boolean value indicating whether the struct should be packed (`true` for packed, `false` for unpacked). A packed struct has its fields tightly packed without padding.
141///
142/// # Returns
143///
144/// Returns an instance of [`ValueRef`], which encapsulates the constant struct value created in the specified context.
145#[must_use]
146pub fn const_struct_in_context(
147 context: &ContextRef,
148 constant_vals: &[ValueRef],
149 packed: bool,
150) -> ValueRef {
151 let constant_vals_ptr = crate::to_mut_ptr!(constant_vals);
152 unsafe {
153 ValueRef(core::LLVMConstStructInContext(
154 context.get_ref(),
155 constant_vals_ptr,
156 *CUint::from(constant_vals.len()),
157 *CInt::from(packed),
158 ))
159 }
160}
161
162/// Create a `ConstantStruct` in the global `Context`.
163///
164/// This is the same as `constStruct_in_context` except it operates on the
165/// global context.
166///
167/// # Details
168///
169/// Creates a constant struct value in the global LLVM context.
170///
171/// This function wraps the `LLVMConstStruct` function from the LLVM core library. It generates a constant
172/// struct value using an array of constant values (`constant_vals`). The `packed` parameter allows you to specify
173/// whether the struct should be packed, meaning that its fields are laid out without padding. This function operates
174/// in the global LLVM context, as opposed to a specific context.
175///
176/// # Parameters
177///
178/// - `constant_vals`: A slice of constant values &[`ValueRef`] that will be used as the fields of the struct. Each element in this slice corresponds to a field in the struct.
179/// - `packed`: A boolean value indicating whether the struct should be packed (`true` for packed, `false` for unpacked). A packed struct has its fields tightly packed without padding.
180///
181/// # Returns
182///
183/// Returns an instance of `ValueRef`, which encapsulates the constant struct value created in the global context.
184#[must_use]
185pub fn const_struct(constant_vals: &[ValueRef], packed: bool) -> ValueRef {
186 let constant_vals_ptr = crate::to_mut_ptr!(constant_vals);
187 unsafe {
188 ValueRef(core::LLVMConstStruct(
189 constant_vals_ptr,
190 *CUint::from(constant_vals.len()),
191 *CInt::from(packed),
192 ))
193 }
194}
195
196/// Create a `ConstantArray` from values.
197///
198/// # Details
199///
200/// Creates a constant array value with elements of a specified type.
201///
202/// This function wraps the `LLVMConstArray2` function from the LLVM core library. It generates a constant
203/// array value with the specified element type (`element_type`) using an array of constant values (`constant_vals`).
204/// Each element in `constant_vals` must be of the same type as `element_type`.
205///
206/// # Parameters
207///
208/// - `element_type`: A reference to the type of elements in the array (`TypeRef`). This specifies the type that each element in the array should have.
209/// - `constant_vals`: A slice of constant values (`&[ValueRef]`) that will be used as the elements of the array. Each element in this slice corresponds to an element in the resulting array.
210///
211/// # Returns
212///
213/// Returns an instance of [`ValueRef`], which encapsulates the constant array value created with the specified element type and elements.
214#[must_use]
215pub fn const_array2(element_type: &TypeRef, constant_vals: &[ValueRef]) -> ValueRef {
216 let constant_vals_ptr = crate::to_mut_ptr!(constant_vals);
217 unsafe {
218 ValueRef(core::LLVMConstArray2(
219 element_type.get_ref(),
220 constant_vals_ptr,
221 u64::try_from(constant_vals.len()).unwrap_or(u64::MAX),
222 ))
223 }
224}
225
226/// Create a non-anonymous `ConstantStruct` from values.
227///
228/// # Details
229///
230/// Creates a constant named struct value with specified field values.
231///
232/// This function wraps the `LLVMConstNamedStruct` function from the LLVM core library. It generates a constant
233/// struct value of the specified named struct type (`struct_type`) using an array of constant values (`constant_vals`).
234/// Each element in `constant_vals` corresponds to a field in the struct.
235///
236/// # Parameters
237///
238/// - `struct_type`: A reference to the named struct type (`TypeRef`) for the constant value. This type specifies the structure that the constant will represent.
239/// - `constant_vals`: A slice of constant values (`&[ValueRef]`) that will be used as the fields of the struct. Each element in this slice corresponds to a field in the struct.
240///
241/// # Returns
242///
243/// Returns an instance of [`ValueRef`], which encapsulates the constant named struct value created with the specified fields.
244#[must_use]
245pub fn const_named_struct(struct_type: &TypeRef, constant_vals: &[ValueRef]) -> ValueRef {
246 let constant_vals_ptr = crate::to_mut_ptr!(constant_vals);
247 unsafe {
248 ValueRef(core::LLVMConstNamedStruct(
249 struct_type.get_ref(),
250 constant_vals_ptr,
251 *CUint::from(constant_vals.len()),
252 ))
253 }
254}
255
256/// Get element of a constant aggregate `(struct, array or vector)` at the
257/// specified index. Returns `None` if the index is out of range, or it's not
258/// possible to determine the element (e.g., because the constant is a
259/// constant expression.)
260///
261/// # Details
262///
263/// Retrieves a specific element from an aggregate constant (e.g., an array or struct).
264///
265/// This function wraps the `LLVMGetAggregateElement` function from the LLVM core library. It returns the element
266/// at the specified index (`idx`) from the aggregate constant represented by [`ValueRef`]. If the index is out of bounds
267/// or the element cannot be retrieved, the function returns `None`.
268///
269/// # Parameters
270///
271/// - `idx`: The index of the element to retrieve from the aggregate constant. This index should be within the bounds of the aggregate's elements.
272///
273/// # Returns
274///
275/// Returns an [Option<ValueRef>]:
276/// - `Some(ValueRef)` containing the retrieved element if the index is valid and the element is found.
277/// - `None` if the index is out of bounds or the element cannot be retrieved.
278#[must_use]
279pub fn get_aggregate_element(val: &ValueRef, idx: u32) -> Option<ValueRef> {
280 let element = unsafe { core::LLVMGetAggregateElement(val.get_ref(), *CUint::from(idx)) };
281 if element.is_null() {
282 None
283 } else {
284 Some(ValueRef(element))
285 }
286}
287
288/// Create a `ConstantVector` from values.
289///
290/// # Details
291///
292/// Creates a constant vector value from an array of scalar constant values.
293///
294/// This function wraps the `LLVMConstVector` function from the LLVM core library. It generates a constant
295/// vector using the provided array of scalar constant values (`scalar_constant_vals`). Each element in the array
296/// corresponds to an element in the resulting vector, and the type of the vector is inferred from the types of the scalar constants.
297///
298/// # Parameters
299///
300/// - `scalar_constant_vals`: A slice of scalar constant values [`ValueRef`] that will be used as the elements of the vector. Each element in this slice corresponds to an element in the resulting vector.
301///
302/// # Returns
303///
304/// Returns an instance of [`ValueRef`], which encapsulates the constant vector value created from the specified scalar constants.
305#[must_use]
306pub fn const_vector(scalar_constant_vals: &[ValueRef]) -> ValueRef {
307 let scalar_constant_vals_ptr = crate::to_mut_ptr!(scalar_constant_vals);
308 unsafe {
309 ValueRef(core::LLVMConstVector(
310 scalar_constant_vals_ptr,
311 *CUint::from(scalar_constant_vals.len()),
312 ))
313 }
314}