core: Add more creator functions for ProxyType #410
|
@ -1,10 +1,11 @@
|
||||||
use inkwell::{
|
use inkwell::{
|
||||||
IntPredicate,
|
AddressSpace, IntPredicate,
|
||||||
types::{AnyTypeEnum, BasicTypeEnum, IntType, PointerType},
|
types::{AnyTypeEnum, BasicTypeEnum, IntType, PointerType},
|
||||||
values::{BasicValueEnum, IntValue, PointerValue},
|
values::{BasicValueEnum, IntValue, PointerValue},
|
||||||
};
|
};
|
||||||
use inkwell::types::BasicType;
|
use inkwell::context::Context;
|
||||||
use inkwell::values::BasicValue;
|
use inkwell::types::{ArrayType, BasicType, StructType};
|
||||||
|
use inkwell::values::{ArrayValue, BasicValue, StructValue};
|
||||||
use crate::codegen::{
|
use crate::codegen::{
|
||||||
CodeGenContext,
|
CodeGenContext,
|
||||||
CodeGenerator,
|
CodeGenerator,
|
||||||
|
@ -14,13 +15,39 @@ use crate::codegen::{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A LLVM type that is used to represent a non-primitive type in NAC3.
|
/// A LLVM type that is used to represent a non-primitive type in NAC3.
|
||||||
pub trait ProxyType<'ctx> {
|
pub trait ProxyType<'ctx>: Into<Self::Base> {
|
||||||
/// The underlying type as represented by an LLVM type.
|
/// The LLVM type of which values of this type possess. This is usually a
|
||||||
|
/// [LLVM pointer type][PointerType].
|
||||||
type Base: BasicType<'ctx>;
|
type Base: BasicType<'ctx>;
|
||||||
|
|
||||||
|
/// The underlying LLVM type used to represent values. This is usually the element type of
|
||||||
|
/// [`Base`] if it is a pointer, otherwise this is the same type as `Base`.
|
||||||
|
type Underlying: BasicType<'ctx>;
|
||||||
|
|
||||||
/// The type of values represented by this type.
|
/// The type of values represented by this type.
|
||||||
type Value: ProxyValue<'ctx>;
|
type Value: ProxyValue<'ctx>;
|
||||||
|
|
||||||
|
/// Creates a new value of this type.
|
||||||
|
fn new_value<G: CodeGenerator + ?Sized>(
|
||||||
|
&self,
|
||||||
|
generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
name: Option<&'ctx str>,
|
||||||
|
) -> Self::Value;
|
||||||
|
|
||||||
|
/// Creates a new array value of this type.
|
||||||
|
fn new_array_value<G: CodeGenerator + ?Sized>(
|
||||||
|
&self,
|
||||||
|
generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
size: IntValue<'ctx>,
|
||||||
|
name: Option<&'ctx str>,
|
||||||
|
) -> ArraySliceValue<'ctx> {
|
||||||
|
generator
|
||||||
|
.gen_array_var_alloc(ctx, self.as_underlying_type().as_basic_type_enum(), size, name)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates a [`value`][ProxyValue] with this as its type.
|
/// Creates a [`value`][ProxyValue] with this as its type.
|
||||||
fn create_value(
|
fn create_value(
|
||||||
&self,
|
&self,
|
||||||
|
@ -28,23 +55,39 @@ pub trait ProxyType<'ctx> {
|
||||||
name: Option<&'ctx str>,
|
name: Option<&'ctx str>,
|
||||||
) -> Self::Value;
|
) -> Self::Value;
|
||||||
|
|
||||||
/// Returns the base type of this proxy.
|
/// Returns the [base type][Self::Base] of this proxy.
|
||||||
fn as_base_type(&self) -> Self::Base;
|
fn as_base_type(&self) -> Self::Base;
|
||||||
|
|
||||||
|
/// Returns the [underlying type][Self::Underlying] of this proxy.
|
||||||
|
fn as_underlying_type(&self) -> Self::Underlying;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A LLVM type that is used to represent a non-primitive value in NAC3.
|
/// A LLVM type that is used to represent a non-primitive value in NAC3.
|
||||||
pub trait ProxyValue<'ctx> {
|
pub trait ProxyValue<'ctx>: Into<Self::Base> {
|
||||||
/// The underlying type as represented by an LLVM value.
|
/// The type of LLVM values represented by this instance. This is usually the
|
||||||
|
/// [LLVM pointer type][PointerValue].
|
||||||
type Base: BasicValue<'ctx>;
|
type Base: BasicValue<'ctx>;
|
||||||
|
|
||||||
|
/// The underlying type of LLVM values represented by this instance. This is usually the element
|
||||||
|
/// type of [`Base`] if it is a pointer, otherwise this is the same type as `Base`.
|
||||||
|
type Underlying: BasicValue<'ctx>;
|
||||||
|
|
||||||
/// The type of this value.
|
/// The type of this value.
|
||||||
type Type: ProxyType<'ctx>;
|
type Type: ProxyType<'ctx>;
|
||||||
|
|
||||||
/// Returns the [type][ProxyType] of this value.
|
/// Returns the [type][ProxyType] of this value.
|
||||||
fn get_type(&self) -> Self::Type;
|
fn get_type(&self) -> Self::Type;
|
||||||
|
|
||||||
/// Returns the base value of this proxy.
|
/// Returns the [base value][Self::Base] of this proxy.
|
||||||
fn as_base_value(&self) -> Self::Base;
|
fn as_base_value(&self) -> Self::Base;
|
||||||
|
|
||||||
|
/// Loads this value into its [underlying representation][Self::Underlying]. Usually involves a
|
||||||
|
/// `getelementptr` if [`Self::Base`] is a [pointer value][PointerValue].
|
||||||
|
fn as_underlying_value(
|
||||||
|
&self,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
name: Option<&'ctx str>,
|
||||||
|
) -> Self::Underlying;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An LLVM value that is array-like, i.e. it contains a contiguous, sequenced collection of
|
/// An LLVM value that is array-like, i.e. it contains a contiguous, sequenced collection of
|
||||||
|
@ -463,6 +506,27 @@ impl<'ctx> ListType<'ctx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an instance of [`ListType`].
|
||||||
|
#[must_use]
|
||||||
|
pub fn new<G: CodeGenerator + ?Sized>(
|
||||||
|
generator: &G,
|
||||||
|
ctx: &'ctx Context,
|
||||||
|
element_type: BasicTypeEnum<'ctx>,
|
||||||
|
) -> Self {
|
||||||
|
let llvm_usize = generator.get_size_type(ctx);
|
||||||
|
let llvm_list = ctx
|
||||||
|
.struct_type(
|
||||||
|
&[
|
||||||
|
element_type.ptr_type(AddressSpace::default()).into(),
|
||||||
|
llvm_usize.into(),
|
||||||
|
],
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.ptr_type(AddressSpace::default());
|
||||||
|
|
||||||
|
ListType::from_type(llvm_list, llvm_usize)
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates an [`ListType`] from a [`PointerType`].
|
/// Creates an [`ListType`] from a [`PointerType`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self {
|
pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self {
|
||||||
|
@ -495,8 +559,21 @@ impl<'ctx> ListType<'ctx> {
|
||||||
|
|
||||||
impl<'ctx> ProxyType<'ctx> for ListType<'ctx> {
|
impl<'ctx> ProxyType<'ctx> for ListType<'ctx> {
|
||||||
type Base = PointerType<'ctx>;
|
type Base = PointerType<'ctx>;
|
||||||
|
type Underlying = StructType<'ctx>;
|
||||||
type Value = ListValue<'ctx>;
|
type Value = ListValue<'ctx>;
|
||||||
|
|
||||||
|
fn new_value<G: CodeGenerator + ?Sized>(
|
||||||
|
&self,
|
||||||
|
generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
name: Option<&'ctx str>,
|
||||||
|
) -> Self::Value {
|
||||||
|
self.create_value(
|
||||||
|
generator.gen_var_alloc(ctx, self.as_underlying_type().into(), name).unwrap(),
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn create_value(
|
fn create_value(
|
||||||
&self,
|
&self,
|
||||||
value: <Self::Value as ProxyValue<'ctx>>::Base,
|
value: <Self::Value as ProxyValue<'ctx>>::Base,
|
||||||
|
@ -510,6 +587,10 @@ impl<'ctx> ProxyType<'ctx> for ListType<'ctx> {
|
||||||
fn as_base_type(&self) -> Self::Base {
|
fn as_base_type(&self) -> Self::Base {
|
||||||
self.ty
|
self.ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_underlying_type(&self) -> Self::Underlying {
|
||||||
|
self.as_base_type().get_element_type().into_struct_type()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> From<ListType<'ctx>> for PointerType<'ctx> {
|
impl<'ctx> From<ListType<'ctx>> for PointerType<'ctx> {
|
||||||
|
@ -629,6 +710,7 @@ impl<'ctx> ListValue<'ctx> {
|
||||||
|
|
||||||
impl<'ctx> ProxyValue<'ctx> for ListValue<'ctx> {
|
impl<'ctx> ProxyValue<'ctx> for ListValue<'ctx> {
|
||||||
type Base = PointerValue<'ctx>;
|
type Base = PointerValue<'ctx>;
|
||||||
|
type Underlying = StructValue<'ctx>;
|
||||||
type Type = ListType<'ctx>;
|
type Type = ListType<'ctx>;
|
||||||
|
|
||||||
fn get_type(&self) -> Self::Type {
|
fn get_type(&self) -> Self::Type {
|
||||||
|
@ -638,6 +720,17 @@ impl<'ctx> ProxyValue<'ctx> for ListValue<'ctx> {
|
||||||
fn as_base_value(&self) -> Self::Base {
|
fn as_base_value(&self) -> Self::Base {
|
||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_underlying_value(
|
||||||
|
&self,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
name: Option<&'ctx str>,
|
||||||
|
) -> Self::Underlying {
|
||||||
|
ctx.builder
|
||||||
|
.build_load(self.as_base_value(), name.unwrap_or_default())
|
||||||
|
.map(BasicValueEnum::into_struct_value)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> From<ListValue<'ctx>> for PointerValue<'ctx> {
|
impl<'ctx> From<ListValue<'ctx>> for PointerValue<'ctx> {
|
||||||
|
@ -757,6 +850,15 @@ impl<'ctx> RangeType<'ctx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an instance of [`RangeType`].
|
||||||
|
#[must_use]
|
||||||
|
pub fn new(ctx: &'ctx Context) -> Self {
|
||||||
|
let llvm_i32 = ctx.i32_type();
|
||||||
|
let llvm_range = llvm_i32.array_type(3).ptr_type(AddressSpace::default());
|
||||||
|
|
||||||
|
RangeType::from_type(llvm_range)
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates an [`RangeType`] from a [`PointerType`].
|
/// Creates an [`RangeType`] from a [`PointerType`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn from_type(ptr_ty: PointerType<'ctx>) -> Self {
|
pub fn from_type(ptr_ty: PointerType<'ctx>) -> Self {
|
||||||
|
@ -778,8 +880,21 @@ impl<'ctx> RangeType<'ctx> {
|
||||||
|
|
||||||
impl<'ctx> ProxyType<'ctx> for RangeType<'ctx> {
|
impl<'ctx> ProxyType<'ctx> for RangeType<'ctx> {
|
||||||
type Base = PointerType<'ctx>;
|
type Base = PointerType<'ctx>;
|
||||||
|
type Underlying = ArrayType<'ctx>;
|
||||||
type Value = RangeValue<'ctx>;
|
type Value = RangeValue<'ctx>;
|
||||||
|
|
||||||
|
fn new_value<G: CodeGenerator + ?Sized>(
|
||||||
|
&self,
|
||||||
|
generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
name: Option<&'ctx str>,
|
||||||
|
) -> Self::Value {
|
||||||
|
self.create_value(
|
||||||
|
generator.gen_var_alloc(ctx, self.as_underlying_type().into(), name).unwrap(),
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn create_value(&self, value: <Self::Value as ProxyValue<'ctx>>::Base, name: Option<&'ctx str>) -> Self::Value {
|
fn create_value(&self, value: <Self::Value as ProxyValue<'ctx>>::Base, name: Option<&'ctx str>) -> Self::Value {
|
||||||
debug_assert_eq!(value.get_type(), self.as_base_type());
|
debug_assert_eq!(value.get_type(), self.as_base_type());
|
||||||
|
|
||||||
|
@ -789,6 +904,10 @@ impl<'ctx> ProxyType<'ctx> for RangeType<'ctx> {
|
||||||
fn as_base_type(&self) -> Self::Base {
|
fn as_base_type(&self) -> Self::Base {
|
||||||
self.ty
|
self.ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_underlying_type(&self) -> Self::Underlying {
|
||||||
|
self.as_base_type().get_element_type().into_array_type()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> From<RangeType<'ctx>> for PointerType<'ctx> {
|
impl<'ctx> From<RangeType<'ctx>> for PointerType<'ctx> {
|
||||||
|
@ -935,6 +1054,7 @@ impl<'ctx> RangeValue<'ctx> {
|
||||||
|
|
||||||
impl<'ctx> ProxyValue<'ctx> for RangeValue<'ctx> {
|
impl<'ctx> ProxyValue<'ctx> for RangeValue<'ctx> {
|
||||||
type Base = PointerValue<'ctx>;
|
type Base = PointerValue<'ctx>;
|
||||||
|
type Underlying = ArrayValue<'ctx>;
|
||||||
type Type = RangeType<'ctx>;
|
type Type = RangeType<'ctx>;
|
||||||
|
|
||||||
fn get_type(&self) -> Self::Type {
|
fn get_type(&self) -> Self::Type {
|
||||||
|
@ -944,6 +1064,17 @@ impl<'ctx> ProxyValue<'ctx> for RangeValue<'ctx> {
|
||||||
fn as_base_value(&self) -> Self::Base {
|
fn as_base_value(&self) -> Self::Base {
|
||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_underlying_value(
|
||||||
|
&self,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
name: Option<&'ctx str>,
|
||||||
|
) -> Self::Underlying {
|
||||||
|
ctx.builder
|
||||||
|
.build_load(self.as_base_value(), name.unwrap_or_default())
|
||||||
|
.map(BasicValueEnum::into_array_value)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> From<RangeValue<'ctx>> for PointerValue<'ctx> {
|
impl<'ctx> From<RangeValue<'ctx>> for PointerValue<'ctx> {
|
||||||
|
@ -1005,6 +1136,34 @@ impl<'ctx> NDArrayType<'ctx> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates an instance of [`ListType`].
|
||||||
|
#[must_use]
|
||||||
|
pub fn new<G: CodeGenerator + ?Sized>(
|
||||||
|
generator: &G,
|
||||||
|
ctx: &'ctx Context,
|
||||||
|
dtype: BasicTypeEnum<'ctx>,
|
||||||
|
) -> Self {
|
||||||
|
let llvm_usize = generator.get_size_type(ctx);
|
||||||
|
|
||||||
|
// struct NDArray { num_dims: size_t, dims: size_t*, data: T* }
|
||||||
|
//
|
||||||
|
// * num_dims: Number of dimensions in the array
|
||||||
|
// * dims: Pointer to an array containing the size of each dimension
|
||||||
|
// * data: Pointer to an array containing the array data
|
||||||
|
let llvm_ndarray = ctx
|
||||||
|
.struct_type(
|
||||||
|
&[
|
||||||
|
llvm_usize.into(),
|
||||||
|
llvm_usize.ptr_type(AddressSpace::default()).into(),
|
||||||
|
dtype.ptr_type(AddressSpace::default()).into(),
|
||||||
|
],
|
||||||
|
false,
|
||||||
|
)
|
||||||
|
.ptr_type(AddressSpace::default());
|
||||||
|
|
||||||
|
NDArrayType::from_type(llvm_ndarray, llvm_usize)
|
||||||
|
}
|
||||||
|
|
||||||
/// Creates an [`NDArrayType`] from a [`PointerType`].
|
/// Creates an [`NDArrayType`] from a [`PointerType`].
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self {
|
pub fn from_type(ptr_ty: PointerType<'ctx>, llvm_usize: IntType<'ctx>) -> Self {
|
||||||
|
@ -1037,8 +1196,23 @@ impl<'ctx> NDArrayType<'ctx> {
|
||||||
|
|
||||||
impl<'ctx> ProxyType<'ctx> for NDArrayType<'ctx> {
|
impl<'ctx> ProxyType<'ctx> for NDArrayType<'ctx> {
|
||||||
type Base = PointerType<'ctx>;
|
type Base = PointerType<'ctx>;
|
||||||
|
type Underlying = StructType<'ctx>;
|
||||||
type Value = NDArrayValue<'ctx>;
|
type Value = NDArrayValue<'ctx>;
|
||||||
|
|
||||||
|
fn new_value<G: CodeGenerator + ?Sized>(
|
||||||
|
&self,
|
||||||
|
generator: &mut G,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
name: Option<&'ctx str>,
|
||||||
|
) -> Self::Value {
|
||||||
|
self.create_value(
|
||||||
|
generator
|
||||||
|
.gen_var_alloc(ctx, self.as_underlying_type().into(), name)
|
||||||
|
.unwrap(),
|
||||||
|
name,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn create_value(
|
fn create_value(
|
||||||
&self,
|
&self,
|
||||||
value: <Self::Value as ProxyValue<'ctx>>::Base,
|
value: <Self::Value as ProxyValue<'ctx>>::Base,
|
||||||
|
@ -1052,6 +1226,10 @@ impl<'ctx> ProxyType<'ctx> for NDArrayType<'ctx> {
|
||||||
fn as_base_type(&self) -> Self::Base {
|
fn as_base_type(&self) -> Self::Base {
|
||||||
self.ty
|
self.ty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_underlying_type(&self) -> Self::Underlying {
|
||||||
|
self.as_base_type().get_element_type().into_struct_type()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> From<NDArrayType<'ctx>> for PointerType<'ctx> {
|
impl<'ctx> From<NDArrayType<'ctx>> for PointerType<'ctx> {
|
||||||
|
@ -1198,6 +1376,7 @@ impl<'ctx> NDArrayValue<'ctx> {
|
||||||
|
|
||||||
impl<'ctx> ProxyValue<'ctx> for NDArrayValue<'ctx> {
|
impl<'ctx> ProxyValue<'ctx> for NDArrayValue<'ctx> {
|
||||||
type Base = PointerValue<'ctx>;
|
type Base = PointerValue<'ctx>;
|
||||||
|
type Underlying = StructValue<'ctx>;
|
||||||
type Type = NDArrayType<'ctx>;
|
type Type = NDArrayType<'ctx>;
|
||||||
|
|
||||||
fn get_type(&self) -> Self::Type {
|
fn get_type(&self) -> Self::Type {
|
||||||
|
@ -1207,6 +1386,17 @@ impl<'ctx> ProxyValue<'ctx> for NDArrayValue<'ctx> {
|
||||||
fn as_base_value(&self) -> Self::Base {
|
fn as_base_value(&self) -> Self::Base {
|
||||||
self.value
|
self.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn as_underlying_value(
|
||||||
|
&self,
|
||||||
|
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||||
|
name: Option<&'ctx str>,
|
||||||
|
) -> Self::Underlying {
|
||||||
|
ctx.builder
|
||||||
|
.build_load(self.as_base_value(), name.unwrap_or_default())
|
||||||
|
.map(BasicValueEnum::into_struct_value)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'ctx> From<NDArrayValue<'ctx>> for PointerValue<'ctx> {
|
impl<'ctx> From<NDArrayValue<'ctx>> for PointerValue<'ctx> {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
|
codegen::classes::{ListType, NDArrayType, ProxyType, RangeType},
|
||||||
symbol_resolver::{StaticValue, SymbolResolver},
|
symbol_resolver::{StaticValue, SymbolResolver},
|
||||||
toplevel::{
|
toplevel::{
|
||||||
helper::PRIMITIVE_DEF_IDS,
|
helper::PRIMITIVE_DEF_IDS,
|
||||||
|
@ -452,7 +453,6 @@ fn get_llvm_type<'ctx, G: CodeGenerator + ?Sized>(
|
||||||
}
|
}
|
||||||
|
|
||||||
TObj { obj_id, .. } if *obj_id == PRIMITIVE_DEF_IDS.ndarray => {
|
TObj { obj_id, .. } if *obj_id == PRIMITIVE_DEF_IDS.ndarray => {
|
||||||
let llvm_usize = generator.get_size_type(ctx);
|
|
||||||
let (dtype, _) = unpack_ndarray_var_tys(unifier, ty);
|
let (dtype, _) = unpack_ndarray_var_tys(unifier, ty);
|
||||||
let element_type = get_llvm_type(
|
let element_type = get_llvm_type(
|
||||||
ctx,
|
ctx,
|
||||||
|
@ -464,17 +464,7 @@ fn get_llvm_type<'ctx, G: CodeGenerator + ?Sized>(
|
||||||
dtype,
|
dtype,
|
||||||
);
|
);
|
||||||
|
|
||||||
// struct NDArray { num_dims: size_t, dims: size_t*, data: T* }
|
NDArrayType::new(generator, ctx, element_type).as_base_type().into()
|
||||||
//
|
|
||||||
// * num_dims: Number of dimensions in the array
|
|
||||||
// * dims: Pointer to an array containing the size of each dimension
|
|
||||||
// * data: Pointer to an array containing the array data
|
|
||||||
let fields = [
|
|
||||||
llvm_usize.into(),
|
|
||||||
llvm_usize.ptr_type(AddressSpace::default()).into(),
|
|
||||||
element_type.ptr_type(AddressSpace::default()).into(),
|
|
||||||
];
|
|
||||||
ctx.struct_type(&fields, false).ptr_type(AddressSpace::default()).into()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => unreachable!("LLVM type for primitive {} is missing", unifier.stringify(ty)),
|
_ => unreachable!("LLVM type for primitive {} is missing", unifier.stringify(ty)),
|
||||||
|
@ -528,15 +518,11 @@ fn get_llvm_type<'ctx, G: CodeGenerator + ?Sized>(
|
||||||
ctx.struct_type(&fields, false).into()
|
ctx.struct_type(&fields, false).into()
|
||||||
}
|
}
|
||||||
TList { ty } => {
|
TList { ty } => {
|
||||||
// a struct with an integer and a pointer to an array
|
|
||||||
let element_type = get_llvm_type(
|
let element_type = get_llvm_type(
|
||||||
ctx, module, generator, unifier, top_level, type_cache, *ty,
|
ctx, module, generator, unifier, top_level, type_cache, *ty,
|
||||||
);
|
);
|
||||||
let fields = [
|
|
||||||
element_type.ptr_type(AddressSpace::default()).into(),
|
ListType::new(generator, ctx, element_type).as_base_type().into()
|
||||||
generator.get_size_type(ctx).into(),
|
|
||||||
];
|
|
||||||
ctx.struct_type(&fields, false).ptr_type(AddressSpace::default()).into()
|
|
||||||
}
|
}
|
||||||
TVirtual { .. } => unimplemented!(),
|
TVirtual { .. } => unimplemented!(),
|
||||||
_ => unreachable!("{}", ty_enum.get_type_name()),
|
_ => unreachable!("{}", ty_enum.get_type_name()),
|
||||||
|
@ -671,7 +657,7 @@ pub fn gen_func_impl<'ctx, G: CodeGenerator, F: FnOnce(&mut G, &mut CodeGenConte
|
||||||
Some(t) => t.as_basic_type_enum()
|
Some(t) => t.as_basic_type_enum()
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
(primitives.range, context.i32_type().array_type(3).ptr_type(AddressSpace::default()).into()),
|
(primitives.range, RangeType::new(context).as_base_type().into()),
|
||||||
(primitives.exception, {
|
(primitives.exception, {
|
||||||
let name = "Exception";
|
let name = "Exception";
|
||||||
if let Some(t) = module.get_struct_type(name) {
|
if let Some(t) = module.get_struct_type(name) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::{
|
codegen::{
|
||||||
concrete_type::ConcreteTypeStore, CodeGenContext, CodeGenLLVMOptions,
|
classes::{ListType, NDArrayType, ProxyType, RangeType},
|
||||||
|
concrete_type::ConcreteTypeStore, CodeGenContext, CodeGenerator, CodeGenLLVMOptions,
|
||||||
CodeGenTargetMachineOptions, CodeGenTask, DefaultCodeGenerator, WithCall, WorkerRegistry,
|
CodeGenTargetMachineOptions, CodeGenTask, DefaultCodeGenerator, WithCall, WorkerRegistry,
|
||||||
},
|
},
|
||||||
symbol_resolver::{SymbolResolver, ValueEnum},
|
symbol_resolver::{SymbolResolver, ValueEnum},
|
||||||
|
@ -425,3 +426,35 @@ fn test_simple_call() {
|
||||||
registry.add_task(task);
|
registry.add_task(task);
|
||||||
registry.wait_tasks_complete(handles);
|
registry.wait_tasks_complete(handles);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_classes_list_type_new() {
|
||||||
|
let ctx = inkwell::context::Context::create();
|
||||||
|
let generator = DefaultCodeGenerator::new(String::new(), 64);
|
||||||
|
|
||||||
|
let llvm_i32 = ctx.i32_type();
|
||||||
|
let llvm_usize = generator.get_size_type(&ctx);
|
||||||
|
|
||||||
|
let llvm_list = ListType::new(&generator, &ctx, llvm_i32.into());
|
||||||
|
assert!(ListType::is_type(llvm_list.as_base_type(), llvm_usize).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_classes_range_type_new() {
|
||||||
|
let ctx = inkwell::context::Context::create();
|
||||||
|
|
||||||
|
let llvm_range = RangeType::new(&ctx);
|
||||||
|
assert!(RangeType::is_type(llvm_range.as_base_type()).is_ok());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_classes_ndarray_type_new() {
|
||||||
|
let ctx = inkwell::context::Context::create();
|
||||||
|
let generator = DefaultCodeGenerator::new(String::new(), 64);
|
||||||
|
|
||||||
|
let llvm_i32 = ctx.i32_type();
|
||||||
|
let llvm_usize = generator.get_size_type(&ctx);
|
||||||
|
|
||||||
|
let llvm_ndarray = NDArrayType::new(&generator, &ctx, llvm_i32.into());
|
||||||
|
assert!(NDArrayType::is_type(llvm_ndarray.as_base_type(), llvm_usize).is_ok());
|
||||||
|
}
|
||||||
|
|
|
@ -12,7 +12,15 @@ use itertools::Either;
|
||||||
use crate::{
|
use crate::{
|
||||||
codegen::{
|
codegen::{
|
||||||
builtin_fns,
|
builtin_fns,
|
||||||
classes::{ArrayLikeValue, NDArrayValue, RangeValue, TypedArrayLikeAccessor},
|
classes::{
|
||||||
|
ArrayLikeValue,
|
||||||
|
NDArrayValue,
|
||||||
|
ProxyType,
|
||||||
|
ProxyValue,
|
||||||
|
RangeValue,
|
||||||
|
RangeType,
|
||||||
|
TypedArrayLikeAccessor,
|
||||||
|
},
|
||||||
expr::destructure_range,
|
expr::destructure_range,
|
||||||
irrt::*,
|
irrt::*,
|
||||||
numpy::*,
|
numpy::*,
|
||||||
|
@ -943,26 +951,53 @@ pub fn get_builtins(unifier: &mut Unifier, primitives: &PrimitiveStore) -> Built
|
||||||
let mut stop = None;
|
let mut stop = None;
|
||||||
let mut step = None;
|
let mut step = None;
|
||||||
let int32 = ctx.ctx.i32_type();
|
let int32 = ctx.ctx.i32_type();
|
||||||
let zero = int32.const_zero();
|
|
||||||
let ty_i32 = ctx.primitives.int32;
|
let ty_i32 = ctx.primitives.int32;
|
||||||
for (i, arg) in args.iter().enumerate() {
|
for (i, arg) in args.iter().enumerate() {
|
||||||
if arg.0 == Some("start".into()) {
|
if arg.0 == Some("start".into()) {
|
||||||
start = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
start = Some(arg.1
|
||||||
|
.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, ty_i32)?
|
||||||
|
.into_int_value()
|
||||||
|
);
|
||||||
} else if arg.0 == Some("stop".into()) {
|
} else if arg.0 == Some("stop".into()) {
|
||||||
stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
stop = Some(
|
||||||
|
arg.1
|
||||||
|
.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, ty_i32)?
|
||||||
|
.into_int_value()
|
||||||
|
);
|
||||||
} else if arg.0 == Some("step".into()) {
|
} else if arg.0 == Some("step".into()) {
|
||||||
step = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
step = Some(
|
||||||
|
arg.1
|
||||||
|
.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, ty_i32)?
|
||||||
|
.into_int_value()
|
||||||
|
);
|
||||||
} else if i == 0 {
|
} else if i == 0 {
|
||||||
start = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
start = Some(
|
||||||
|
arg.1
|
||||||
|
.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, ty_i32)?
|
||||||
|
.into_int_value()
|
||||||
|
);
|
||||||
} else if i == 1 {
|
} else if i == 1 {
|
||||||
stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
stop = Some(
|
||||||
|
arg.1
|
||||||
|
.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, ty_i32)?
|
||||||
|
.into_int_value()
|
||||||
|
);
|
||||||
} else if i == 2 {
|
} else if i == 2 {
|
||||||
step = Some(arg.1.clone().to_basic_value_enum(ctx, generator, ty_i32)?);
|
step = Some(
|
||||||
|
arg.1
|
||||||
|
.clone()
|
||||||
|
.to_basic_value_enum(ctx, generator, ty_i32)?
|
||||||
|
.into_int_value()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let step = match step {
|
let step = match step {
|
||||||
Some(step) => {
|
Some(step) => {
|
||||||
let step = step.into_int_value();
|
|
||||||
// assert step != 0, throw exception if not
|
// assert step != 0, throw exception if not
|
||||||
let not_zero = ctx.builder
|
let not_zero = ctx.builder
|
||||||
.build_int_compare(
|
.build_int_compare(
|
||||||
|
@ -989,30 +1024,13 @@ pub fn get_builtins(unifier: &mut Unifier, primitives: &PrimitiveStore) -> Built
|
||||||
start = None;
|
start = None;
|
||||||
v
|
v
|
||||||
});
|
});
|
||||||
let start = start.unwrap_or_else(|| int32.const_zero().into());
|
let start = start.unwrap_or_else(|| int32.const_zero());
|
||||||
let ty = int32.array_type(3);
|
|
||||||
let ptr = generator.gen_var_alloc(ctx, ty.into(), Some("range")).unwrap();
|
let ptr = RangeType::new(ctx.ctx).new_value(generator, ctx, Some("range"));
|
||||||
unsafe {
|
ptr.store_start(ctx, start);
|
||||||
let a = ctx.builder
|
ptr.store_end(ctx, stop);
|
||||||
.build_in_bounds_gep(ptr, &[zero, zero], "start")
|
ptr.store_step(ctx, step);
|
||||||
.unwrap();
|
Ok(Some(ptr.as_base_value().into()))
|
||||||
let b = ctx.builder
|
|
||||||
.build_in_bounds_gep(
|
|
||||||
ptr,
|
|
||||||
&[zero, int32.const_int(1, false)],
|
|
||||||
"end",
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
let c = ctx.builder.build_in_bounds_gep(
|
|
||||||
ptr,
|
|
||||||
&[zero, int32.const_int(2, false)],
|
|
||||||
"step",
|
|
||||||
).unwrap();
|
|
||||||
ctx.builder.build_store(a, start).unwrap();
|
|
||||||
ctx.builder.build_store(b, stop).unwrap();
|
|
||||||
ctx.builder.build_store(c, step).unwrap();
|
|
||||||
}
|
|
||||||
Ok(Some(ptr.into()))
|
|
||||||
},
|
},
|
||||||
)))),
|
)))),
|
||||||
loc: None,
|
loc: None,
|
||||||
|
|
Loading…
Reference in New Issue