diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index 99998791..44d287d6 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -18,7 +18,7 @@ use nac3core::{ irrt::call_ndarray_calc_size, llvm_intrinsics::{call_int_smax, call_memcpy_generic, call_stackrestore, call_stacksave}, stmt::{gen_block, gen_for_callback_incrementing, gen_if_callback, gen_with}, - types::{NDArrayType, ProxyType}, + types::NDArrayType, values::{ ArrayLikeIndexer, ArrayLikeValue, ArraySliceValue, ListValue, NDArrayValue, ProxyValue, RangeValue, UntypedArrayLikeAccessor, @@ -460,12 +460,20 @@ fn format_rpc_arg<'ctx>( let (elem_ty, _) = unpack_ndarray_var_tys(&mut ctx.unifier, arg_ty); let llvm_elem_ty = ctx.get_llvm_type(generator, elem_ty); - let llvm_arg_ty = NDArrayType::new(generator, ctx.ctx, llvm_elem_ty); - let llvm_arg = llvm_arg_ty.map_value(arg.into_pointer_value(), None); + let llvm_arg = NDArrayValue::from_pointer_value( + arg.into_pointer_value(), + llvm_elem_ty, + llvm_usize, + None, + ); let llvm_usize_sizeof = ctx .builder - .build_int_truncate_or_bit_cast(llvm_arg_ty.size_type().size_of(), llvm_usize, "") + .build_int_truncate_or_bit_cast( + llvm_arg.get_type().size_type().size_of(), + llvm_usize, + "", + ) .unwrap(); let llvm_pdata_sizeof = ctx .builder @@ -598,7 +606,7 @@ fn format_rpc_ret<'ctx>( // Allocate the resulting ndarray // A condition after format_rpc_ret ensures this will not be popped this off. - let ndarray = llvm_ret_ty.new_value(generator, ctx, Some("rpc.result")); + let ndarray = llvm_ret_ty.alloca(generator, ctx, Some("rpc.result")); // Setup ndims let ndims = diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index f8462ab2..2cd56700 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -32,7 +32,7 @@ use super::{ gen_for_callback_incrementing, gen_if_callback, gen_if_else_expr_callback, gen_raise, gen_var, }, - types::{ListType, ProxyType}, + types::ListType, values::{ ArrayLikeIndexer, ArrayLikeValue, ListValue, NDArrayValue, ProxyValue, RangeValue, TypedArrayLikeAccessor, UntypedArrayLikeAccessor, @@ -1112,7 +1112,7 @@ pub fn allocate_list<'ctx, G: CodeGenerator + ?Sized>( // List structure; type { ty*, size_t } let arr_ty = ListType::new(generator, ctx.ctx, llvm_elem_ty); - let list = arr_ty.new_value(generator, ctx, name); + let list = arr_ty.alloca(generator, ctx, name); let length = ctx.builder.build_int_z_extend(length, llvm_usize, "").unwrap(); list.store_size(ctx, generator, length); diff --git a/nac3core/src/codegen/types/list.rs b/nac3core/src/codegen/types/list.rs index 7b082365..3d041349 100644 --- a/nac3core/src/codegen/types/list.rs +++ b/nac3core/src/codegen/types/list.rs @@ -111,6 +111,31 @@ impl<'ctx> ListType<'ctx> { .map(PointerType::get_element_type) .unwrap() } + + /// Allocates an instance of [`ListValue`] as if by calling `alloca` on the base type. + #[must_use] + pub fn alloca( + &self, + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_pointer_value( + self.raw_alloca(generator, ctx, name), + self.llvm_usize, + name, + ) + } + + /// Converts an existing value into a [`ListValue`]. + #[must_use] + pub fn map_value( + &self, + value: <>::Value as ProxyValue<'ctx>>::Base, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_pointer_value(value, self.llvm_usize, name) + } } impl<'ctx> ProxyType<'ctx> for ListType<'ctx> { @@ -137,25 +162,22 @@ impl<'ctx> ProxyType<'ctx> for ListType<'ctx> { Self::is_representable(llvm_ty, generator.get_size_type(ctx)) } - fn new_value( + fn raw_alloca( &self, generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, name: Option<&'ctx str>, - ) -> Self::Value { - self.map_value( - generator - .gen_var_alloc( - ctx, - self.as_base_type().get_element_type().into_struct_type().into(), - name, - ) - .unwrap(), - name, - ) + ) -> >::Base { + generator + .gen_var_alloc( + ctx, + self.as_base_type().get_element_type().into_struct_type().into(), + name, + ) + .unwrap() } - fn new_array_value( + fn array_alloca( &self, generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, @@ -172,14 +194,6 @@ impl<'ctx> ProxyType<'ctx> for ListType<'ctx> { .unwrap() } - fn map_value( - &self, - value: >::Base, - name: Option<&'ctx str>, - ) -> Self::Value { - Self::Value::from_pointer_value(value, self.llvm_usize, name) - } - fn as_base_type(&self) -> Self::Base { self.ty } diff --git a/nac3core/src/codegen/types/mod.rs b/nac3core/src/codegen/types/mod.rs index fc64c9d1..517a682f 100644 --- a/nac3core/src/codegen/types/mod.rs +++ b/nac3core/src/codegen/types/mod.rs @@ -1,3 +1,21 @@ +//! This module contains abstraction over all intrinsic composite types of NAC3. +//! +//! # `raw_alloca` vs `alloca` vs `construct` +//! +//! There are three ways of creating a new object instance using the abstractions provided by this +//! module. +//! +//! - `raw_alloca`: Allocates the object on the stack, returning an instance of +//! [`impl BasicValue`][inkwell::values::BasicValue]. This is similar to a `malloc` expression in +//! C++ but the object is allocated on the stack. +//! - `alloca`: Similar to `raw_alloca`, but also wraps the allocated object with +//! [`>::Value`][ProxyValue], and returns the wrapped object. The returned +//! object will not initialize any value or fields. This is similar to a type-safe `malloc` +//! expression in C++ but the object is allocated on the stack. +//! - `construct`: Similar to `alloca`, but performs some initialization on the value or fields of +//! the returned object. This is similar to a `new` expression in C++ but the object is allocated +//! on the stack. + use inkwell::{context::Context, types::BasicType, values::IntValue}; use super::{ @@ -35,16 +53,17 @@ pub trait ProxyType<'ctx>: Into { llvm_ty: Self::Base, ) -> Result<(), String>; - /// Creates a new value of this type. - fn new_value( + /// Creates a new value of this type, returning the LLVM instance of this value. + fn raw_alloca( &self, generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, name: Option<&'ctx str>, - ) -> Self::Value; + ) -> >::Base; - /// Creates a new array value of this type. - fn new_array_value( + /// Creates a new array value of this type, returning an [`ArraySliceValue`] encapsulating the + /// resulting array. + fn array_alloca( &self, generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, @@ -52,13 +71,6 @@ pub trait ProxyType<'ctx>: Into { name: Option<&'ctx str>, ) -> ArraySliceValue<'ctx>; - /// Converts an existing value into a [`ProxyValue`] of this type. - fn map_value( - &self, - value: >::Base, - name: Option<&'ctx str>, - ) -> Self::Value; - /// Returns the [base type][Self::Base] of this proxy. fn as_base_type(&self) -> Self::Base; } diff --git a/nac3core/src/codegen/types/ndarray/mod.rs b/nac3core/src/codegen/types/ndarray/mod.rs index d149b910..7a49fc55 100644 --- a/nac3core/src/codegen/types/ndarray/mod.rs +++ b/nac3core/src/codegen/types/ndarray/mod.rs @@ -175,6 +175,37 @@ impl<'ctx> NDArrayType<'ctx> { pub fn element_type(&self) -> BasicTypeEnum<'ctx> { self.dtype } + + /// Allocates an instance of [`NDArrayValue`] as if by calling `alloca` on the base type. + #[must_use] + pub fn alloca( + &self, + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_pointer_value( + self.raw_alloca(generator, ctx, name), + self.dtype, + self.llvm_usize, + name, + ) + } + + /// Converts an existing value into a [`NDArrayValue`]. + #[must_use] + pub fn map_value( + &self, + value: <>::Value as ProxyValue<'ctx>>::Base, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_pointer_value( + value, + self.dtype, + self.llvm_usize, + name, + ) + } } impl<'ctx> ProxyType<'ctx> for NDArrayType<'ctx> { @@ -201,25 +232,22 @@ impl<'ctx> ProxyType<'ctx> for NDArrayType<'ctx> { Self::is_representable(llvm_ty, generator.get_size_type(ctx)) } - fn new_value( + fn raw_alloca( &self, generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, name: Option<&'ctx str>, - ) -> Self::Value { - self.map_value( - generator - .gen_var_alloc( - ctx, - self.as_base_type().get_element_type().into_struct_type().into(), - name, - ) - .unwrap(), - name, - ) + ) -> >::Base { + generator + .gen_var_alloc( + ctx, + self.as_base_type().get_element_type().into_struct_type().into(), + name, + ) + .unwrap() } - fn new_array_value( + fn array_alloca( &self, generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, @@ -236,16 +264,6 @@ impl<'ctx> ProxyType<'ctx> for NDArrayType<'ctx> { .unwrap() } - fn map_value( - &self, - value: >::Base, - name: Option<&'ctx str>, - ) -> Self::Value { - debug_assert_eq!(value.get_type(), self.as_base_type()); - - NDArrayValue::from_pointer_value(value, self.dtype, self.llvm_usize, name) - } - fn as_base_type(&self) -> Self::Base { self.ty } diff --git a/nac3core/src/codegen/types/range.rs b/nac3core/src/codegen/types/range.rs index 49c43882..e704455b 100644 --- a/nac3core/src/codegen/types/range.rs +++ b/nac3core/src/codegen/types/range.rs @@ -76,6 +76,30 @@ impl<'ctx> RangeType<'ctx> { pub fn value_type(&self) -> IntType<'ctx> { self.as_base_type().get_element_type().into_array_type().get_element_type().into_int_type() } + + /// Allocates an instance of [`RangeValue`] as if by calling `alloca` on the base type. + #[must_use] + pub fn alloca( + &self, + generator: &mut G, + ctx: &mut CodeGenContext<'ctx, '_>, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_pointer_value( + self.raw_alloca(generator, ctx, name), + name, + ) + } + + /// Converts an existing value into a [`RangeValue`]. + #[must_use] + pub fn map_value( + &self, + value: <>::Value as ProxyValue<'ctx>>::Base, + name: Option<&'ctx str>, + ) -> >::Value { + >::Value::from_pointer_value(value, name) + } } impl<'ctx> ProxyType<'ctx> for RangeType<'ctx> { @@ -102,25 +126,22 @@ impl<'ctx> ProxyType<'ctx> for RangeType<'ctx> { Self::is_representable(llvm_ty) } - fn new_value( + fn raw_alloca( &self, generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, name: Option<&'ctx str>, - ) -> Self::Value { - self.map_value( - generator - .gen_var_alloc( - ctx, - self.as_base_type().get_element_type().into_struct_type().into(), - name, - ) - .unwrap(), - name, - ) + ) -> >::Base { + generator + .gen_var_alloc( + ctx, + self.as_base_type().get_element_type().into_struct_type().into(), + name, + ) + .unwrap() } - fn new_array_value( + fn array_alloca( &self, generator: &mut G, ctx: &mut CodeGenContext<'ctx, '_>, @@ -137,16 +158,6 @@ impl<'ctx> ProxyType<'ctx> for RangeType<'ctx> { .unwrap() } - fn map_value( - &self, - value: >::Base, - name: Option<&'ctx str>, - ) -> Self::Value { - debug_assert_eq!(value.get_type(), self.as_base_type()); - - RangeValue::from_pointer_value(value, name) - } - fn as_base_type(&self) -> Self::Base { self.ty }