From faf7a0f8c0430f52fbca8ece738d7f1f8e9bd36c Mon Sep 17 00:00:00 2001 From: David Mak Date: Tue, 19 Mar 2024 01:00:57 +0800 Subject: [PATCH] core: DO NOT MERGE - Add ArrayAllocaValue --- nac3core/src/codegen/classes.rs | 87 +++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/nac3core/src/codegen/classes.rs b/nac3core/src/codegen/classes.rs index 30697f1..7cf4e68 100644 --- a/nac3core/src/codegen/classes.rs +++ b/nac3core/src/codegen/classes.rs @@ -160,6 +160,93 @@ pub trait TypedArrayLikeMutator<'ctx, T, Index = IntValue<'ctx>>: UntypedArrayLi } } +#[derive(Copy, Clone)] +pub struct ArrayAllocaValue<'ctx>(PointerValue<'ctx>, IntValue<'ctx>, Option<&'ctx str>); + +impl<'ctx> ArrayAllocaValue<'ctx> { + /// Creates an [`ListValue`] from a [`PointerValue`]. + #[must_use] + pub fn from_ptr_val( + ptr: PointerValue<'ctx>, + size: IntValue<'ctx>, + name: Option<&'ctx str>, + ) -> Self { + ArrayAllocaValue(ptr, size, name) + } + + /// Returns the underlying [`PointerValue`] pointing to the `list` instance. + #[must_use] + pub fn as_ptr_value(&self) -> PointerValue<'ctx> { + self.0 + } +} + +impl<'ctx> From> for PointerValue<'ctx> { + fn from(value: ArrayAllocaValue<'ctx>) -> Self { + value.as_ptr_value() + } +} + +impl<'ctx> ArrayLikeValue<'ctx> for ArrayAllocaValue<'ctx> { + fn cast_elem_to_type( + _: &mut CodeGenContext<'ctx, '_>, + value: BasicValueEnum<'ctx>, + ) -> BasicValueEnum<'ctx> { + value + } + + fn size( + &self, + _: &mut CodeGenContext<'ctx, '_>, + _: &mut G, + ) -> IntValue<'ctx> { + self.1 + } + + unsafe fn ptr_offset_unchecked( + &self, + ctx: &mut CodeGenContext<'ctx, '_>, + _: &mut G, + idx: IntValue<'ctx>, + name: Option<&str>, + ) -> PointerValue<'ctx> { + let var_name = name + .map(|v| format!("{v}.addr")) + .unwrap_or_default(); + + ctx.builder.build_in_bounds_gep( + self.as_ptr_value(), + &[idx], + var_name.as_str(), + ).unwrap() + } + + fn ptr_offset( + &self, + ctx: &mut CodeGenContext<'ctx, '_>, + generator: &mut G, + idx: IntValue<'ctx>, + name: Option<&str>, + ) -> PointerValue<'ctx> { + debug_assert_eq!(idx.get_type(), generator.get_size_type(ctx.ctx)); + + let size = self.size(ctx, generator); + let in_range = ctx.builder.build_int_compare(IntPredicate::ULT, idx, size, "").unwrap(); + ctx.make_assert( + generator, + in_range, + "0:IndexError", + "list index out of range", + [None, None, None], + ctx.current_loc, + ); + + unsafe { + self.ptr_offset_unchecked(ctx, generator, idx, name) + } + } +} + #[cfg(not(debug_assertions))] pub fn assert_is_list<'ctx>(_value: PointerValue<'ctx>, _llvm_usize: IntType<'ctx>) {}