75 lines
1.7 KiB
Rust
75 lines
1.7 KiB
Rust
use std::{
|
|
ffi::{CStr, CString, c_char},
|
|
ptr::null_mut,
|
|
};
|
|
|
|
use llvm_sys::error::LLVMDisposeErrorMessage;
|
|
|
|
use crate::{
|
|
Type,
|
|
builder::{Builder, InstructionValue},
|
|
};
|
|
|
|
pub fn into_cstring<T: Into<String>>(value: T) -> CString {
|
|
let string = value.into();
|
|
unsafe { CString::from_vec_with_nul_unchecked((string + "\0").into_bytes()) }
|
|
}
|
|
|
|
pub fn from_cstring(pointer: *mut c_char) -> Option<String> {
|
|
if pointer.is_null() {
|
|
None
|
|
} else {
|
|
unsafe { CStr::from_ptr(pointer).to_str().ok().map(|s| s.to_owned()) }
|
|
}
|
|
}
|
|
|
|
fn cstring_to_err(value: *mut c_char) -> Result<(), String> {
|
|
from_cstring(value)
|
|
.filter(|s| !s.is_empty())
|
|
.map_or(Ok(()), |s| Err(s))
|
|
}
|
|
|
|
/// Utility struct for LLVM's Error Messages, which need to be disposed
|
|
/// manually.
|
|
pub struct ErrorMessageHolder(*mut c_char);
|
|
|
|
impl ErrorMessageHolder {
|
|
pub fn null() -> Self {
|
|
ErrorMessageHolder(null_mut())
|
|
}
|
|
|
|
pub fn borrow_mut(&mut self) -> *mut *mut c_char {
|
|
&mut self.0
|
|
}
|
|
|
|
pub fn into_result(&self) -> Result<(), String> {
|
|
cstring_to_err(self.0)
|
|
}
|
|
}
|
|
|
|
impl Drop for ErrorMessageHolder {
|
|
fn drop(&mut self) {
|
|
unsafe {
|
|
if !self.0.is_null() {
|
|
LLVMDisposeErrorMessage(self.0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Make sure types for given instructions match. Return Ok(type) if they do,
|
|
/// and error otherwise.
|
|
pub fn match_types(
|
|
lhs: &InstructionValue,
|
|
rhs: &InstructionValue,
|
|
builder: &Builder,
|
|
) -> Result<Type, ()> {
|
|
let lhs_type = lhs.get_type(&builder);
|
|
let rhs_type = rhs.get_type(&builder);
|
|
if let (Ok(lhs_t), Ok(rhs_t)) = (lhs_type, rhs_type) {
|
|
if lhs_t == rhs_t { Ok(lhs_t) } else { Err(()) }
|
|
} else {
|
|
Err(())
|
|
}
|
|
}
|