[core] codegen: Implement StructProxy on existing proxies

This commit is contained in:
David Mak 2025-01-27 23:23:05 +08:00
parent 0ff99f4677
commit acd5e382c0
23 changed files with 568 additions and 169 deletions

View File

@ -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);

View File

@ -47,14 +47,14 @@ pub fn call_len<'ctx, G: CodeGenerator + ?Sized>(
let range_ty = ctx.primitives.range;
Ok(if ctx.unifier.unioned(arg_ty, range_ty) {
let arg = RangeType::new(ctx).map_value(arg.into_pointer_value(), Some("range"));
let arg = RangeType::new(ctx).map_pointer_value(arg.into_pointer_value(), Some("range"));
let (start, end, step) = destructure_range(ctx, arg);
calculate_len_for_slice_range(generator, ctx, start, end, step)
} else {
match &*ctx.unifier.get_ty_immutable(arg_ty) {
TypeEnum::TTuple { .. } => {
let tuple = TupleType::from_unifier_type(generator, ctx, arg_ty)
.map_value(arg.into_struct_value(), None);
.map_struct_value(arg.into_struct_value(), None);
llvm_i32.const_int(tuple.get_type().num_elements().into(), false)
}
@ -72,7 +72,7 @@ pub fn call_len<'ctx, G: CodeGenerator + ?Sized>(
if *obj_id == ctx.primitives.list.obj_id(&ctx.unifier).unwrap() =>
{
let list = ListType::from_unifier_type(generator, ctx, arg_ty)
.map_value(arg.into_pointer_value(), None);
.map_pointer_value(arg.into_pointer_value(), None);
ctx.builder
.build_int_truncate_or_bit_cast(list.load_size(ctx, None), llvm_i32, "len")
.unwrap()

View File

@ -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

View File

@ -511,7 +511,7 @@ pub fn gen_for<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"));
// 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

View File

@ -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<G: CodeGenerator + ?Sized>(
&self,
value: <<Self as ProxyType<'ctx>>::Value as ProxyValue<'ctx>>::Base,
generator: &mut G,
ctx: &mut CodeGenContext<'ctx, '_>,
value: StructValue<'ctx>,
name: Option<&'ctx str>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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<ListType<'ctx>> for PointerType<'ctx> {
fn from(value: ListType<'ctx>) -> Self {
value.as_base_type()

View File

@ -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)
}

View File

@ -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<G: CodeGenerator + ?Sized>(
&self,
value: <<Self as ProxyType<'ctx>>::Value as ProxyValue<'ctx>>::Base,
generator: &mut G,
ctx: &mut CodeGenContext<'ctx, '_>,
value: StructValue<'ctx>,
name: Option<&'ctx str>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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<ShapeEntryType<'ctx>> for PointerType<'ctx> {
fn from(value: ShapeEntryType<'ctx>) -> Self {
value.as_base_type()

View File

@ -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<G: CodeGenerator + ?Sized>(
&self,
value: <<Self as ProxyType<'ctx>>::Value as ProxyValue<'ctx>>::Base,
generator: &mut G,
ctx: &mut CodeGenContext<'ctx, '_>,
value: StructValue<'ctx>,
name: Option<&'ctx str>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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<ContiguousNDArrayType<'ctx>> for PointerType<'ctx> {
fn from(value: ContiguousNDArrayType<'ctx>) -> Self {
value.as_base_type()

View File

@ -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<G: CodeGenerator + ?Sized>(
&self,
value: <<Self as ProxyType<'ctx>>::Value as ProxyValue<'ctx>>::Base,
generator: &mut G,
ctx: &mut CodeGenContext<'ctx, '_>,
value: StructValue<'ctx>,
name: Option<&'ctx str>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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<NDIndexType<'ctx>> for PointerType<'ctx> {
fn from(value: NDIndexType<'ctx>) -> Self {
value.as_base_type()

View File

@ -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<G: CodeGenerator + ?Sized>(
&self,
value: <<Self as ProxyType<'ctx>>::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>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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<NDIterType<'ctx>> for PointerType<'ctx> {
fn from(value: NDIterType<'ctx>) -> Self {
value.as_base_type()

View File

@ -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<G: CodeGenerator + ?Sized>(
&self,
value: <<Self as ProxyType<'ctx>>::Value as ProxyValue<'ctx>>::Base,
generator: &mut G,
ctx: &mut CodeGenContext<'ctx, '_>,
value: ArrayValue<'ctx>,
name: Option<&'ctx str>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::Value::from_pointer_value(value, self.llvm_usize, name)

View File

@ -1,14 +1,14 @@
use inkwell::{
context::Context,
types::{BasicType, BasicTypeEnum, IntType, StructType},
values::BasicValueEnum,
types::{BasicType, BasicTypeEnum, IntType, PointerType, StructType},
values::{BasicValueEnum, PointerValue, StructValue},
};
use itertools::Itertools;
use super::ProxyType;
use crate::{
codegen::{
values::{ProxyValue, TupleValue},
values::TupleValue,
CodeGenContext, CodeGenerator,
},
typecheck::typedef::{Type, TypeEnum},
@ -77,12 +77,18 @@ impl<'ctx> TupleType<'ctx> {
/// Creates an [`TupleType`] from a [`StructType`].
#[must_use]
pub fn from_type(struct_ty: StructType<'ctx>, llvm_usize: IntType<'ctx>) -> Self {
pub fn from_struct_type(struct_ty: StructType<'ctx>, llvm_usize: IntType<'ctx>) -> Self {
debug_assert!(Self::has_same_repr(struct_ty, llvm_usize).is_ok());
TupleType { ty: struct_ty, llvm_usize }
}
/// Creates an [`TupleType`] from a [`PointerType`].
#[must_use]
pub fn from_pointer_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self {
Self::from_struct_type(ptr_ty.get_element_type().into_struct_type(), llvm_usize)
}
/// Returns the number of elements present in this [`TupleType`].
#[must_use]
pub fn num_elements(&self) -> u32 {
@ -117,7 +123,10 @@ impl<'ctx> TupleType<'ctx> {
ctx: &CodeGenContext<'ctx, '_>,
name: Option<&'ctx str>,
) -> <Self as ProxyType<'ctx>>::Value {
self.map_value(Self::llvm_type(ctx.ctx, &self.ty.get_field_types()).const_zero(), name)
self.map_struct_value(
Self::llvm_type(ctx.ctx, &self.ty.get_field_types()).const_zero(),
name,
)
}
/// Constructs a [`TupleValue`] from `objects`. The resulting tuple preserves the order of
@ -147,13 +156,24 @@ impl<'ctx> TupleType<'ctx> {
/// Converts an existing value into a [`ListValue`].
#[must_use]
pub fn map_value(
pub fn map_struct_value(
&self,
value: <<Self as ProxyType<'ctx>>::Value as ProxyValue<'ctx>>::Base,
value: StructValue<'ctx>,
name: Option<&'ctx str>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::Value::from_pointer_value(ctx, value, self.llvm_usize, name)
}
}
impl<'ctx> ProxyType<'ctx> for TupleType<'ctx> {

View File

@ -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<G: CodeGenerator + ?Sized>(
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<G: CodeGenerator + ?Sized>(
&self,
generator: &mut G,
ctx: &mut CodeGenContext<'ctx, '_>,
value: StructValue<'ctx>,
name: Option<&'ctx str>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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: <<Self as ProxyType<'ctx>>::Value as ProxyValue<'ctx>>::Base,
value: PointerValue<'ctx>,
name: Option<&'ctx str>,
) -> <Self as ProxyType<'ctx>>::Value {
<Self as ProxyType<'ctx>>::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<SliceType<'ctx>> for PointerType<'ctx> {
fn from(value: SliceType<'ctx>) -> Self {
value.as_base_type()

View File

@ -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<G: CodeGenerator + ?Sized>(
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<ListValue<'ctx>> 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<G: CodeGenerator + ?Sized>(

View File

@ -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<G: CodeGenerator + ?Sized>(
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<ShapeEntryValue<'ctx>> 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);

View File

@ -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<G: CodeGenerator + ?Sized>(
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 {
<Self as ProxyValue<'ctx>>::Type::from_type(
<Self as ProxyValue<'ctx>>::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<ContiguousNDArrayValue<'ctx>> for PointerValue<'ctx> {
fn from(value: ContiguousNDArrayValue<'ctx>) -> Self {
value.as_base_value()

View File

@ -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<G: CodeGenerator + ?Sized>(
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<NDIndexValue<'ctx>> for PointerValue<'ctx> {
fn from(value: NDIndexValue<'ctx>) -> Self {
value.as_base_value()

View File

@ -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<G: CodeGenerator + ?Sized>(
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<NDIterValue<'ctx>> for PointerValue<'ctx> {
fn from(value: NDIterValue<'ctx>) -> Self {
value.as_base_value()

View File

@ -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();

View File

@ -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<G: CodeGenerator + ?Sized>(
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 {

View File

@ -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 {

View File

@ -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<G: CodeGenerator + ?Sized>(
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<SliceValue<'ctx>> for PointerValue<'ctx> {
fn from(value: SliceValue<'ctx>) -> Self {
value.as_base_value()

View File

@ -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;