diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index 2cc54387..65d3ea00 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -1431,7 +1431,7 @@ fn polymorphic_print<'ctx>( fmt.push_str("range("); flush(ctx, generator, &mut fmt, &mut args); - let val = RangeType::new(ctx).map_value(value.into_pointer_value(), None); + let val = RangeType::new(ctx).map_pointer_value(value.into_pointer_value(), None); let (start, stop, step) = destructure_range(ctx, val); diff --git a/nac3core/src/codegen/builtin_fns.rs b/nac3core/src/codegen/builtin_fns.rs index 4974a605..1086a649 100644 --- a/nac3core/src/codegen/builtin_fns.rs +++ b/nac3core/src/codegen/builtin_fns.rs @@ -47,14 +47,14 @@ pub fn call_len<'ctx, G: CodeGenerator + ?Sized>( let range_ty = ctx.primitives.range; Ok(if ctx.unifier.unioned(arg_ty, range_ty) { - let arg = RangeType::new(ctx).map_value(arg.into_pointer_value(), Some("range")); + let arg = RangeType::new(ctx).map_pointer_value(arg.into_pointer_value(), Some("range")); let (start, end, step) = destructure_range(ctx, arg); calculate_len_for_slice_range(generator, ctx, start, end, step) } else { match &*ctx.unifier.get_ty_immutable(arg_ty) { TypeEnum::TTuple { .. } => { let tuple = TupleType::from_unifier_type(generator, ctx, arg_ty) - .map_value(arg.into_struct_value(), None); + .map_struct_value(arg.into_struct_value(), None); llvm_i32.const_int(tuple.get_type().num_elements().into(), false) } @@ -72,7 +72,7 @@ pub fn call_len<'ctx, G: CodeGenerator + ?Sized>( if *obj_id == ctx.primitives.list.obj_id(&ctx.unifier).unwrap() => { let list = ListType::from_unifier_type(generator, ctx, arg_ty) - .map_value(arg.into_pointer_value(), None); + .map_pointer_value(arg.into_pointer_value(), None); ctx.builder .build_int_truncate_or_bit_cast(list.load_size(ctx, None), llvm_i32, "len") .unwrap() diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index 11b31350..9722f42a 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -1151,7 +1151,7 @@ pub fn gen_comprehension<'ctx, G: CodeGenerator>( if *obj_id == ctx.primitives.range.obj_id(&ctx.unifier).unwrap() => { let iter_val = - RangeType::new(ctx).map_value(iter_val.into_pointer_value(), Some("range")); + RangeType::new(ctx).map_pointer_value(iter_val.into_pointer_value(), Some("range")); let (start, stop, step) = destructure_range(ctx, iter_val); let diff = ctx.builder.build_int_sub(stop, start, "diff").unwrap(); // add 1 to the length as the value is rounded to zero diff --git a/nac3core/src/codegen/stmt.rs b/nac3core/src/codegen/stmt.rs index e8f1d906..890644a2 100644 --- a/nac3core/src/codegen/stmt.rs +++ b/nac3core/src/codegen/stmt.rs @@ -511,7 +511,7 @@ pub fn gen_for( if *obj_id == ctx.primitives.range.obj_id(&ctx.unifier).unwrap() => { let iter_val = - RangeType::new(ctx).map_value(iter_val.into_pointer_value(), Some("range")); + RangeType::new(ctx).map_pointer_value(iter_val.into_pointer_value(), Some("range")); // Internal variable for loop; Cannot be assigned let i = generator.gen_var_alloc(ctx, int32.into(), Some("for.i.addr"))?; // Variable declared in "target" expression of the loop; Can be reassigned *or* shadowed diff --git a/nac3core/src/codegen/types/list.rs b/nac3core/src/codegen/types/list.rs index f99ad5cb..b4110daa 100644 --- a/nac3core/src/codegen/types/list.rs +++ b/nac3core/src/codegen/types/list.rs @@ -1,7 +1,7 @@ use inkwell::{ - context::{AsContextRef, Context}, - types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType}, - values::{IntValue, PointerValue}, + context::Context, + types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType, StructType}, + values::{IntValue, PointerValue, StructValue}, AddressSpace, IntPredicate, OptimizationLevel, }; use itertools::Itertools; @@ -13,8 +13,9 @@ use crate::{ codegen::{ types::structure::{ check_struct_type_matches_fields, FieldIndexCounter, StructField, StructFields, + StructProxyType, }, - values::{ListValue, ProxyValue}, + values::ListValue, CodeGenContext, CodeGenerator, }, typecheck::typedef::{iter_type_vars, Type, TypeEnum}, @@ -62,13 +63,6 @@ impl<'ctx> ListType<'ctx> { ListStructFields::new_typed(item, llvm_usize) } - /// See [`ListType::fields`]. - // TODO: Move this into e.g. StructProxyType - #[must_use] - pub fn get_fields(&self, _ctx: &impl AsContextRef<'ctx>) -> ListStructFields<'ctx> { - Self::fields(self.item.unwrap_or(self.llvm_usize.into()), self.llvm_usize) - } - /// Creates an LLVM type corresponding to the expected structure of a `List`. #[must_use] fn llvm_type( @@ -153,9 +147,15 @@ impl<'ctx> ListType<'ctx> { Self::new_impl(ctx.ctx, llvm_elem_type, llvm_usize) } + /// Creates an [`ListType`] from a [`StructType`]. + #[must_use] + pub fn from_struct_type(ty: StructType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + Self::from_pointer_type(ty.ptr_type(AddressSpace::default()), llvm_usize) + } + /// Creates an [`ListType`] from a [`PointerType`]. #[must_use] - pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + pub fn from_pointer_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); let ctx = ptr_ty.get_context(); @@ -295,9 +295,27 @@ impl<'ctx> ListType<'ctx> { /// Converts an existing value into a [`ListValue`]. #[must_use] - pub fn map_value( + pub fn map_struct_value( &self, - value: <>::Value as ProxyValue<'ctx>>::Base, + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + value: StructValue<'ctx>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_struct_value( + generator, + ctx, + value, + self.llvm_usize, + name, + ) + } + + /// Converts an existing value into a [`ListValue`]. + #[must_use] + pub fn map_pointer_value( + &self, + value: PointerValue<'ctx>, name: Option<&'ctx str>, ) -> >::Value { >::Value::from_pointer_value(value, self.llvm_usize, name) @@ -357,6 +375,14 @@ impl<'ctx> ProxyType<'ctx> for ListType<'ctx> { } } +impl<'ctx> StructProxyType<'ctx> for ListType<'ctx> { + type StructFields = ListStructFields<'ctx>; + + fn get_fields(&self) -> Self::StructFields { + Self::fields(self.item.unwrap_or(self.llvm_usize.into()), self.llvm_usize) + } +} + impl<'ctx> From> for PointerType<'ctx> { fn from(value: ListType<'ctx>) -> Self { value.as_base_type() diff --git a/nac3core/src/codegen/types/ndarray/array.rs b/nac3core/src/codegen/types/ndarray/array.rs index 9630ec15..15f83a8f 100644 --- a/nac3core/src/codegen/types/ndarray/array.rs +++ b/nac3core/src/codegen/types/ndarray/array.rs @@ -222,7 +222,7 @@ impl<'ctx> NDArrayType<'ctx> { if *obj_id == ctx.primitives.list.obj_id(&ctx.unifier).unwrap() => { let list = ListType::from_unifier_type(generator, ctx, object_ty) - .map_value(object.into_pointer_value(), None); + .map_pointer_value(object.into_pointer_value(), None); self.construct_numpy_array_list_impl(generator, ctx, (object_ty, list), copy, name) } diff --git a/nac3core/src/codegen/types/ndarray/broadcast.rs b/nac3core/src/codegen/types/ndarray/broadcast.rs index 40847ce2..fa532b42 100644 --- a/nac3core/src/codegen/types/ndarray/broadcast.rs +++ b/nac3core/src/codegen/types/ndarray/broadcast.rs @@ -1,7 +1,7 @@ use inkwell::{ context::{AsContextRef, Context}, - types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType}, - values::{IntValue, PointerValue}, + types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType, StructType}, + values::{IntValue, PointerValue, StructValue}, AddressSpace, }; use itertools::Itertools; @@ -10,10 +10,10 @@ use nac3core_derive::StructFields; use crate::codegen::{ types::{ - structure::{check_struct_type_matches_fields, StructField, StructFields}, + structure::{check_struct_type_matches_fields, StructField, StructFields, StructProxyType}, ProxyType, }, - values::{ndarray::ShapeEntryValue, ProxyValue}, + values::ndarray::ShapeEntryValue, CodeGenContext, CodeGenerator, }; @@ -41,13 +41,6 @@ impl<'ctx> ShapeEntryType<'ctx> { ShapeEntryStructFields::new(ctx, llvm_usize) } - /// See [`ShapeEntryStructFields::fields`]. - // TODO: Move this into e.g. StructProxyType - #[must_use] - pub fn get_fields(&self, ctx: impl AsContextRef<'ctx>) -> ShapeEntryStructFields<'ctx> { - Self::fields(ctx, self.llvm_usize) - } - /// Creates an LLVM type corresponding to the expected structure of a `ShapeEntry`. #[must_use] fn llvm_type(ctx: &'ctx Context, llvm_usize: IntType<'ctx>) -> PointerType<'ctx> { @@ -78,9 +71,15 @@ impl<'ctx> ShapeEntryType<'ctx> { Self::new_impl(ctx, generator.get_size_type(ctx)) } + /// Creates a [`ShapeEntryType`] from a [`StructType`] representing an `ShapeEntry`. + #[must_use] + pub fn from_struct_type(ty: StructType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + Self::from_pointer_type(ty.ptr_type(AddressSpace::default()), llvm_usize) + } + /// Creates a [`ShapeEntryType`] from a [`PointerType`] representing an `ShapeEntry`. #[must_use] - pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + pub fn from_pointer_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); Self { ty: ptr_ty, llvm_usize } @@ -117,9 +116,27 @@ impl<'ctx> ShapeEntryType<'ctx> { /// Converts an existing value into a [`ShapeEntryValue`]. #[must_use] - pub fn map_value( + pub fn map_struct_value( &self, - value: <>::Value as ProxyValue<'ctx>>::Base, + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + value: StructValue<'ctx>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_struct_value( + generator, + ctx, + value, + self.llvm_usize, + name, + ) + } + + /// Converts an existing value into a [`ShapeEntryValue`]. + #[must_use] + pub fn map_pointer_value( + &self, + value: PointerValue<'ctx>, name: Option<&'ctx str>, ) -> >::Value { >::Value::from_pointer_value(value, self.llvm_usize, name) @@ -173,6 +190,14 @@ impl<'ctx> ProxyType<'ctx> for ShapeEntryType<'ctx> { } } +impl<'ctx> StructProxyType<'ctx> for ShapeEntryType<'ctx> { + type StructFields = ShapeEntryStructFields<'ctx>; + + fn get_fields(&self) -> Self::StructFields { + Self::fields(self.ty.get_context(), self.llvm_usize) + } +} + impl<'ctx> From> for PointerType<'ctx> { fn from(value: ShapeEntryType<'ctx>) -> Self { value.as_base_type() diff --git a/nac3core/src/codegen/types/ndarray/contiguous.rs b/nac3core/src/codegen/types/ndarray/contiguous.rs index 40311a57..1857536a 100644 --- a/nac3core/src/codegen/types/ndarray/contiguous.rs +++ b/nac3core/src/codegen/types/ndarray/contiguous.rs @@ -1,7 +1,7 @@ use inkwell::{ context::Context, - types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType}, - values::{IntValue, PointerValue}, + types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType, StructType}, + values::{IntValue, PointerValue, StructValue}, AddressSpace, }; use itertools::Itertools; @@ -13,10 +13,11 @@ use crate::{ types::{ structure::{ check_struct_type_matches_fields, FieldIndexCounter, StructField, StructFields, + StructProxyType, }, ProxyType, }, - values::{ndarray::ContiguousNDArrayValue, ProxyValue}, + values::ndarray::ContiguousNDArrayValue, CodeGenContext, CodeGenerator, }, toplevel::numpy::unpack_ndarray_var_tys, @@ -67,13 +68,6 @@ impl<'ctx> ContiguousNDArrayType<'ctx> { ContiguousNDArrayStructFields::new_typed(item, llvm_usize) } - /// See [`NDArrayType::fields`]. - // TODO: Move this into e.g. StructProxyType - #[must_use] - pub fn get_fields(&self) -> ContiguousNDArrayStructFields<'ctx> { - Self::fields(self.item, self.llvm_usize) - } - /// Creates an LLVM type corresponding to the expected structure of an `NDArray`. #[must_use] fn llvm_type( @@ -123,9 +117,19 @@ impl<'ctx> ContiguousNDArrayType<'ctx> { Self::new_impl(ctx.ctx, llvm_dtype, ctx.get_size_type()) } + /// Creates an [`ContiguousNDArrayType`] from a [`StructType`] representing an `NDArray`. + #[must_use] + pub fn from_struct_type( + ty: StructType<'ctx>, + item: BasicTypeEnum<'ctx>, + llvm_usize: IntType<'ctx>, + ) -> Self { + Self::from_pointer_type(ty.ptr_type(AddressSpace::default()), item, llvm_usize) + } + /// Creates an [`ContiguousNDArrayType`] from a [`PointerType`] representing an `NDArray`. #[must_use] - pub fn from_type( + pub fn from_pointer_type( ptr_ty: PointerType<'ctx>, item: BasicTypeEnum<'ctx>, llvm_usize: IntType<'ctx>, @@ -174,9 +178,28 @@ impl<'ctx> ContiguousNDArrayType<'ctx> { /// Converts an existing value into a [`ContiguousNDArrayValue`]. #[must_use] - pub fn map_value( + pub fn map_struct_value( &self, - value: <>::Value as ProxyValue<'ctx>>::Base, + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + value: StructValue<'ctx>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_struct_value( + generator, + ctx, + value, + self.item, + self.llvm_usize, + name, + ) + } + + /// Converts an existing value into a [`ContiguousNDArrayValue`]. + #[must_use] + pub fn map_pointer_value( + &self, + value: PointerValue<'ctx>, name: Option<&'ctx str>, ) -> >::Value { >::Value::from_pointer_value( @@ -243,6 +266,14 @@ impl<'ctx> ProxyType<'ctx> for ContiguousNDArrayType<'ctx> { } } +impl<'ctx> StructProxyType<'ctx> for ContiguousNDArrayType<'ctx> { + type StructFields = ContiguousNDArrayStructFields<'ctx>; + + fn get_fields(&self) -> Self::StructFields { + Self::fields(self.item, self.llvm_usize) + } +} + impl<'ctx> From> for PointerType<'ctx> { fn from(value: ContiguousNDArrayType<'ctx>) -> Self { value.as_base_type() diff --git a/nac3core/src/codegen/types/ndarray/indexing.rs b/nac3core/src/codegen/types/ndarray/indexing.rs index ec214ceb..d00e0fb3 100644 --- a/nac3core/src/codegen/types/ndarray/indexing.rs +++ b/nac3core/src/codegen/types/ndarray/indexing.rs @@ -1,7 +1,7 @@ use inkwell::{ context::{AsContextRef, Context}, - types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType}, - values::{IntValue, PointerValue}, + types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType, StructType}, + values::{IntValue, PointerValue, StructValue}, AddressSpace, }; use itertools::Itertools; @@ -10,12 +10,12 @@ use nac3core_derive::StructFields; use crate::codegen::{ types::{ - structure::{check_struct_type_matches_fields, StructField, StructFields}, + structure::{check_struct_type_matches_fields, StructField, StructFields, StructProxyType}, ProxyType, }, values::{ ndarray::{NDIndexValue, RustNDIndex}, - ArrayLikeIndexer, ArraySliceValue, ProxyValue, + ArrayLikeIndexer, ArraySliceValue, }, CodeGenContext, CodeGenerator, }; @@ -43,11 +43,6 @@ impl<'ctx> NDIndexType<'ctx> { NDIndexStructFields::new(ctx, llvm_usize) } - #[must_use] - pub fn get_fields(&self) -> NDIndexStructFields<'ctx> { - Self::fields(self.ty.get_context(), self.llvm_usize) - } - #[must_use] fn llvm_type(ctx: &'ctx Context, llvm_usize: IntType<'ctx>) -> PointerType<'ctx> { let field_tys = @@ -76,7 +71,12 @@ impl<'ctx> NDIndexType<'ctx> { } #[must_use] - pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + pub fn from_struct_type(ty: StructType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + Self::from_pointer_type(ty.ptr_type(AddressSpace::default()), llvm_usize) + } + + #[must_use] + pub fn from_pointer_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); Self { ty: ptr_ty, llvm_usize } @@ -148,9 +148,26 @@ impl<'ctx> NDIndexType<'ctx> { } #[must_use] - pub fn map_value( + pub fn map_struct_value( &self, - value: <>::Value as ProxyValue<'ctx>>::Base, + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + value: StructValue<'ctx>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_struct_value( + generator, + ctx, + value, + self.llvm_usize, + name, + ) + } + + #[must_use] + pub fn map_pointer_value( + &self, + value: PointerValue<'ctx>, name: Option<&'ctx str>, ) -> >::Value { >::Value::from_pointer_value(value, self.llvm_usize, name) @@ -201,6 +218,14 @@ impl<'ctx> ProxyType<'ctx> for NDIndexType<'ctx> { } } +impl<'ctx> StructProxyType<'ctx> for NDIndexType<'ctx> { + type StructFields = NDIndexStructFields<'ctx>; + + fn get_fields(&self) -> Self::StructFields { + Self::fields(self.ty.get_context(), self.llvm_usize) + } +} + impl<'ctx> From> for PointerType<'ctx> { fn from(value: NDIndexType<'ctx>) -> Self { value.as_base_type() diff --git a/nac3core/src/codegen/types/ndarray/nditer.rs b/nac3core/src/codegen/types/ndarray/nditer.rs index ba21a7ea..aec1a6f5 100644 --- a/nac3core/src/codegen/types/ndarray/nditer.rs +++ b/nac3core/src/codegen/types/ndarray/nditer.rs @@ -1,7 +1,7 @@ use inkwell::{ context::{AsContextRef, Context}, - types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType}, - values::{IntValue, PointerValue}, + types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType, StructType}, + values::{IntValue, PointerValue, StructValue}, AddressSpace, }; use itertools::Itertools; @@ -11,7 +11,9 @@ use nac3core_derive::StructFields; use super::ProxyType; use crate::codegen::{ irrt, - types::structure::{check_struct_type_matches_fields, StructField, StructFields}, + types::structure::{ + check_struct_type_matches_fields, StructField, StructFields, StructProxyType, + }, values::{ ndarray::{NDArrayValue, NDIterValue}, ArrayLikeValue, ArraySliceValue, ProxyValue, TypedArrayLikeAdapter, @@ -50,13 +52,6 @@ impl<'ctx> NDIterType<'ctx> { NDIterStructFields::new(ctx, llvm_usize) } - /// See [`NDIterType::fields`]. - // TODO: Move this into e.g. StructProxyType - #[must_use] - pub fn get_fields(&self, ctx: impl AsContextRef<'ctx>) -> NDIterStructFields<'ctx> { - Self::fields(ctx, self.llvm_usize) - } - /// Creates an LLVM type corresponding to the expected structure of an `NDIter`. #[must_use] fn llvm_type(ctx: &'ctx Context, llvm_usize: IntType<'ctx>) -> PointerType<'ctx> { @@ -87,9 +82,15 @@ impl<'ctx> NDIterType<'ctx> { Self::new_impl(ctx, generator.get_size_type(ctx)) } + /// Creates an [`NDIterType`] from a [`StructType`] representing an `NDIter`. + #[must_use] + pub fn from_struct_type(ty: StructType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + Self::from_pointer_type(ty.ptr_type(AddressSpace::default()), llvm_usize) + } + /// Creates an [`NDIterType`] from a [`PointerType`] representing an `NDIter`. #[must_use] - pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + pub fn from_pointer_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); Self { ty: ptr_ty, llvm_usize } @@ -159,7 +160,8 @@ impl<'ctx> NDIterType<'ctx> { let indices = TypedArrayLikeAdapter::from(indices, |_, _, v| v.into_int_value(), |_, _, v| v.into()); - let nditer = self.map_value(nditer, ndarray, indices.as_slice_value(ctx, generator), None); + let nditer = + self.map_pointer_value(nditer, ndarray, indices.as_slice_value(ctx, generator), None); irrt::ndarray::call_nac3_nditer_initialize(generator, ctx, nditer, ndarray, &indices); @@ -167,9 +169,30 @@ impl<'ctx> NDIterType<'ctx> { } #[must_use] - pub fn map_value( + pub fn map_struct_value( &self, - value: <>::Value as ProxyValue<'ctx>>::Base, + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + value: StructValue<'ctx>, + parent: NDArrayValue<'ctx>, + indices: ArraySliceValue<'ctx>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_struct_value( + generator, + ctx, + value, + parent, + indices, + self.llvm_usize, + name, + ) + } + + #[must_use] + pub fn map_pointer_value( + &self, + value: PointerValue<'ctx>, parent: NDArrayValue<'ctx>, indices: ArraySliceValue<'ctx>, name: Option<&'ctx str>, @@ -229,6 +252,14 @@ impl<'ctx> ProxyType<'ctx> for NDIterType<'ctx> { } } +impl<'ctx> StructProxyType<'ctx> for NDIterType<'ctx> { + type StructFields = NDIterStructFields<'ctx>; + + fn get_fields(&self) -> Self::StructFields { + Self::fields(self.ty.get_context(), self.llvm_usize) + } +} + impl<'ctx> From> for PointerType<'ctx> { fn from(value: NDIterType<'ctx>) -> Self { value.as_base_type() diff --git a/nac3core/src/codegen/types/range.rs b/nac3core/src/codegen/types/range.rs index b6f15c70..e8f6f4d5 100644 --- a/nac3core/src/codegen/types/range.rs +++ b/nac3core/src/codegen/types/range.rs @@ -1,13 +1,14 @@ use inkwell::{ context::Context, - types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType}, + types::{AnyTypeEnum, ArrayType, BasicType, BasicTypeEnum, IntType, PointerType}, + values::{ArrayValue, PointerValue}, AddressSpace, }; use super::ProxyType; use crate::{ codegen::{ - values::{ProxyValue, RangeValue}, + values::RangeValue, {CodeGenContext, CodeGenerator}, }, typecheck::typedef::{Type, TypeEnum}, @@ -61,9 +62,15 @@ impl<'ctx> RangeType<'ctx> { Self::new(ctx) } + /// Creates an [`RangeType`] from a [`ArrayType`]. + #[must_use] + pub fn from_array_type(arr_ty: ArrayType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + Self::from_pointer_type(arr_ty.ptr_type(AddressSpace::default()), llvm_usize) + } + /// Creates an [`RangeType`] from a [`PointerType`]. #[must_use] - pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + pub fn from_pointer_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { debug_assert!(Self::has_same_repr(ptr_ty, llvm_usize).is_ok()); RangeType { ty: ptr_ty, llvm_usize } @@ -110,9 +117,27 @@ impl<'ctx> RangeType<'ctx> { /// Converts an existing value into a [`RangeValue`]. #[must_use] - pub fn map_value( + pub fn map_array_value( &self, - value: <>::Value as ProxyValue<'ctx>>::Base, + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + value: ArrayValue<'ctx>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_array_value( + generator, + ctx, + value, + self.llvm_usize, + name, + ) + } + + /// Converts an existing value into a [`RangeValue`]. + #[must_use] + pub fn map_pointer_value( + &self, + value: PointerValue<'ctx>, name: Option<&'ctx str>, ) -> >::Value { >::Value::from_pointer_value(value, self.llvm_usize, name) diff --git a/nac3core/src/codegen/types/tuple.rs b/nac3core/src/codegen/types/tuple.rs index 29e93233..52711bf3 100644 --- a/nac3core/src/codegen/types/tuple.rs +++ b/nac3core/src/codegen/types/tuple.rs @@ -1,14 +1,14 @@ use inkwell::{ context::Context, - types::{BasicType, BasicTypeEnum, IntType, StructType}, - values::BasicValueEnum, + types::{BasicType, BasicTypeEnum, IntType, PointerType, StructType}, + values::{BasicValueEnum, PointerValue, StructValue}, }; use itertools::Itertools; use super::ProxyType; use crate::{ codegen::{ - values::{ProxyValue, TupleValue}, + values::TupleValue, CodeGenContext, CodeGenerator, }, typecheck::typedef::{Type, TypeEnum}, @@ -77,12 +77,18 @@ impl<'ctx> TupleType<'ctx> { /// Creates an [`TupleType`] from a [`StructType`]. #[must_use] - pub fn from_type(struct_ty: StructType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + pub fn from_struct_type(struct_ty: StructType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { debug_assert!(Self::has_same_repr(struct_ty, llvm_usize).is_ok()); TupleType { ty: struct_ty, llvm_usize } } + /// Creates an [`TupleType`] from a [`PointerType`]. + #[must_use] + pub fn from_pointer_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self { + Self::from_struct_type(ptr_ty.get_element_type().into_struct_type(), llvm_usize) + } + /// Returns the number of elements present in this [`TupleType`]. #[must_use] pub fn num_elements(&self) -> u32 { @@ -117,7 +123,10 @@ impl<'ctx> TupleType<'ctx> { ctx: &CodeGenContext<'ctx, '_>, name: Option<&'ctx str>, ) -> >::Value { - self.map_value(Self::llvm_type(ctx.ctx, &self.ty.get_field_types()).const_zero(), name) + self.map_struct_value( + Self::llvm_type(ctx.ctx, &self.ty.get_field_types()).const_zero(), + name, + ) } /// Constructs a [`TupleValue`] from `objects`. The resulting tuple preserves the order of @@ -147,13 +156,24 @@ impl<'ctx> TupleType<'ctx> { /// Converts an existing value into a [`ListValue`]. #[must_use] - pub fn map_value( + pub fn map_struct_value( &self, - value: <>::Value as ProxyValue<'ctx>>::Base, + value: StructValue<'ctx>, name: Option<&'ctx str>, ) -> >::Value { >::Value::from_struct_value(value, self.llvm_usize, name) } + + /// Converts an existing value into a [`TupleValue`]. + #[must_use] + pub fn map_pointer_value( + &self, + ctx: &CodeGenContext<'ctx, '_>, + value: PointerValue<'ctx>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_pointer_value(ctx, value, self.llvm_usize, name) + } } impl<'ctx> ProxyType<'ctx> for TupleType<'ctx> { diff --git a/nac3core/src/codegen/types/utils/slice.rs b/nac3core/src/codegen/types/utils/slice.rs index e482ed5b..e43ac743 100644 --- a/nac3core/src/codegen/types/utils/slice.rs +++ b/nac3core/src/codegen/types/utils/slice.rs @@ -1,7 +1,7 @@ use inkwell::{ context::{AsContextRef, Context, ContextRef}, - types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType}, - values::IntValue, + types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType, StructType}, + values::{IntValue, PointerValue, StructValue}, AddressSpace, }; use itertools::Itertools; @@ -12,10 +12,11 @@ use crate::codegen::{ types::{ structure::{ check_struct_type_matches_fields, FieldIndexCounter, StructField, StructFields, + StructProxyType, }, ProxyType, }, - values::{utils::SliceValue, ProxyValue}, + values::utils::SliceValue, CodeGenContext, CodeGenerator, }; @@ -27,7 +28,7 @@ pub struct SliceType<'ctx> { } #[derive(PartialEq, Eq, Clone, Copy, StructFields)] -pub struct SliceFields<'ctx> { +pub struct SliceStructFields<'ctx> { #[value_type(bool_type())] pub start_defined: StructField<'ctx, IntValue<'ctx>>, #[value_type(usize)] @@ -42,14 +43,14 @@ pub struct SliceFields<'ctx> { pub step: StructField<'ctx, IntValue<'ctx>>, } -impl<'ctx> SliceFields<'ctx> { - /// Creates a new instance of [`SliceFields`] with a custom integer type for its range values. +impl<'ctx> SliceStructFields<'ctx> { + /// Creates a new instance of [`SliceStructFields`] with a custom integer type for its range values. #[must_use] pub fn new_sized(ctx: &impl AsContextRef<'ctx>, int_ty: IntType<'ctx>) -> Self { let ctx = unsafe { ContextRef::new(ctx.as_ctx_ref()) }; let mut counter = FieldIndexCounter::default(); - SliceFields { + SliceStructFields { start_defined: StructField::create(&mut counter, "start_defined", ctx.bool_type()), start: StructField::create(&mut counter, "start", int_ty), stop_defined: StructField::create(&mut counter, "stop_defined", ctx.bool_type()), @@ -61,16 +62,10 @@ impl<'ctx> SliceFields<'ctx> { } impl<'ctx> SliceType<'ctx> { - // TODO: Move this into e.g. StructProxyType - #[must_use] - pub fn get_fields(&self) -> SliceFields<'ctx> { - SliceFields::new_sized(&self.int_ty.get_context(), self.int_ty) - } - /// Creates an LLVM type corresponding to the expected structure of a `Slice`. #[must_use] fn llvm_type(ctx: &'ctx Context, int_ty: IntType<'ctx>) -> PointerType<'ctx> { - let field_tys = SliceFields::new_sized(&int_ty.get_context(), int_ty) + let field_tys = SliceStructFields::new_sized(&int_ty.get_context(), int_ty) .into_iter() .map(|field| field.1) .collect_vec(); @@ -90,6 +85,16 @@ impl<'ctx> SliceType<'ctx> { Self::new_impl(ctx.ctx, int_ty, ctx.get_size_type()) } + /// Creates an instance of [`SliceType`] with `int_ty` as its backing integer type. + #[must_use] + pub fn new_with_generator( + generator: &G, + ctx: &'ctx Context, + int_ty: IntType<'ctx>, + ) -> Self { + Self::new_impl(ctx, int_ty, generator.get_size_type(ctx)) + } + /// Creates an instance of [`SliceType`] with `usize` as its backing integer type. #[must_use] pub fn new_usize(ctx: &CodeGenContext<'ctx, '_>) -> Self { @@ -105,9 +110,19 @@ impl<'ctx> SliceType<'ctx> { Self::new_impl(ctx, generator.get_size_type(ctx), generator.get_size_type(ctx)) } + /// Creates an [`SliceType`] from a [`StructType`] representing a `slice`. + #[must_use] + pub fn from_struct_type( + ty: StructType<'ctx>, + int_ty: IntType<'ctx>, + llvm_usize: IntType<'ctx>, + ) -> Self { + Self::from_pointer_type(ty.ptr_type(AddressSpace::default()), int_ty, llvm_usize) + } + /// Creates an [`SliceType`] from a [`PointerType`] representing a `slice`. #[must_use] - pub fn from_type( + pub fn from_pointer_type( ptr_ty: PointerType<'ctx>, int_ty: IntType<'ctx>, llvm_usize: IntType<'ctx>, @@ -157,11 +172,30 @@ impl<'ctx> SliceType<'ctx> { ) } + /// Converts an existing value into a [`SliceValue`]. + #[must_use] + pub fn map_struct_value( + &self, + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + value: StructValue<'ctx>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_struct_value( + generator, + ctx, + value, + self.int_ty, + self.llvm_usize, + name, + ) + } + /// Converts an existing value into a [`ContiguousNDArrayValue`]. #[must_use] - pub fn map_value( + pub fn map_pointer_value( &self, - value: <>::Value as ProxyValue<'ctx>>::Base, + value: PointerValue<'ctx>, name: Option<&'ctx str>, ) -> >::Value { >::Value::from_pointer_value( @@ -192,7 +226,7 @@ impl<'ctx> ProxyType<'ctx> for SliceType<'ctx> { fn has_same_repr(ty: Self::Base, llvm_usize: IntType<'ctx>) -> Result<(), String> { let ctx = ty.get_context(); - let fields = SliceFields::new(ctx, llvm_usize); + let fields = SliceStructFields::new(ctx, llvm_usize); let llvm_ty = ty.get_element_type(); let AnyTypeEnum::StructType(llvm_ty) = llvm_ty else { @@ -242,6 +276,14 @@ impl<'ctx> ProxyType<'ctx> for SliceType<'ctx> { } } +impl<'ctx> StructProxyType<'ctx> for SliceType<'ctx> { + type StructFields = SliceStructFields<'ctx>; + + fn get_fields(&self) -> Self::StructFields { + SliceStructFields::new_sized(&self.ty.get_context(), self.int_ty) + } +} + impl<'ctx> From> for PointerType<'ctx> { fn from(value: SliceType<'ctx>) -> Self { value.as_base_type() diff --git a/nac3core/src/codegen/values/list.rs b/nac3core/src/codegen/values/list.rs index cdd1a416..453065b8 100644 --- a/nac3core/src/codegen/values/list.rs +++ b/nac3core/src/codegen/values/list.rs @@ -1,14 +1,18 @@ use inkwell::{ types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType}, - values::{BasicValueEnum, IntValue, PointerValue}, + values::{BasicValueEnum, IntValue, PointerValue, StructValue}, AddressSpace, IntPredicate, }; use super::{ - ArrayLikeIndexer, ArrayLikeValue, ProxyValue, UntypedArrayLikeAccessor, UntypedArrayLikeMutator, + structure::StructProxyValue, ArrayLikeIndexer, ArrayLikeValue, ProxyValue, + UntypedArrayLikeAccessor, UntypedArrayLikeMutator, }; use crate::codegen::{ - types::{structure::StructField, ListType, ProxyType}, + types::{ + structure::{StructField, StructProxyType}, + ListType, ProxyType, + }, {CodeGenContext, CodeGenerator}, }; @@ -21,6 +25,26 @@ pub struct ListValue<'ctx> { } impl<'ctx> ListValue<'ctx> { + /// Creates an [`ListValue`] from a [`PointerValue`]. + #[must_use] + pub fn from_struct_value( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + val: StructValue<'ctx>, + llvm_usize: IntType<'ctx>, + name: Option<&'ctx str>, + ) -> Self { + let pval = generator + .gen_var_alloc( + ctx, + val.get_type().into(), + name.map(|name| format!("{name}.addr")).as_deref(), + ) + .unwrap(); + ctx.builder.build_store(pval, val).unwrap(); + Self::from_pointer_value(pval, llvm_usize, name) + } + /// Creates an [`ListValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -33,19 +57,13 @@ impl<'ctx> ListValue<'ctx> { ListValue { value: ptr, llvm_usize, name } } - fn items_field(&self, ctx: &CodeGenContext<'ctx, '_>) -> StructField<'ctx, PointerValue<'ctx>> { - self.get_type().get_fields(&ctx.ctx).items - } - - /// Returns the double-indirection pointer to the `data` array, as if by calling `getelementptr` - /// on the field. - fn pptr_to_data(&self, ctx: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> { - self.items_field(ctx).ptr_by_gep(ctx, self.value, self.name) + fn items_field(&self) -> StructField<'ctx, PointerValue<'ctx>> { + self.get_type().get_fields().items } /// Stores the array of data elements `data` into this instance. fn store_data(&self, ctx: &CodeGenContext<'ctx, '_>, data: PointerValue<'ctx>) { - self.items_field(ctx).store(ctx, self.value, data, self.name); + self.items_field().store(ctx, self.value, data, self.name); } /// Convenience method for creating a new array storing data elements with the given element @@ -83,15 +101,15 @@ impl<'ctx> ListValue<'ctx> { ListDataProxy(self) } - fn len_field(&self, ctx: &CodeGenContext<'ctx, '_>) -> StructField<'ctx, IntValue<'ctx>> { - self.get_type().get_fields(&ctx.ctx).len + fn len_field(&self) -> StructField<'ctx, IntValue<'ctx>> { + self.get_type().get_fields().len } /// Stores the `size` of this `list` into this instance. pub fn store_size(&self, ctx: &CodeGenContext<'ctx, '_>, size: IntValue<'ctx>) { debug_assert_eq!(size.get_type(), ctx.get_size_type()); - self.len_field(ctx).store(ctx, self.value, size, self.name); + self.len_field().store(ctx, self.value, size, self.name); } /// Returns the size of this `list` as a value. @@ -100,7 +118,7 @@ impl<'ctx> ListValue<'ctx> { ctx: &CodeGenContext<'ctx, '_>, name: Option<&'ctx str>, ) -> IntValue<'ctx> { - self.len_field(ctx).load(ctx, self.value, name) + self.len_field().load(ctx, self.value, name) } /// Returns an instance of [`ListValue`] with the `items` pointer cast to `i8*`. @@ -123,7 +141,7 @@ impl<'ctx> ProxyValue<'ctx> for ListValue<'ctx> { type Type = ListType<'ctx>; fn get_type(&self) -> Self::Type { - ListType::from_type(self.as_base_value().get_type(), self.llvm_usize) + ListType::from_pointer_type(self.as_base_value().get_type(), self.llvm_usize) } fn as_base_value(&self) -> Self::Base { @@ -135,6 +153,8 @@ impl<'ctx> ProxyValue<'ctx> for ListValue<'ctx> { } } +impl<'ctx> StructProxyValue<'ctx> for ListValue<'ctx> {} + impl<'ctx> From> for PointerValue<'ctx> { fn from(value: ListValue<'ctx>) -> Self { value.as_base_value() @@ -159,12 +179,7 @@ impl<'ctx> ArrayLikeValue<'ctx> for ListDataProxy<'ctx, '_> { ctx: &CodeGenContext<'ctx, '_>, _: &G, ) -> PointerValue<'ctx> { - let var_name = self.0.name.map(|v| format!("{v}.data")).unwrap_or_default(); - - ctx.builder - .build_load(self.0.pptr_to_data(ctx), var_name.as_str()) - .map(BasicValueEnum::into_pointer_value) - .unwrap() + self.0.items_field().load(ctx, self.0.value, self.0.name) } fn size( diff --git a/nac3core/src/codegen/values/ndarray/broadcast.rs b/nac3core/src/codegen/values/ndarray/broadcast.rs index e30bfae2..4935a364 100644 --- a/nac3core/src/codegen/values/ndarray/broadcast.rs +++ b/nac3core/src/codegen/values/ndarray/broadcast.rs @@ -1,6 +1,6 @@ use inkwell::{ types::IntType, - values::{IntValue, PointerValue}, + values::{IntValue, PointerValue, StructValue}, }; use itertools::Itertools; @@ -8,12 +8,13 @@ use crate::codegen::{ irrt, types::{ ndarray::{NDArrayType, ShapeEntryType}, - structure::StructField, + structure::{StructField, StructProxyType}, ProxyType, }, values::{ - ndarray::NDArrayValue, ArrayLikeIndexer, ArrayLikeValue, ArraySliceValue, ProxyValue, - TypedArrayLikeAccessor, TypedArrayLikeAdapter, TypedArrayLikeMutator, + ndarray::NDArrayValue, structure::StructProxyValue, ArrayLikeIndexer, ArrayLikeValue, + ArraySliceValue, ProxyValue, TypedArrayLikeAccessor, TypedArrayLikeAdapter, + TypedArrayLikeMutator, }, CodeGenContext, CodeGenerator, }; @@ -26,6 +27,26 @@ pub struct ShapeEntryValue<'ctx> { } impl<'ctx> ShapeEntryValue<'ctx> { + /// Creates an [`ShapeEntryValue`] from a [`StructValue`]. + #[must_use] + pub fn from_struct_value( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + val: StructValue<'ctx>, + llvm_usize: IntType<'ctx>, + name: Option<&'ctx str>, + ) -> Self { + let pval = generator + .gen_var_alloc( + ctx, + val.get_type().into(), + name.map(|name| format!("{name}.addr")).as_deref(), + ) + .unwrap(); + ctx.builder.build_store(pval, val).unwrap(); + Self::from_pointer_value(pval, llvm_usize, name) + } + /// Creates an [`ShapeEntryValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -39,7 +60,7 @@ impl<'ctx> ShapeEntryValue<'ctx> { } fn ndims_field(&self) -> StructField<'ctx, IntValue<'ctx>> { - self.get_type().get_fields(self.value.get_type().get_context()).ndims + self.get_type().get_fields().ndims } /// Stores the number of dimensions into this value. @@ -48,7 +69,7 @@ impl<'ctx> ShapeEntryValue<'ctx> { } fn shape_field(&self) -> StructField<'ctx, PointerValue<'ctx>> { - self.get_type().get_fields(self.value.get_type().get_context()).shape + self.get_type().get_fields().shape } /// Stores the shape into this value. @@ -63,7 +84,7 @@ impl<'ctx> ProxyValue<'ctx> for ShapeEntryValue<'ctx> { type Type = ShapeEntryType<'ctx>; fn get_type(&self) -> Self::Type { - Self::Type::from_type(self.value.get_type(), self.llvm_usize) + Self::Type::from_pointer_type(self.value.get_type(), self.llvm_usize) } fn as_base_value(&self) -> Self::Base { @@ -75,6 +96,8 @@ impl<'ctx> ProxyValue<'ctx> for ShapeEntryValue<'ctx> { } } +impl<'ctx> StructProxyValue<'ctx> for ShapeEntryValue<'ctx> {} + impl<'ctx> From> for PointerValue<'ctx> { fn from(value: ShapeEntryValue<'ctx>) -> Self { value.as_base_value() @@ -163,7 +186,7 @@ fn broadcast_shapes<'ctx, G, Shape>( None, ) }; - let shape_entry = llvm_shape_ty.map_value(pshape_entry, None); + let shape_entry = llvm_shape_ty.map_pointer_value(pshape_entry, None); let in_ndims = llvm_usize.const_int(*in_ndims, false); shape_entry.store_ndims(ctx, in_ndims); diff --git a/nac3core/src/codegen/values/ndarray/contiguous.rs b/nac3core/src/codegen/values/ndarray/contiguous.rs index b8bf0afa..16efd0a0 100644 --- a/nac3core/src/codegen/values/ndarray/contiguous.rs +++ b/nac3core/src/codegen/values/ndarray/contiguous.rs @@ -1,16 +1,17 @@ use inkwell::{ types::{BasicType, BasicTypeEnum, IntType}, - values::{IntValue, PointerValue}, + values::{IntValue, PointerValue, StructValue}, AddressSpace, }; -use super::{ArrayLikeValue, NDArrayValue, ProxyValue}; +use super::NDArrayValue; use crate::codegen::{ stmt::gen_if_callback, types::{ ndarray::{ContiguousNDArrayType, NDArrayType}, - structure::StructField, + structure::{StructField, StructProxyType}, }, + values::{structure::StructProxyValue, ArrayLikeValue, ProxyValue}, CodeGenContext, CodeGenerator, }; @@ -23,6 +24,27 @@ pub struct ContiguousNDArrayValue<'ctx> { } impl<'ctx> ContiguousNDArrayValue<'ctx> { + /// Creates an [`ContiguousNDArrayValue`] from a [`StructValue`]. + #[must_use] + pub fn from_struct_value( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + val: StructValue<'ctx>, + dtype: BasicTypeEnum<'ctx>, + llvm_usize: IntType<'ctx>, + name: Option<&'ctx str>, + ) -> Self { + let pval = generator + .gen_var_alloc( + ctx, + val.get_type().into(), + name.map(|name| format!("{name}.addr")).as_deref(), + ) + .unwrap(); + ctx.builder.build_store(pval, val).unwrap(); + Self::from_pointer_value(pval, dtype, llvm_usize, name) + } + /// Creates an [`ContiguousNDArrayValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -75,7 +97,7 @@ impl<'ctx> ProxyValue<'ctx> for ContiguousNDArrayValue<'ctx> { type Type = ContiguousNDArrayType<'ctx>; fn get_type(&self) -> Self::Type { - >::Type::from_type( + >::Type::from_pointer_type( self.as_base_value().get_type(), self.item, self.llvm_usize, @@ -91,6 +113,8 @@ impl<'ctx> ProxyValue<'ctx> for ContiguousNDArrayValue<'ctx> { } } +impl<'ctx> StructProxyValue<'ctx> for ContiguousNDArrayValue<'ctx> {} + impl<'ctx> From> for PointerValue<'ctx> { fn from(value: ContiguousNDArrayValue<'ctx>) -> Self { value.as_base_value() diff --git a/nac3core/src/codegen/values/ndarray/indexing.rs b/nac3core/src/codegen/values/ndarray/indexing.rs index 49fdfe17..6ed0ed0b 100644 --- a/nac3core/src/codegen/values/ndarray/indexing.rs +++ b/nac3core/src/codegen/values/ndarray/indexing.rs @@ -1,6 +1,6 @@ use inkwell::{ types::IntType, - values::{IntValue, PointerValue}, + values::{IntValue, PointerValue, StructValue}, AddressSpace, }; use itertools::Itertools; @@ -12,10 +12,12 @@ use crate::{ irrt, types::{ ndarray::{NDArrayType, NDIndexType}, - structure::StructField, + structure::{StructField, StructProxyType}, utils::SliceType, }, - values::{ndarray::NDArrayValue, utils::RustSlice, ProxyValue}, + values::{ + ndarray::NDArrayValue, structure::StructProxyValue, utils::RustSlice, ProxyValue, + }, CodeGenContext, CodeGenerator, }, typecheck::typedef::Type, @@ -30,6 +32,26 @@ pub struct NDIndexValue<'ctx> { } impl<'ctx> NDIndexValue<'ctx> { + /// Creates an [`NDIndexValue`] from a [`StructValue`]. + #[must_use] + pub fn from_struct_value( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + val: StructValue<'ctx>, + llvm_usize: IntType<'ctx>, + name: Option<&'ctx str>, + ) -> Self { + let pval = generator + .gen_var_alloc( + ctx, + val.get_type().into(), + name.map(|name| format!("{name}.addr")).as_deref(), + ) + .unwrap(); + ctx.builder.build_store(pval, val).unwrap(); + Self::from_pointer_value(pval, llvm_usize, name) + } + /// Creates an [`NDIndexValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -73,7 +95,7 @@ impl<'ctx> ProxyValue<'ctx> for NDIndexValue<'ctx> { type Type = NDIndexType<'ctx>; fn get_type(&self) -> Self::Type { - Self::Type::from_type(self.value.get_type(), self.llvm_usize) + Self::Type::from_pointer_type(self.value.get_type(), self.llvm_usize) } fn as_base_value(&self) -> Self::Base { @@ -85,6 +107,8 @@ impl<'ctx> ProxyValue<'ctx> for NDIndexValue<'ctx> { } } +impl<'ctx> StructProxyValue<'ctx> for NDIndexValue<'ctx> {} + impl<'ctx> From> for PointerValue<'ctx> { fn from(value: NDIndexValue<'ctx>) -> Self { value.as_base_value() diff --git a/nac3core/src/codegen/values/ndarray/nditer.rs b/nac3core/src/codegen/values/ndarray/nditer.rs index e4855743..c1bf7513 100644 --- a/nac3core/src/codegen/values/ndarray/nditer.rs +++ b/nac3core/src/codegen/values/ndarray/nditer.rs @@ -1,15 +1,18 @@ use inkwell::{ types::{BasicType, IntType}, - values::{BasicValueEnum, IntValue, PointerValue}, + values::{BasicValueEnum, IntValue, PointerValue, StructValue}, AddressSpace, }; -use super::{NDArrayValue, ProxyValue}; +use super::NDArrayValue; use crate::codegen::{ irrt, stmt::{gen_for_callback, BreakContinueHooks}, - types::{ndarray::NDIterType, structure::StructField}, - values::{ArraySliceValue, TypedArrayLikeAdapter}, + types::{ + ndarray::NDIterType, + structure::{StructField, StructProxyType}, + }, + values::{structure::StructProxyValue, ArraySliceValue, ProxyValue, TypedArrayLikeAdapter}, CodeGenContext, CodeGenerator, }; @@ -23,6 +26,28 @@ pub struct NDIterValue<'ctx> { } impl<'ctx> NDIterValue<'ctx> { + /// Creates an [`NDArrayValue`] from a [`StructValue`]. + #[must_use] + pub fn from_struct_value( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + val: StructValue<'ctx>, + parent: NDArrayValue<'ctx>, + indices: ArraySliceValue<'ctx>, + llvm_usize: IntType<'ctx>, + name: Option<&'ctx str>, + ) -> Self { + let pval = generator + .gen_var_alloc( + ctx, + val.get_type().into(), + name.map(|name| format!("{name}.addr")).as_deref(), + ) + .unwrap(); + ctx.builder.build_store(pval, val).unwrap(); + Self::from_pointer_value(pval, parent, indices, llvm_usize, name) + } + /// Creates an [`NDArrayValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -56,11 +81,8 @@ impl<'ctx> NDIterValue<'ctx> { irrt::ndarray::call_nac3_nditer_next(ctx, *self); } - fn element_field( - &self, - ctx: &CodeGenContext<'ctx, '_>, - ) -> StructField<'ctx, PointerValue<'ctx>> { - self.get_type().get_fields(ctx.ctx).element + fn element_field(&self) -> StructField<'ctx, PointerValue<'ctx>> { + self.get_type().get_fields().element } /// Get pointer to the current element. @@ -68,7 +90,7 @@ impl<'ctx> NDIterValue<'ctx> { pub fn get_pointer(&self, ctx: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> { let elem_ty = self.parent.dtype; - let p = self.element_field(ctx).load(ctx, self.as_abi_value(ctx), self.name); + let p = self.element_field().load(ctx, self.as_abi_value(ctx), self.name); ctx.builder .build_pointer_cast(p, elem_ty.ptr_type(AddressSpace::default()), "element") .unwrap() @@ -81,14 +103,14 @@ impl<'ctx> NDIterValue<'ctx> { ctx.builder.build_load(p, "value").unwrap() } - fn nth_field(&self, ctx: &CodeGenContext<'ctx, '_>) -> StructField<'ctx, IntValue<'ctx>> { - self.get_type().get_fields(ctx.ctx).nth + fn nth_field(&self) -> StructField<'ctx, IntValue<'ctx>> { + self.get_type().get_fields().nth } /// Get the index of the current element if this ndarray were a flat ndarray. #[must_use] pub fn get_index(&self, ctx: &CodeGenContext<'ctx, '_>) -> IntValue<'ctx> { - self.nth_field(ctx).load(ctx, self.as_abi_value(ctx), self.name) + self.nth_field().load(ctx, self.as_abi_value(ctx), self.name) } /// Get the indices of the current element. @@ -110,7 +132,7 @@ impl<'ctx> ProxyValue<'ctx> for NDIterValue<'ctx> { type Type = NDIterType<'ctx>; fn get_type(&self) -> Self::Type { - NDIterType::from_type(self.as_base_value().get_type(), self.llvm_usize) + NDIterType::from_pointer_type(self.as_base_value().get_type(), self.llvm_usize) } fn as_base_value(&self) -> Self::Base { @@ -122,6 +144,8 @@ impl<'ctx> ProxyValue<'ctx> for NDIterValue<'ctx> { } } +impl<'ctx> StructProxyValue<'ctx> for NDIterValue<'ctx> {} + impl<'ctx> From> for PointerValue<'ctx> { fn from(value: NDIterValue<'ctx>) -> Self { value.as_base_value() diff --git a/nac3core/src/codegen/values/ndarray/shape.rs b/nac3core/src/codegen/values/ndarray/shape.rs index 3ac2795d..b3331b6f 100644 --- a/nac3core/src/codegen/values/ndarray/shape.rs +++ b/nac3core/src/codegen/values/ndarray/shape.rs @@ -42,7 +42,7 @@ pub fn parse_numpy_int_sequence<'ctx, G: CodeGenerator + ?Sized>( // 1. A list of `int32`; e.g., `np.empty([600, 800, 3])` let input_seq = ListType::from_unifier_type(generator, ctx, input_seq_ty) - .map_value(input_seq.into_pointer_value(), None); + .map_pointer_value(input_seq.into_pointer_value(), None); let len = input_seq.load_size(ctx, None); // TODO: Find a way to remove this mid-BB allocation @@ -86,7 +86,7 @@ pub fn parse_numpy_int_sequence<'ctx, G: CodeGenerator + ?Sized>( // 2. A tuple of ints; e.g., `np.empty((600, 800, 3))` let input_seq = TupleType::from_unifier_type(generator, ctx, input_seq_ty) - .map_value(input_seq.into_struct_value(), None); + .map_struct_value(input_seq.into_struct_value(), None); let len = input_seq.get_type().num_elements(); diff --git a/nac3core/src/codegen/values/range.rs b/nac3core/src/codegen/values/range.rs index 20bdba79..67e623a1 100644 --- a/nac3core/src/codegen/values/range.rs +++ b/nac3core/src/codegen/values/range.rs @@ -1,10 +1,10 @@ use inkwell::{ types::IntType, - values::{BasicValueEnum, IntValue, PointerValue}, + values::{ArrayValue, BasicValueEnum, IntValue, PointerValue}, }; use super::ProxyValue; -use crate::codegen::{types::RangeType, CodeGenContext}; +use crate::codegen::{types::RangeType, CodeGenContext, CodeGenerator}; /// Proxy type for accessing a `range` value in LLVM. #[derive(Copy, Clone)] @@ -15,6 +15,26 @@ pub struct RangeValue<'ctx> { } impl<'ctx> RangeValue<'ctx> { + /// Creates an [`RangeValue`] from a [`PointerValue`]. + #[must_use] + pub fn from_array_value( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + val: ArrayValue<'ctx>, + llvm_usize: IntType<'ctx>, + name: Option<&'ctx str>, + ) -> Self { + let pval = generator + .gen_var_alloc( + ctx, + val.get_type().into(), + name.map(|name| format!("{name}.addr")).as_deref(), + ) + .unwrap(); + ctx.builder.build_store(pval, val).unwrap(); + Self::from_pointer_value(pval, llvm_usize, name) + } + /// Creates an [`RangeValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -142,7 +162,7 @@ impl<'ctx> ProxyValue<'ctx> for RangeValue<'ctx> { type Type = RangeType<'ctx>; fn get_type(&self) -> Self::Type { - RangeType::from_type(self.value.get_type(), self.llvm_usize) + RangeType::from_pointer_type(self.value.get_type(), self.llvm_usize) } fn as_base_value(&self) -> Self::Base { diff --git a/nac3core/src/codegen/values/tuple.rs b/nac3core/src/codegen/values/tuple.rs index 08b2b8be..320e2190 100644 --- a/nac3core/src/codegen/values/tuple.rs +++ b/nac3core/src/codegen/values/tuple.rs @@ -1,6 +1,6 @@ use inkwell::{ types::IntType, - values::{BasicValue, BasicValueEnum, StructValue}, + values::{BasicValue, BasicValueEnum, PointerValue, StructValue}, }; use super::ProxyValue; @@ -26,6 +26,24 @@ impl<'ctx> TupleValue<'ctx> { Self { value, llvm_usize, name } } + /// Creates an [`TupleValue`] from a [`PointerValue`]. + #[must_use] + pub fn from_pointer_value( + ctx: &CodeGenContext<'ctx, '_>, + ptr: PointerValue<'ctx>, + llvm_usize: IntType<'ctx>, + name: Option<&'ctx str>, + ) -> Self { + Self::from_struct_value( + ctx.builder + .build_load(ptr, name.unwrap_or_default()) + .map(BasicValueEnum::into_struct_value) + .unwrap(), + llvm_usize, + name, + ) + } + /// Stores a value into the tuple element at the given `index`. pub fn store_element( &mut self, @@ -62,7 +80,7 @@ impl<'ctx> ProxyValue<'ctx> for TupleValue<'ctx> { type Type = TupleType<'ctx>; fn get_type(&self) -> Self::Type { - TupleType::from_type(self.as_base_value().get_type(), self.llvm_usize) + TupleType::from_struct_type(self.as_base_value().get_type(), self.llvm_usize) } fn as_base_value(&self) -> Self::Base { diff --git a/nac3core/src/codegen/values/utils/slice.rs b/nac3core/src/codegen/values/utils/slice.rs index f7739357..549e556d 100644 --- a/nac3core/src/codegen/values/utils/slice.rs +++ b/nac3core/src/codegen/values/utils/slice.rs @@ -1,14 +1,17 @@ use inkwell::{ types::IntType, - values::{IntValue, PointerValue}, + values::{IntValue, PointerValue, StructValue}, }; use nac3parser::ast::Expr; use crate::{ codegen::{ - types::{structure::StructField, utils::SliceType}, - values::ProxyValue, + types::{ + structure::{StructField, StructProxyType}, + utils::SliceType, + }, + values::{structure::StructProxyValue, ProxyValue}, CodeGenContext, CodeGenerator, }, typecheck::typedef::Type, @@ -24,6 +27,27 @@ pub struct SliceValue<'ctx> { } impl<'ctx> SliceValue<'ctx> { + /// Creates an [`SliceValue`] from a [`StructValue`]. + #[must_use] + pub fn from_struct_value( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + val: StructValue<'ctx>, + int_ty: IntType<'ctx>, + llvm_usize: IntType<'ctx>, + name: Option<&'ctx str>, + ) -> Self { + let pval = generator + .gen_var_alloc( + ctx, + val.get_type().into(), + name.map(|name| format!("{name}.addr")).as_deref(), + ) + .unwrap(); + ctx.builder.build_store(pval, val).unwrap(); + Self::from_pointer_value(pval, int_ty, llvm_usize, name) + } + /// Creates an [`SliceValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -155,7 +179,7 @@ impl<'ctx> ProxyValue<'ctx> for SliceValue<'ctx> { type Type = SliceType<'ctx>; fn get_type(&self) -> Self::Type { - Self::Type::from_type(self.value.get_type(), self.int_ty, self.llvm_usize) + Self::Type::from_pointer_type(self.value.get_type(), self.int_ty, self.llvm_usize) } fn as_base_value(&self) -> Self::Base { @@ -167,6 +191,8 @@ impl<'ctx> ProxyValue<'ctx> for SliceValue<'ctx> { } } +impl<'ctx> StructProxyValue<'ctx> for SliceValue<'ctx> {} + impl<'ctx> From> for PointerValue<'ctx> { fn from(value: SliceValue<'ctx>) -> Self { value.as_base_value() diff --git a/nac3core/src/toplevel/builtins.rs b/nac3core/src/toplevel/builtins.rs index 165f64a8..93e1c6b0 100644 --- a/nac3core/src/toplevel/builtins.rs +++ b/nac3core/src/toplevel/builtins.rs @@ -577,7 +577,7 @@ impl<'a> BuiltinBuilder<'a> { let (zelf_ty, zelf) = obj.unwrap(); let zelf = zelf.to_basic_value_enum(ctx, generator, zelf_ty)?.into_pointer_value(); - let zelf = RangeType::new(ctx).map_value(zelf, Some("range")); + let zelf = RangeType::new(ctx).map_pointer_value(zelf, Some("range")); let mut start = None; let mut stop = None;