-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added constants: composite, scalar (#10)
- Loading branch information
Showing
5 changed files
with
323 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
//! Functions in this group operate on composite constants. | ||
|
||
use super::ValueRef; | ||
use crate::core::context::ContextRef; | ||
use crate::core::types::TypeRef; | ||
use crate::{CInt, CStr, CString, CUint, GetRef}; | ||
use llvm_sys::core; | ||
|
||
impl ValueRef { | ||
/// Create a `ConstantDataSequential` and initialize it with a string. | ||
#[must_use] | ||
pub fn const_string_in_context( | ||
context: &ContextRef, | ||
string: &str, | ||
dont_null_terminate: bool, | ||
) -> Self { | ||
let c_string = CString::from(string); | ||
unsafe { | ||
Self(core::LLVMConstStringInContext( | ||
context.get_ref(), | ||
c_string.as_ptr(), | ||
*CUint::from(string.len()), | ||
*CInt::from(dont_null_terminate), | ||
)) | ||
} | ||
} | ||
|
||
/// Create a `ConstantDataSequential` with string content in the global context. | ||
/// | ||
/// This is the same as `const_string_in_context` except it operates on the | ||
/// global context. | ||
#[must_use] | ||
pub fn const_string(string: &str, dont_null_terminate: bool) -> Self { | ||
let c_string = CString::from(string); | ||
unsafe { | ||
Self(core::LLVMConstString( | ||
c_string.as_ptr(), | ||
*CUint::from(string.len()), | ||
*CInt::from(dont_null_terminate), | ||
)) | ||
} | ||
} | ||
|
||
/// Returns true if the specified constant is an array of `i8`. | ||
#[must_use] | ||
pub fn is_constant_string(&self) -> bool { | ||
unsafe { core::LLVMIsConstantString(self.0) != 0 } | ||
} | ||
|
||
/// Get the given constant data sequential as a string. | ||
#[must_use] | ||
pub fn get_as_string(&self) -> Option<String> { | ||
unsafe { | ||
let mut length = 0; | ||
let c_str = core::LLVMGetAsString(self.0, &mut length); | ||
if c_str.is_null() { | ||
None | ||
} else { | ||
Some(CStr::new(c_str).to_string()) | ||
} | ||
} | ||
} | ||
|
||
/// Create an anonymous `ConstantStruct` with the specified values. | ||
#[must_use] | ||
pub fn const_struct_in_context( | ||
context: &ContextRef, | ||
constant_vals: &[Self], | ||
packed: bool, | ||
) -> Self { | ||
let mut constant_vals = constant_vals.iter().map(|v| v.0).collect::<Vec<_>>(); | ||
let constant_vals_ptr = if constant_vals.is_empty() { | ||
std::ptr::null_mut() | ||
} else { | ||
constant_vals.as_mut_ptr() | ||
}; | ||
unsafe { | ||
Self(core::LLVMConstStructInContext( | ||
context.get_ref(), | ||
constant_vals_ptr, | ||
*CUint::from(constant_vals.len()), | ||
*CInt::from(packed), | ||
)) | ||
} | ||
} | ||
|
||
/// Create a `ConstantStruct` in the global `Context`. | ||
/// | ||
/// This is the same as `constStruct_in_context` except it operates on the | ||
/// global context. | ||
#[must_use] | ||
pub fn const_struct(constant_vals: &[Self], packed: bool) -> Self { | ||
let mut constant_vals = constant_vals.iter().map(|v| v.0).collect::<Vec<_>>(); | ||
let constant_vals_ptr = if constant_vals.is_empty() { | ||
std::ptr::null_mut() | ||
} else { | ||
constant_vals.as_mut_ptr() | ||
}; | ||
unsafe { | ||
Self(core::LLVMConstStruct( | ||
constant_vals_ptr, | ||
*CUint::from(constant_vals.len()), | ||
*CInt::from(packed), | ||
)) | ||
} | ||
} | ||
|
||
/// Create a `ConstantArray` from values. | ||
#[must_use] | ||
pub fn const_array2(element_type: &TypeRef, constant_vals: &[Self]) -> Self { | ||
let mut constant_vals = constant_vals.iter().map(|v| v.0).collect::<Vec<_>>(); | ||
let constant_vals_ptr = if constant_vals.is_empty() { | ||
std::ptr::null_mut() | ||
} else { | ||
constant_vals.as_mut_ptr() | ||
}; | ||
unsafe { | ||
Self(core::LLVMConstArray2( | ||
element_type.get_ref(), | ||
constant_vals_ptr, | ||
u64::try_from(constant_vals.len()).unwrap_or(u64::MAX), | ||
)) | ||
} | ||
} | ||
|
||
/// Create a non-anonymous `ConstantStruct` from values. | ||
#[must_use] | ||
pub fn const_named_struct(struct_type: &TypeRef, constant_vals: &[Self]) -> Self { | ||
let mut constant_vals = constant_vals.iter().map(|v| v.0).collect::<Vec<_>>(); | ||
let constant_vals_ptr = if constant_vals.is_empty() { | ||
std::ptr::null_mut() | ||
} else { | ||
constant_vals.as_mut_ptr() | ||
}; | ||
unsafe { | ||
Self(core::LLVMConstNamedStruct( | ||
struct_type.get_ref(), | ||
constant_vals_ptr, | ||
*CUint::from(constant_vals.len()), | ||
)) | ||
} | ||
} | ||
|
||
/// Get element of a constant aggregate `(struct, array or vector)` at the | ||
/// specified index. Returns `None` if the index is out of range, or it's not | ||
/// possible to determine the element (e.g., because the constant is a | ||
/// constant expression.) | ||
#[must_use] | ||
pub fn get_aggregate_element(&self, idx: u32) -> Option<Self> { | ||
let element = unsafe { core::LLVMGetAggregateElement(self.0, *CUint::from(idx)) }; | ||
if element.is_null() { | ||
None | ||
} else { | ||
Some(Self(element)) | ||
} | ||
} | ||
|
||
/// Create a `ConstantVector` from values. | ||
#[must_use] | ||
pub fn const_vector(scalar_constant_vals: &[Self]) -> Self { | ||
let mut scalar_constant_vals = scalar_constant_vals.iter().map(|v| v.0).collect::<Vec<_>>(); | ||
let scalar_constant_vals_ptr = if scalar_constant_vals.is_empty() { | ||
std::ptr::null_mut() | ||
} else { | ||
scalar_constant_vals.as_mut_ptr() | ||
}; | ||
unsafe { | ||
Self(core::LLVMConstVector( | ||
scalar_constant_vals_ptr, | ||
*CUint::from(scalar_constant_vals.len()), | ||
)) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
//! Functions in this group model `ValueRef` instances that correspond | ||
//! to constants referring to scalar types. | ||
|
||
use super::ValueRef; | ||
use crate::core::types::TypeRef; | ||
use crate::{CDouble, CInt, CString, CUint, GetRef}; | ||
use llvm_sys::core; | ||
|
||
impl ValueRef { | ||
/// Obtain a constant value for an integer type. | ||
/// | ||
/// The returned value corresponds to a `llvm ConstantInt`. | ||
#[must_use] | ||
pub fn const_int(ty: &TypeRef, n: u64, sign_extend: bool) -> Self { | ||
unsafe { | ||
Self(core::LLVMConstInt( | ||
ty.get_ref(), | ||
n, | ||
*CInt::from(sign_extend), | ||
)) | ||
} | ||
} | ||
|
||
/// Obtain a constant value for an integer of arbitrary precision. | ||
#[must_use] | ||
pub fn const_int_of_arbitrary_precision(ty: &TypeRef, words: &[u64]) -> Self { | ||
unsafe { | ||
Self(core::LLVMConstIntOfArbitraryPrecision( | ||
ty.get_ref(), | ||
*CUint::from(words.len()), | ||
words.as_ptr(), | ||
)) | ||
} | ||
} | ||
|
||
/// Obtain a constant value for an integer parsed from a string. | ||
/// | ||
/// A similar API, `const_int_of_string_and_size` is also available. If the | ||
/// string's length is available, it is preferred to call that function | ||
/// instead. | ||
#[must_use] | ||
pub fn const_int_of_string(ty: &TypeRef, text: &str, radix: u8) -> Self { | ||
let c_text = CString::from(text); | ||
unsafe { | ||
Self(core::LLVMConstIntOfString( | ||
ty.get_ref(), | ||
c_text.as_ptr(), | ||
radix, | ||
)) | ||
} | ||
} | ||
|
||
/// Obtain a constant value for an integer parsed from a string with | ||
/// specified length. | ||
#[must_use] | ||
pub fn const_int_of_string_and_size(ty: &TypeRef, text: &str, radix: u8) -> Self { | ||
let c_text = CString::from(text); | ||
unsafe { | ||
Self(core::LLVMConstIntOfStringAndSize( | ||
ty.get_ref(), | ||
c_text.as_ptr(), | ||
*CUint::from(text.len()), | ||
radix, | ||
)) | ||
} | ||
} | ||
|
||
/// Obtain a constant value referring to a double floating point value. | ||
#[must_use] | ||
pub fn const_real(ty: &TypeRef, n: f64) -> Self { | ||
unsafe { Self(core::LLVMConstReal(ty.get_ref(), *CDouble::from(n))) } | ||
} | ||
|
||
/// Obtain a constant for a floating point value parsed from a string. | ||
/// | ||
/// A similar API, `const_real_of_string_and_size` is also available. It | ||
/// should be used if the input string's length is known. | ||
#[must_use] | ||
pub fn const_real_of_string(ty: &TypeRef, text: &str) -> Self { | ||
let c_text = CString::from(text); | ||
unsafe { Self(core::LLVMConstRealOfString(ty.get_ref(), c_text.as_ptr())) } | ||
} | ||
|
||
/// Obtain a constant for a floating point value parsed from a string with specified length. | ||
#[must_use] | ||
pub fn const_real_of_string_and_size(ty: &TypeRef, text: &str) -> Self { | ||
let c_text = CString::from(text); | ||
unsafe { | ||
Self(core::LLVMConstRealOfStringAndSize( | ||
ty.get_ref(), | ||
c_text.as_ptr(), | ||
*CUint::from(text.len()), | ||
)) | ||
} | ||
} | ||
|
||
/// Obtain the zero extended value for an integer constant value. | ||
#[must_use] | ||
pub fn const_int_get_zext_value(&self) -> u64 { | ||
unsafe { core::LLVMConstIntGetZExtValue(self.0) } | ||
} | ||
|
||
/// Obtain the sign extended value for an integer constant value. | ||
#[must_use] | ||
pub fn const_int_get_sext_value(&self) -> i64 { | ||
unsafe { core::LLVMConstIntGetSExtValue(self.0) } | ||
} | ||
|
||
/// Obtain the double value for a floating point constant value. | ||
/// `losesInfo` indicates if some precision was lost in the conversion. | ||
/// | ||
/// ## Returns | ||
/// `f64` constant value and `losesInfo` flag | ||
#[must_use] | ||
pub fn const_real_get_double(&self) -> (f64, bool) { | ||
let mut loses_info_c = 0; | ||
let result = unsafe { core::LLVMConstRealGetDouble(self.0, &mut loses_info_c) }; | ||
(result, loses_info_c != 0) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters