//! //! The LLVM pointer. //! use inkwell::types::BasicType; use crate::eravm::context::address_space::AddressSpace; use crate::eravm::context::global::Global; use crate::eravm::context::Context; use crate::eravm::Dependency; /// /// The LLVM pointer. /// #[derive(Debug, Clone, Copy)] pub struct Pointer<'ctx> { /// The pointee type. pub r#type: inkwell::types::BasicTypeEnum<'ctx>, /// The address space. pub address_space: AddressSpace, /// The pointer value. pub value: inkwell::values::PointerValue<'ctx>, } impl<'ctx> Pointer<'ctx> { /// /// A shortcut constructor. /// pub fn new( r#type: T, address_space: AddressSpace, value: inkwell::values::PointerValue<'ctx>, ) -> Self where T: BasicType<'ctx>, { Self { r#type: r#type.as_basic_type_enum(), address_space, value, } } /// /// Wraps a 256-bit primitive type pointer. /// pub fn new_stack_field( context: &Context<'ctx, D>, value: inkwell::values::PointerValue<'ctx>, ) -> Self where D: Dependency + Clone, { Self { r#type: context.field_type().as_basic_type_enum(), address_space: AddressSpace::Stack, value, } } /// /// Creates a new pointer with the specified `offset`. /// pub fn new_with_offset( context: &Context<'ctx, D>, address_space: AddressSpace, r#type: T, offset: inkwell::values::IntValue<'ctx>, name: &str, ) -> Self where D: Dependency + Clone, T: BasicType<'ctx>, { assert_ne!( address_space, AddressSpace::Stack, "Stack pointers cannot be addressed" ); let offset = context.safe_truncate_int_to_i32(offset).unwrap(); let value = context .builder .build_int_to_ptr(offset, context.llvm().ptr_type(address_space.into()), name) .unwrap(); Self::new(r#type, address_space, value) } /// /// Casts the pointer into another type. /// pub fn cast(self, r#type: T) -> Self where T: BasicType<'ctx>, { Self { r#type: r#type.as_basic_type_enum(), address_space: self.address_space, value: self.value, } } pub fn address_space_cast( self, context: &Context<'ctx, D>, address_space: AddressSpace, name: &str, ) -> anyhow::Result where D: Dependency + Clone, { let value = context.builder().build_address_space_cast( self.value, context.llvm().ptr_type(address_space.into()), name, )?; Ok(Self { address_space, value, ..self }) } } impl<'ctx> From> for Pointer<'ctx> { fn from(global: Global<'ctx>) -> Self { Self { r#type: global.r#type, address_space: AddressSpace::Stack, value: global.value.as_pointer_value(), } } }