From 68da9b0ecff29a203bcd9539a204e05130e74420 Mon Sep 17 00:00:00 2001 From: David Mak Date: Mon, 27 Jan 2025 23:23:05 +0800 Subject: [PATCH] [core] codegen: Implement StructProxy on existing proxies --- nac3artiq/src/codegen.rs | 8 +- nac3artiq/src/symbol_resolver.rs | 20 ++-- nac3core/src/codegen/builtin_fns.rs | 59 +++++++----- nac3core/src/codegen/expr.rs | 6 +- nac3core/src/codegen/numpy.rs | 10 +- nac3core/src/codegen/stmt.rs | 4 +- nac3core/src/codegen/types/list.rs | 54 ++++++++--- nac3core/src/codegen/types/ndarray/array.rs | 8 +- .../src/codegen/types/ndarray/broadcast.rs | 53 ++++++++--- .../src/codegen/types/ndarray/contiguous.rs | 57 +++++++++--- .../src/codegen/types/ndarray/indexing.rs | 49 +++++++--- nac3core/src/codegen/types/ndarray/mod.rs | 60 +++++++++--- nac3core/src/codegen/types/ndarray/nditer.rs | 59 +++++++++--- nac3core/src/codegen/types/range.rs | 35 ++++++- nac3core/src/codegen/types/tuple.rs | 37 ++++++-- nac3core/src/codegen/types/utils/slice.rs | 78 ++++++++++++---- nac3core/src/codegen/values/list.rs | 61 +++++++----- .../src/codegen/values/ndarray/broadcast.rs | 39 ++++++-- .../src/codegen/values/ndarray/contiguous.rs | 34 ++++++- .../src/codegen/values/ndarray/indexing.rs | 32 ++++++- nac3core/src/codegen/values/ndarray/mod.rs | 92 +++++++++++-------- nac3core/src/codegen/values/ndarray/nditer.rs | 52 ++++++++--- nac3core/src/codegen/values/ndarray/shape.rs | 4 +- nac3core/src/codegen/values/range.rs | 26 +++++- nac3core/src/codegen/values/tuple.rs | 22 ++++- nac3core/src/codegen/values/utils/slice.rs | 34 ++++++- nac3core/src/toplevel/builtins.rs | 10 +- 27 files changed, 729 insertions(+), 274 deletions(-) diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index 2cc54387..572acccf 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -476,8 +476,8 @@ fn format_rpc_arg<'ctx>( let (elem_ty, ndims) = unpack_ndarray_var_tys(&mut ctx.unifier, arg_ty); let ndims = extract_ndims(&ctx.unifier, ndims); let dtype = ctx.get_llvm_type(generator, elem_ty); - let ndarray = - NDArrayType::new(ctx, dtype, ndims).map_value(arg.into_pointer_value(), None); + let ndarray = NDArrayType::new(ctx, dtype, ndims) + .map_pointer_value(arg.into_pointer_value(), None); let ndims = llvm_usize.const_int(ndims, false); @@ -1383,7 +1383,7 @@ fn polymorphic_print<'ctx>( let (dtype, _) = unpack_ndarray_var_tys(&mut ctx.unifier, ty); let ndarray = NDArrayType::from_unifier_type(generator, ctx, ty) - .map_value(value.into_pointer_value(), None); + .map_pointer_value(value.into_pointer_value(), None); let num_0 = llvm_usize.const_zero(); @@ -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/nac3artiq/src/symbol_resolver.rs b/nac3artiq/src/symbol_resolver.rs index 06a9400c..f14a8eed 100644 --- a/nac3artiq/src/symbol_resolver.rs +++ b/nac3artiq/src/symbol_resolver.rs @@ -16,7 +16,7 @@ use pyo3::{ use super::PrimitivePythonId; use nac3core::{ codegen::{ - types::{ndarray::NDArrayType, ProxyType}, + types::{ndarray::NDArrayType, structure::StructProxyType, ProxyType}, values::ndarray::make_contiguous_strides, CodeGenContext, CodeGenerator, }, @@ -1315,17 +1315,13 @@ impl InnerResolver { .unwrap() }; - let ndarray = llvm_ndarray - .as_abi_type() - .get_element_type() - .into_struct_type() - .const_named_struct(&[ - ndarray_itemsize.into(), - ndarray_ndims.into(), - ndarray_shape.into(), - ndarray_strides.into(), - ndarray_data.into(), - ]); + let ndarray = llvm_ndarray.get_struct_type().const_named_struct(&[ + ndarray_itemsize.into(), + ndarray_ndims.into(), + ndarray_shape.into(), + ndarray_strides.into(), + ndarray_data.into(), + ]); let ndarray_global = ctx.module.add_global( llvm_ndarray.as_abi_type().get_element_type().into_struct_type(), diff --git a/nac3core/src/codegen/builtin_fns.rs b/nac3core/src/codegen/builtin_fns.rs index 20a89d0a..dfb90824 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) } @@ -62,7 +62,7 @@ pub fn call_len<'ctx, G: CodeGenerator + ?Sized>( if *obj_id == ctx.primitives.ndarray.obj_id(&ctx.unifier).unwrap() => { let ndarray = NDArrayType::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(ndarray.len(ctx), llvm_i32, "len") .unwrap() @@ -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() @@ -126,7 +126,8 @@ pub fn call_int32<'ctx, G: CodeGenerator + ?Sized>( if n_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => { let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, n_ty); - let ndarray = NDArrayType::from_unifier_type(generator, ctx, n_ty).map_value(n, None); + let ndarray = + NDArrayType::from_unifier_type(generator, ctx, n_ty).map_pointer_value(n, None); let result = ndarray .map( @@ -186,7 +187,8 @@ pub fn call_int64<'ctx, G: CodeGenerator + ?Sized>( if n_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => { let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, n_ty); - let ndarray = NDArrayType::from_unifier_type(generator, ctx, n_ty).map_value(n, None); + let ndarray = + NDArrayType::from_unifier_type(generator, ctx, n_ty).map_pointer_value(n, None); let result = ndarray .map( @@ -262,7 +264,8 @@ pub fn call_uint32<'ctx, G: CodeGenerator + ?Sized>( if n_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => { let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, n_ty); - let ndarray = NDArrayType::from_unifier_type(generator, ctx, n_ty).map_value(n, None); + let ndarray = + NDArrayType::from_unifier_type(generator, ctx, n_ty).map_pointer_value(n, None); let result = ndarray .map( @@ -327,7 +330,8 @@ pub fn call_uint64<'ctx, G: CodeGenerator + ?Sized>( if n_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => { let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, n_ty); - let ndarray = NDArrayType::from_unifier_type(generator, ctx, n_ty).map_value(n, None); + let ndarray = + NDArrayType::from_unifier_type(generator, ctx, n_ty).map_pointer_value(n, None); let result = ndarray .map( @@ -391,7 +395,8 @@ pub fn call_float<'ctx, G: CodeGenerator + ?Sized>( if n_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => { let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, n_ty); - let ndarray = NDArrayType::from_unifier_type(generator, ctx, n_ty).map_value(n, None); + let ndarray = + NDArrayType::from_unifier_type(generator, ctx, n_ty).map_pointer_value(n, None); let result = ndarray .map( @@ -435,7 +440,8 @@ pub fn call_round<'ctx, G: CodeGenerator + ?Sized>( if n_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => { let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, n_ty); - let ndarray = NDArrayType::from_unifier_type(generator, ctx, n_ty).map_value(n, None); + let ndarray = + NDArrayType::from_unifier_type(generator, ctx, n_ty).map_pointer_value(n, None); let result = ndarray .map( @@ -474,7 +480,8 @@ pub fn call_numpy_round<'ctx, G: CodeGenerator + ?Sized>( if n_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => { let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, n_ty); - let ndarray = NDArrayType::from_unifier_type(generator, ctx, n_ty).map_value(n, None); + let ndarray = + NDArrayType::from_unifier_type(generator, ctx, n_ty).map_pointer_value(n, None); let result = ndarray .map( @@ -536,7 +543,8 @@ pub fn call_bool<'ctx, G: CodeGenerator + ?Sized>( if n_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => { let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, n_ty); - let ndarray = NDArrayType::from_unifier_type(generator, ctx, n_ty).map_value(n, None); + let ndarray = + NDArrayType::from_unifier_type(generator, ctx, n_ty).map_pointer_value(n, None); let result = ndarray .map( @@ -587,7 +595,8 @@ pub fn call_floor<'ctx, G: CodeGenerator + ?Sized>( if n_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => { let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, n_ty); - let ndarray = NDArrayType::from_unifier_type(generator, ctx, n_ty).map_value(n, None); + let ndarray = + NDArrayType::from_unifier_type(generator, ctx, n_ty).map_pointer_value(n, None); let result = ndarray .map( @@ -637,7 +646,8 @@ pub fn call_ceil<'ctx, G: CodeGenerator + ?Sized>( if n_ty.obj_id(&ctx.unifier).is_some_and(|id| id == PrimDef::NDArray.id()) => { let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, n_ty); - let ndarray = NDArrayType::from_unifier_type(generator, ctx, n_ty).map_value(n, None); + let ndarray = + NDArrayType::from_unifier_type(generator, ctx, n_ty).map_pointer_value(n, None); let result = ndarray .map( @@ -858,7 +868,8 @@ pub fn call_numpy_max_min<'ctx, G: CodeGenerator + ?Sized>( { let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, a_ty); - let ndarray = NDArrayType::from_unifier_type(generator, ctx, a_ty).map_value(n, None); + let ndarray = + NDArrayType::from_unifier_type(generator, ctx, a_ty).map_pointer_value(n, None); let llvm_dtype = ndarray.get_type().element_type(); let zero = llvm_usize.const_zero(); @@ -1638,7 +1649,7 @@ pub fn call_np_linalg_cholesky<'ctx, G: CodeGenerator + ?Sized>( let BasicValueEnum::PointerValue(x1) = x1 else { unsupported_type(ctx, FN_NAME, &[x1_ty]) }; - let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_value(x1, None); + let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_pointer_value(x1, None); if !x1.get_type().element_type().is_float_type() { unsupported_type(ctx, FN_NAME, &[x1_ty]); @@ -1672,7 +1683,7 @@ pub fn call_np_linalg_qr<'ctx, G: CodeGenerator + ?Sized>( let BasicValueEnum::PointerValue(x1) = x1 else { unsupported_type(ctx, FN_NAME, &[x1_ty]) }; - let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_value(x1, None); + let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_pointer_value(x1, None); if !x1.get_type().element_type().is_float_type() { unsupported_type(ctx, FN_NAME, &[x1_ty]); @@ -1727,7 +1738,7 @@ pub fn call_np_linalg_svd<'ctx, G: CodeGenerator + ?Sized>( let BasicValueEnum::PointerValue(x1) = x1 else { unsupported_type(ctx, FN_NAME, &[x1_ty]) }; - let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_value(x1, None); + let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_pointer_value(x1, None); if !x1.get_type().element_type().is_float_type() { unsupported_type(ctx, FN_NAME, &[x1_ty]); @@ -1785,7 +1796,7 @@ pub fn call_np_linalg_inv<'ctx, G: CodeGenerator + ?Sized>( let BasicValueEnum::PointerValue(x1) = x1 else { unsupported_type(ctx, FN_NAME, &[x1_ty]) }; - let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_value(x1, None); + let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_pointer_value(x1, None); if !x1.get_type().element_type().is_float_type() { unsupported_type(ctx, FN_NAME, &[x1_ty]); @@ -1820,7 +1831,7 @@ pub fn call_np_linalg_pinv<'ctx, G: CodeGenerator + ?Sized>( let BasicValueEnum::PointerValue(x1) = x1 else { unsupported_type(ctx, FN_NAME, &[x1_ty]) }; - let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_value(x1, None); + let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_pointer_value(x1, None); if !x1.get_type().element_type().is_float_type() { unsupported_type(ctx, FN_NAME, &[x1_ty]); @@ -1865,7 +1876,7 @@ pub fn call_sp_linalg_lu<'ctx, G: CodeGenerator + ?Sized>( let BasicValueEnum::PointerValue(x1) = x1 else { unsupported_type(ctx, FN_NAME, &[x1_ty]) }; - let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_value(x1, None); + let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_pointer_value(x1, None); if !x1.get_type().element_type().is_float_type() { unsupported_type(ctx, FN_NAME, &[x1_ty]); @@ -1974,7 +1985,7 @@ pub fn call_np_linalg_det<'ctx, G: CodeGenerator + ?Sized>( let BasicValueEnum::PointerValue(x1) = x1 else { unsupported_type(ctx, FN_NAME, &[x1_ty]) }; - let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_value(x1, None); + let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_pointer_value(x1, None); if !x1.get_type().element_type().is_float_type() { unsupported_type(ctx, FN_NAME, &[x1_ty]); @@ -2013,7 +2024,7 @@ pub fn call_sp_linalg_schur<'ctx, G: CodeGenerator + ?Sized>( let BasicValueEnum::PointerValue(x1) = x1 else { unsupported_type(ctx, FN_NAME, &[x1_ty]) }; - let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_value(x1, None); + let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_pointer_value(x1, None); assert_eq!(x1.get_type().ndims(), 2); if !x1.get_type().element_type().is_float_type() { @@ -2061,7 +2072,7 @@ pub fn call_sp_linalg_hessenberg<'ctx, G: CodeGenerator + ?Sized>( let BasicValueEnum::PointerValue(x1) = x1 else { unsupported_type(ctx, FN_NAME, &[x1_ty]) }; - let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_value(x1, None); + let x1 = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_pointer_value(x1, None); assert_eq!(x1.get_type().ndims(), 2); if !x1.get_type().element_type().is_float_type() { diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index 7a1d42f4..20d296e4 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 @@ -1767,7 +1767,7 @@ pub fn gen_unaryop_expr_with_values<'ctx, G: CodeGenerator>( let (ndarray_dtype, _) = unpack_ndarray_var_tys(&mut ctx.unifier, ty); let ndarray = NDArrayType::from_unifier_type(generator, ctx, ty) - .map_value(val.into_pointer_value(), None); + .map_pointer_value(val.into_pointer_value(), None); // ndarray uses `~` rather than `not` to perform elementwise inversion, convert it before // passing it to the elementwise codegen function @@ -3043,7 +3043,7 @@ pub fn gen_expr<'ctx, G: CodeGenerator>( let ndarray_ty = value.custom.unwrap(); let ndarray = ndarray.to_basic_value_enum(ctx, generator, ndarray_ty)?; let ndarray = NDArrayType::from_unifier_type(generator, ctx, ndarray_ty) - .map_value(ndarray.into_pointer_value(), None); + .map_pointer_value(ndarray.into_pointer_value(), None); let indices = RustNDIndex::from_subscript_expr(generator, ctx, slice)?; let result = ndarray diff --git a/nac3core/src/codegen/numpy.rs b/nac3core/src/codegen/numpy.rs index 2eec88da..dfb1b4d8 100644 --- a/nac3core/src/codegen/numpy.rs +++ b/nac3core/src/codegen/numpy.rs @@ -272,7 +272,7 @@ pub fn gen_ndarray_copy<'ctx>( obj.as_ref().unwrap().1.clone().to_basic_value_enum(context, generator, this_ty)?; let this = NDArrayType::from_unifier_type(generator, context, this_ty) - .map_value(this_arg.into_pointer_value(), None); + .map_pointer_value(this_arg.into_pointer_value(), None); let ndarray = this.make_copy(generator, context); Ok(ndarray.as_abi_value(context)) } @@ -295,7 +295,7 @@ pub fn gen_ndarray_fill<'ctx>( let value_arg = args[0].1.clone().to_basic_value_enum(context, generator, value_ty)?; let this = NDArrayType::from_unifier_type(generator, context, this_ty) - .map_value(this_arg.into_pointer_value(), None); + .map_pointer_value(this_arg.into_pointer_value(), None); this.fill(generator, context, value_arg); Ok(()) } @@ -316,8 +316,10 @@ pub fn ndarray_dot<'ctx, G: CodeGenerator + ?Sized>( match (x1, x2) { (BasicValueEnum::PointerValue(n1), BasicValueEnum::PointerValue(n2)) => { - let a = NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_value(n1, None); - let b = NDArrayType::from_unifier_type(generator, ctx, x2_ty).map_value(n2, None); + let a = + NDArrayType::from_unifier_type(generator, ctx, x1_ty).map_pointer_value(n1, None); + let b = + NDArrayType::from_unifier_type(generator, ctx, x2_ty).map_pointer_value(n2, None); // TODO: General `np.dot()` https://numpy.org/doc/stable/reference/generated/numpy.dot.html. assert_eq!(a.get_type().ndims(), 1); diff --git a/nac3core/src/codegen/stmt.rs b/nac3core/src/codegen/stmt.rs index e8f1d906..0c1b931a 100644 --- a/nac3core/src/codegen/stmt.rs +++ b/nac3core/src/codegen/stmt.rs @@ -440,7 +440,7 @@ pub fn gen_setitem<'ctx, G: CodeGenerator>( // ``` let target = NDArrayType::from_unifier_type(generator, ctx, target_ty) - .map_value(target.into_pointer_value(), None); + .map_pointer_value(target.into_pointer_value(), None); let target = target.index(generator, ctx, &key); let value = ScalarOrNDArray::from_value(generator, ctx, (value_ty, value)) @@ -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..633a0b48 100644 --- a/nac3core/src/codegen/types/ndarray/array.rs +++ b/nac3core/src/codegen/types/ndarray/array.rs @@ -167,7 +167,7 @@ impl<'ctx> NDArrayType<'ctx> { .map(BasicValueEnum::into_pointer_value) .unwrap(); - NDArrayType::new(ctx, dtype, ndims).map_value(ndarray, None) + NDArrayType::new(ctx, dtype, ndims).map_pointer_value(ndarray, None) } /// Implementation of `np_array(, copy=copy)`. @@ -200,7 +200,7 @@ impl<'ctx> NDArrayType<'ctx> { .map(BasicValueEnum::into_pointer_value) .unwrap(); - ndarray.get_type().map_value(ndarray_val, name) + ndarray.get_type().map_pointer_value(ndarray_val, name) } /// Create a new ndarray like @@ -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) } @@ -230,7 +230,7 @@ impl<'ctx> NDArrayType<'ctx> { if *obj_id == ctx.primitives.ndarray.obj_id(&ctx.unifier).unwrap() => { let ndarray = NDArrayType::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_ndarray_impl(generator, ctx, ndarray, 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/mod.rs b/nac3core/src/codegen/types/ndarray/mod.rs index a79a1f30..28ea5276 100644 --- a/nac3core/src/codegen/types/ndarray/mod.rs +++ b/nac3core/src/codegen/types/ndarray/mod.rs @@ -1,7 +1,7 @@ use inkwell::{ context::{AsContextRef, Context}, - types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType}, - values::{BasicValue, IntValue, PointerValue}, + types::{AnyTypeEnum, BasicType, BasicTypeEnum, IntType, PointerType, StructType}, + values::{BasicValue, IntValue, PointerValue, StructValue}, AddressSpace, }; use itertools::Itertools; @@ -9,12 +9,12 @@ use itertools::Itertools; use nac3core_derive::StructFields; use super::{ - structure::{check_struct_type_matches_fields, StructField, StructFields}, + structure::{check_struct_type_matches_fields, StructField, StructFields, StructProxyType}, ProxyType, }; use crate::{ codegen::{ - values::{ndarray::NDArrayValue, ProxyValue, TypedArrayLikeMutator}, + values::{ndarray::NDArrayValue, TypedArrayLikeMutator}, {CodeGenContext, CodeGenerator}, }, toplevel::{helper::extract_ndims, numpy::unpack_ndarray_var_tys}, @@ -71,13 +71,6 @@ impl<'ctx> NDArrayType<'ctx> { NDArrayStructFields::new(ctx, llvm_usize) } - /// See [`NDArrayType::fields`]. - // TODO: Move this into e.g. StructProxyType - #[must_use] - pub fn get_fields(&self, ctx: impl AsContextRef<'ctx>) -> NDArrayStructFields<'ctx> { - Self::fields(ctx, self.llvm_usize) - } - /// Creates an LLVM type corresponding to the expected structure of an `NDArray`. #[must_use] fn llvm_type(ctx: &'ctx Context, llvm_usize: IntType<'ctx>) -> PointerType<'ctx> { @@ -183,9 +176,20 @@ impl<'ctx> NDArrayType<'ctx> { Self::new_impl(ctx.ctx, llvm_dtype, ndims, ctx.get_size_type()) } + /// Creates an [`NDArrayType`] from a [`StructType`] representing an `NDArray`. + #[must_use] + pub fn from_struct_type( + ty: StructType<'ctx>, + dtype: BasicTypeEnum<'ctx>, + ndims: u64, + llvm_usize: IntType<'ctx>, + ) -> Self { + Self::from_pointer_type(ty.ptr_type(AddressSpace::default()), dtype, ndims, llvm_usize) + } + /// Creates an [`NDArrayType`] from a [`PointerType`] representing an `NDArray`. #[must_use] - pub fn from_type( + pub fn from_pointer_type( ptr_ty: PointerType<'ctx>, dtype: BasicTypeEnum<'ctx>, ndims: u64, @@ -411,9 +415,29 @@ impl<'ctx> NDArrayType<'ctx> { /// Converts an existing value into a [`NDArrayValue`]. #[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.dtype, + self.ndims, + self.llvm_usize, + name, + ) + } + + /// Converts an existing value into a [`NDArrayValue`]. + #[must_use] + pub fn map_pointer_value( + &self, + value: PointerValue<'ctx>, name: Option<&'ctx str>, ) -> >::Value { >::Value::from_pointer_value( @@ -471,6 +495,14 @@ impl<'ctx> ProxyType<'ctx> for NDArrayType<'ctx> { } } +impl<'ctx> StructProxyType<'ctx> for NDArrayType<'ctx> { + type StructFields = NDArrayStructFields<'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: NDArrayType<'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..ea66feb4 100644 --- a/nac3core/src/codegen/types/tuple.rs +++ b/nac3core/src/codegen/types/tuple.rs @@ -1,16 +1,13 @@ 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}, - CodeGenContext, CodeGenerator, - }, + codegen::{values::TupleValue, CodeGenContext, CodeGenerator}, typecheck::typedef::{Type, TypeEnum}, }; @@ -77,12 +74,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 +120,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 +153,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..9dca06a4 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() @@ -129,7 +153,7 @@ impl<'ctx> NDArrayValue<'ctx> { |_, ctx| Ok(self.is_c_contiguous(ctx)), |_, ctx| { // This ndarray is contiguous. - let data = self.data_field(ctx).load(ctx, self.as_abi_value(ctx), self.name); + let data = self.data_field().load(ctx, self.as_abi_value(ctx), self.name); let data = ctx .builder .build_pointer_cast(data, result.item.ptr_type(AddressSpace::default()), "") 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/mod.rs b/nac3core/src/codegen/values/ndarray/mod.rs index 38c87e0c..dcb69473 100644 --- a/nac3core/src/codegen/values/ndarray/mod.rs +++ b/nac3core/src/codegen/values/ndarray/mod.rs @@ -2,14 +2,14 @@ use std::iter::repeat_n; use inkwell::{ types::{AnyType, AnyTypeEnum, BasicType, BasicTypeEnum, IntType}, - values::{BasicValue, BasicValueEnum, IntValue, PointerValue}, + values::{BasicValue, BasicValueEnum, IntValue, PointerValue, StructValue}, AddressSpace, IntPredicate, }; use itertools::Itertools; use super::{ - ArrayLikeIndexer, ArrayLikeValue, ProxyValue, TupleValue, TypedArrayLikeAccessor, - TypedArrayLikeAdapter, TypedArrayLikeMutator, UntypedArrayLikeAccessor, + structure::StructProxyValue, ArrayLikeIndexer, ArrayLikeValue, ProxyValue, TupleValue, + TypedArrayLikeAccessor, TypedArrayLikeAdapter, TypedArrayLikeMutator, UntypedArrayLikeAccessor, UntypedArrayLikeMutator, }; use crate::{ @@ -18,7 +18,11 @@ use crate::{ llvm_intrinsics::{call_int_umin, call_memcpy_generic_array}, stmt::gen_for_callback_incrementing, type_aligned_alloca, - types::{ndarray::NDArrayType, structure::StructField, TupleType}, + types::{ + ndarray::NDArrayType, + structure::{StructField, StructProxyType}, + TupleType, + }, CodeGenContext, CodeGenerator, }, typecheck::typedef::{Type, TypeEnum}, @@ -49,6 +53,28 @@ pub struct NDArrayValue<'ctx> { } impl<'ctx> NDArrayValue<'ctx> { + /// Creates an [`NDArrayValue`] from a [`StructValue`]. + #[must_use] + pub fn from_struct_value( + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + val: StructValue<'ctx>, + dtype: BasicTypeEnum<'ctx>, + ndims: u64, + 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, ndims, llvm_usize, name) + } + /// Creates an [`NDArrayValue`] from a [`PointerValue`]. #[must_use] pub fn from_pointer_value( @@ -63,52 +89,45 @@ impl<'ctx> NDArrayValue<'ctx> { NDArrayValue { value: ptr, dtype, ndims, llvm_usize, name } } - fn ndims_field(&self, ctx: &CodeGenContext<'ctx, '_>) -> StructField<'ctx, IntValue<'ctx>> { - self.get_type().get_fields(ctx.ctx).ndims - } - - /// Returns the pointer to the field storing the number of dimensions of this `NDArray`. - fn ptr_to_ndims(&self, ctx: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> { - self.ndims_field(ctx).ptr_by_gep(ctx, self.value, self.name) + fn ndims_field(&self) -> StructField<'ctx, IntValue<'ctx>> { + self.get_type().get_fields().ndims } /// Stores the number of dimensions `ndims` into this instance. pub fn store_ndims(&self, ctx: &CodeGenContext<'ctx, '_>, ndims: IntValue<'ctx>) { debug_assert_eq!(ndims.get_type(), ctx.get_size_type()); - let pndims = self.ptr_to_ndims(ctx); - ctx.builder.build_store(pndims, ndims).unwrap(); + self.ndims_field().store(ctx, self.value, ndims, self.name); } /// Returns the number of dimensions of this `NDArray` as a value. pub fn load_ndims(&self, ctx: &CodeGenContext<'ctx, '_>) -> IntValue<'ctx> { - let pndims = self.ptr_to_ndims(ctx); - ctx.builder.build_load(pndims, "").map(BasicValueEnum::into_int_value).unwrap() + self.ndims_field().load(ctx, self.value, self.name) } - fn itemsize_field(&self, ctx: &CodeGenContext<'ctx, '_>) -> StructField<'ctx, IntValue<'ctx>> { - self.get_type().get_fields(ctx.ctx).itemsize + fn itemsize_field(&self) -> StructField<'ctx, IntValue<'ctx>> { + self.get_type().get_fields().itemsize } /// Stores the size of each element `itemsize` into this instance. pub fn store_itemsize(&self, ctx: &CodeGenContext<'ctx, '_>, itemsize: IntValue<'ctx>) { debug_assert_eq!(itemsize.get_type(), ctx.get_size_type()); - self.itemsize_field(ctx).store(ctx, self.value, itemsize, self.name); + self.itemsize_field().store(ctx, self.value, itemsize, self.name); } /// Returns the size of each element of this `NDArray` as a value. pub fn load_itemsize(&self, ctx: &CodeGenContext<'ctx, '_>) -> IntValue<'ctx> { - self.itemsize_field(ctx).load(ctx, self.value, self.name) + self.itemsize_field().load(ctx, self.value, self.name) } - fn shape_field(&self, ctx: &CodeGenContext<'ctx, '_>) -> StructField<'ctx, PointerValue<'ctx>> { - self.get_type().get_fields(ctx.ctx).shape + fn shape_field(&self) -> StructField<'ctx, PointerValue<'ctx>> { + self.get_type().get_fields().shape } /// Stores the array of dimension sizes `dims` into this instance. fn store_shape(&self, ctx: &CodeGenContext<'ctx, '_>, dims: PointerValue<'ctx>) { - self.shape_field(ctx).store(ctx, self.value, dims, self.name); + self.shape_field().store(ctx, self.value, dims, self.name); } /// Convenience method for creating a new array storing dimension sizes with the given `size`. @@ -127,16 +146,13 @@ impl<'ctx> NDArrayValue<'ctx> { NDArrayShapeProxy(self) } - fn strides_field( - &self, - ctx: &CodeGenContext<'ctx, '_>, - ) -> StructField<'ctx, PointerValue<'ctx>> { - self.get_type().get_fields(ctx.ctx).strides + fn strides_field(&self) -> StructField<'ctx, PointerValue<'ctx>> { + self.get_type().get_fields().strides } /// Stores the array of stride sizes `strides` into this instance. fn store_strides(&self, ctx: &CodeGenContext<'ctx, '_>, strides: PointerValue<'ctx>) { - self.strides_field(ctx).store(ctx, self.value, strides, self.name); + self.strides_field().store(ctx, self.value, strides, self.name); } /// Convenience method for creating a new array storing the stride with the given `size`. @@ -155,14 +171,14 @@ impl<'ctx> NDArrayValue<'ctx> { NDArrayStridesProxy(self) } - fn data_field(&self, ctx: &CodeGenContext<'ctx, '_>) -> StructField<'ctx, PointerValue<'ctx>> { - self.get_type().get_fields(ctx.ctx).data + fn data_field(&self) -> StructField<'ctx, PointerValue<'ctx>> { + self.get_type().get_fields().data } /// Returns the double-indirection pointer to the `data` array, as if by calling `getelementptr` /// on the field. pub fn ptr_to_data(&self, ctx: &CodeGenContext<'ctx, '_>) -> PointerValue<'ctx> { - self.data_field(ctx).ptr_by_gep(ctx, self.value, self.name) + self.data_field().ptr_by_gep(ctx, self.value, self.name) } /// Stores the array of data elements `data` into this instance. @@ -171,7 +187,7 @@ impl<'ctx> NDArrayValue<'ctx> { .builder .build_bit_cast(data, ctx.ctx.i8_type().ptr_type(AddressSpace::default()), "") .unwrap(); - self.data_field(ctx).store(ctx, self.value, data.into_pointer_value(), self.name); + self.data_field().store(ctx, self.value, data.into_pointer_value(), self.name); } /// Convenience method for creating a new array storing data elements with the given element @@ -467,7 +483,7 @@ impl<'ctx> ProxyValue<'ctx> for NDArrayValue<'ctx> { type Type = NDArrayType<'ctx>; fn get_type(&self) -> Self::Type { - NDArrayType::from_type( + NDArrayType::from_pointer_type( self.as_base_value().get_type(), self.dtype, self.ndims, @@ -484,6 +500,8 @@ impl<'ctx> ProxyValue<'ctx> for NDArrayValue<'ctx> { } } +impl<'ctx> StructProxyValue<'ctx> for NDArrayValue<'ctx> {} + impl<'ctx> From> for PointerValue<'ctx> { fn from(value: NDArrayValue<'ctx>) -> Self { value.as_base_value() @@ -508,7 +526,7 @@ impl<'ctx> ArrayLikeValue<'ctx> for NDArrayShapeProxy<'ctx, '_> { ctx: &CodeGenContext<'ctx, '_>, _: &G, ) -> PointerValue<'ctx> { - self.0.shape_field(ctx).load(ctx, self.0.value, self.0.name) + self.0.shape_field().load(ctx, self.0.value, self.0.name) } fn size( @@ -606,7 +624,7 @@ impl<'ctx> ArrayLikeValue<'ctx> for NDArrayStridesProxy<'ctx, '_> { ctx: &CodeGenContext<'ctx, '_>, _: &G, ) -> PointerValue<'ctx> { - self.0.strides_field(ctx).load(ctx, self.0.value, self.0.name) + self.0.strides_field().load(ctx, self.0.value, self.0.name) } fn size( @@ -704,7 +722,7 @@ impl<'ctx> ArrayLikeValue<'ctx> for NDArrayDataProxy<'ctx, '_> { ctx: &CodeGenContext<'ctx, '_>, _: &G, ) -> PointerValue<'ctx> { - self.0.data_field(ctx).load(ctx, self.0.value, self.0.name) + self.0.data_field().load(ctx, self.0.value, self.0.name) } fn size( @@ -958,7 +976,7 @@ impl<'ctx> ScalarOrNDArray<'ctx> { if *obj_id == ctx.primitives.ndarray.obj_id(&ctx.unifier).unwrap() => { let ndarray = NDArrayType::from_unifier_type(generator, ctx, object_ty) - .map_value(object.into_pointer_value(), None); + .map_pointer_value(object.into_pointer_value(), None); ScalarOrNDArray::NDArray(ndarray) } 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..eff614e5 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; @@ -1280,7 +1280,7 @@ impl<'a> BuiltinBuilder<'a> { let ndarray = args[0].1.clone().to_basic_value_enum(ctx, generator, ndarray_ty)?; let ndarray = NDArrayType::from_unifier_type(generator, ctx, ndarray_ty) - .map_value(ndarray.into_pointer_value(), None); + .map_pointer_value(ndarray.into_pointer_value(), None); let size = ctx .builder @@ -1312,7 +1312,7 @@ impl<'a> BuiltinBuilder<'a> { args[0].1.clone().to_basic_value_enum(ctx, generator, ndarray_ty)?; let ndarray = NDArrayType::from_unifier_type(generator, ctx, ndarray_ty) - .map_value(ndarray.into_pointer_value(), None); + .map_pointer_value(ndarray.into_pointer_value(), None); let result_tuple = match prim { PrimDef::FunNpShape => ndarray.make_shape_tuple(generator, ctx), @@ -1353,7 +1353,7 @@ impl<'a> BuiltinBuilder<'a> { let arg_val = args[0].1.clone().to_basic_value_enum(ctx, generator, arg_ty)?; let ndarray = NDArrayType::from_unifier_type(generator, ctx, arg_ty) - .map_value(arg_val.into_pointer_value(), None); + .map_pointer_value(arg_val.into_pointer_value(), None); let ndarray = ndarray.transpose(generator, ctx, None); // TODO: Add axes argument Ok(Some(ndarray.as_abi_value(ctx).into())) @@ -1391,7 +1391,7 @@ impl<'a> BuiltinBuilder<'a> { args[1].1.clone().to_basic_value_enum(ctx, generator, shape_ty)?; let ndarray = NDArrayType::from_unifier_type(generator, ctx, ndarray_ty) - .map_value(ndarray_val.into_pointer_value(), None); + .map_pointer_value(ndarray_val.into_pointer_value(), None); let shape = parse_numpy_int_sequence(generator, ctx, (shape_ty, shape_val));