use inkwell::builder::Builder;
use inkwell::types::{BasicType, BasicTypeEnum};
use inkwell::values::{BasicValueEnum, PointerValue};
use inkwell::AddressSpace;
use std::ffi::CStr;
#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
pub struct RuntimeReferenceValue<'ink>(PointerValue<'ink>);
impl<'ink> RuntimeReferenceValue<'ink> {
pub fn from_ptr(
ptr: PointerValue<'ink>,
object_type: impl BasicType<'ink>,
) -> Result<Self, String> {
let reference_type = object_type
.ptr_type(AddressSpace::Generic)
.ptr_type(AddressSpace::Generic);
if ptr.get_type() == reference_type {
Ok(Self(ptr))
} else {
Err(format!(
"expected pointer of type {}, got {}",
reference_type.print_to_string().to_string_lossy(),
ptr.get_type().print_to_string().to_string_lossy()
))
}
}
pub unsafe fn from_ptr_unchecked(ptr: PointerValue<'ink>) -> Self {
Self(ptr)
}
pub fn get_name(&self) -> &CStr {
self.0.get_name()
}
pub fn get_data_ptr(&self, builder: &Builder<'ink>) -> PointerValue<'ink> {
let value_name = self.0.get_name().to_string_lossy();
builder
.build_load(self.0, &format!("{}->data", &value_name))
.into_pointer_value()
}
pub fn get_type(&self) -> BasicTypeEnum<'ink> {
self.0
.get_type()
.get_element_type()
.into_pointer_type()
.get_element_type()
.try_into()
.expect("could not convert reference type to basic type")
}
}
impl<'ink> From<RuntimeReferenceValue<'ink>> for BasicValueEnum<'ink> {
fn from(value: RuntimeReferenceValue<'ink>) -> Self {
value.0.into()
}
}
impl<'ink> From<RuntimeReferenceValue<'ink>> for PointerValue<'ink> {
fn from(value: RuntimeReferenceValue<'ink>) -> Self {
value.0
}
}