diff --git a/nac3core/src/codegen/model/array.rs b/nac3core/src/codegen/model/array.rs index 2f0d6517..03157970 100644 --- a/nac3core/src/codegen/model/array.rs +++ b/nac3core/src/codegen/model/array.rs @@ -1,4 +1,4 @@ -use std::fmt; +use std::{fmt, marker::PhantomData}; use inkwell::{ context::Context, @@ -39,14 +39,21 @@ impl ArrayLen for AnyLen { /// /// `Len` should be of a [`LenKind`] and `Item` should be a of [`Model`]. #[derive(Debug, Clone, Copy, Default)] -pub struct Array { +pub struct Array<'ctx, Len: ArrayLen, Item: ModelBase<'ctx>> { /// Length of this array. pub len: Len, /// [`Model`] of the array items. pub item: Item, + pub _phantom: PhantomData<&'ctx ()>, } -impl<'ctx, Len: ArrayLen, Item: ModelBase<'ctx>> ModelBase<'ctx> for Array { +impl<'ctx, Len: ArrayLen, Item: ModelBase<'ctx>> Array<'ctx, Len, Item> { + pub fn new(len: Len, item: Item) -> Self { + Array { len, item, _phantom: PhantomData } + } +} + +impl<'ctx, Len: ArrayLen, Item: ModelBase<'ctx>> ModelBase<'ctx> for Array<'ctx, Len, Item> { fn llvm_type_impl(&self, size_t: IntType<'ctx>, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> { let item = self.item.llvm_type_impl(size_t, ctx); item.array_type(self.len.length()).into() @@ -78,12 +85,12 @@ impl<'ctx, Len: ArrayLen, Item: ModelBase<'ctx>> ModelBase<'ctx> for Array> Model<'ctx> for Array { +impl<'ctx, Len: ArrayLen, Item: Model<'ctx>> Model<'ctx> for Array<'ctx, Len, Item> { type Type = ArrayType<'ctx>; type Value = ArrayValue<'ctx>; } -impl<'ctx, Len: ArrayLen, Item: Model<'ctx>> Instance<'ctx, Ptr>> { +impl<'ctx, Len: ArrayLen, Item: Model<'ctx>> Instance<'ctx, Ptr>> { /// Get the pointer to the `i`-th (0-based) array element. pub fn gep( &self, @@ -93,15 +100,15 @@ impl<'ctx, Len: ArrayLen, Item: Model<'ctx>> Instance<'ctx, Ptr let zero = ctx.ctx.i64_type().const_zero(); let ptr = unsafe { ctx.builder.build_in_bounds_gep(self.value, &[zero, i], "").unwrap() }; - unsafe { Ptr(self.model.0.item).believe_value(ptr) } + unsafe { Ptr::new(self.model.item.item).believe_value(ptr) } } /// Like `gep` but `i` is a constant. pub fn gep_const(&self, ctx: &CodeGenContext<'ctx, '_>, i: u64) -> Instance<'ctx, Ptr> { assert!( - i < u64::from(self.model.0.len.length()), + i < u64::from(self.model.item.len.length()), "Index {i} is out of bounds. Array length = {}", - self.model.0.len.length() + self.model.item.len.length() ); let i = ctx.ctx.i64_type().const_int(i, true); diff --git a/nac3core/src/codegen/model/core.rs b/nac3core/src/codegen/model/core.rs index 681833b6..8a556770 100644 --- a/nac3core/src/codegen/model/core.rs +++ b/nac3core/src/codegen/model/core.rs @@ -154,7 +154,7 @@ pub trait Model<'ctx>: fmt::Debug + Clone + Copy + ModelBase<'ctx> { ctx: &CodeGenContext<'ctx, '_>, ) -> Instance<'ctx, Ptr> { let p = ctx.builder.build_alloca(self.llvm_type(generator, ctx.ctx), "").unwrap(); - unsafe { Ptr(*self).believe_value(p) } + unsafe { Ptr::new(*self).believe_value(p) } } // Allocate an array on the stack and return its pointer. @@ -166,7 +166,7 @@ pub trait Model<'ctx>: fmt::Debug + Clone + Copy + ModelBase<'ctx> { ) -> Instance<'ctx, Ptr> { let p = ctx.builder.build_array_alloca(self.llvm_type(generator, ctx.ctx), len, "").unwrap(); - unsafe { Ptr(*self).believe_value(p) } + unsafe { Ptr::new(*self).believe_value(p) } } fn var_alloca( @@ -177,7 +177,7 @@ pub trait Model<'ctx>: fmt::Debug + Clone + Copy + ModelBase<'ctx> { ) -> Result>, String> { let ty = self.llvm_type(generator, ctx.ctx).as_basic_type_enum(); let p = generator.gen_var_alloc(ctx, ty, name)?; - Ok(unsafe { Ptr(*self).believe_value(p) }) + Ok(unsafe { Ptr::new(*self).believe_value(p) }) } fn array_var_alloca( @@ -190,7 +190,7 @@ pub trait Model<'ctx>: fmt::Debug + Clone + Copy + ModelBase<'ctx> { // TODO: Remove ArraySliceValue let ty = self.llvm_type(generator, ctx.ctx).as_basic_type_enum(); let p = generator.gen_array_var_alloc(ctx, ty, len, name)?; - Ok(unsafe { Ptr(*self).believe_value(PointerValue::from(p)) }) + Ok(unsafe { Ptr::new(*self).believe_value(PointerValue::from(p)) }) } /// Allocate a constant array. @@ -199,7 +199,7 @@ pub trait Model<'ctx>: fmt::Debug + Clone + Copy + ModelBase<'ctx> { generator: &mut G, ctx: &'ctx Context, values: &[Instance<'ctx, Self>], - ) -> Instance<'ctx, Array> { + ) -> Instance<'ctx, Array<'ctx, AnyLen, Self>> { macro_rules! make { ($t:expr, $into_value:expr) => { $t.const_array( @@ -220,9 +220,8 @@ pub trait Model<'ctx>: fmt::Debug + Clone + Copy + ModelBase<'ctx> { BasicTypeEnum::VectorType(t) => make!(t, BasicValueEnum::into_vector_value), }; - Array { len: AnyLen(values.len() as u32), item: *self } - .check_value(generator, ctx, value) - .unwrap() + let model = Array::new(AnyLen(values.len() as u32), *self); + model.check_value(generator, ctx, value).unwrap() } } diff --git a/nac3core/src/codegen/model/float.rs b/nac3core/src/codegen/model/float.rs index 8c6d1e3e..d1aeb025 100644 --- a/nac3core/src/codegen/model/float.rs +++ b/nac3core/src/codegen/model/float.rs @@ -1,4 +1,4 @@ -use std::fmt; +use std::{fmt, marker::PhantomData}; use inkwell::{ context::Context, @@ -39,11 +39,20 @@ impl<'ctx> FloatKind<'ctx> for AnyFloat<'ctx> { } #[derive(Debug, Clone, Copy, Default)] -pub struct Float(pub N); +pub struct Float<'ctx, N: FloatKind<'ctx>> { + kind: N, + _phantom: PhantomData<&'ctx ()>, +} -impl<'ctx, N: FloatKind<'ctx>> ModelBase<'ctx> for Float { +impl<'ctx, N: FloatKind<'ctx>> Float<'ctx, N> { + pub fn new(kind: N) -> Self { + Float { kind, _phantom: PhantomData } + } +} + +impl<'ctx, N: FloatKind<'ctx>> ModelBase<'ctx> for Float<'ctx, N> { fn llvm_type_impl(&self, _size_t: IntType<'ctx>, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> { - self.0.get_float_type(ctx).into() + self.kind.get_float_type(ctx).into() } fn check_type_impl( @@ -56,7 +65,7 @@ impl<'ctx, N: FloatKind<'ctx>> ModelBase<'ctx> for Float { return Err(ModelError(format!("Expecting FloatType, but got {ty:?}"))); }; - let expected_ty = self.0.get_float_type(ctx); + let expected_ty = self.kind.get_float_type(ctx); if ty != expected_ty { return Err(ModelError(format!("Expecting {expected_ty:?}, but got {ty:?}"))); } @@ -65,7 +74,7 @@ impl<'ctx, N: FloatKind<'ctx>> ModelBase<'ctx> for Float { } } -impl<'ctx, N: FloatKind<'ctx>> Model<'ctx> for Float { +impl<'ctx, N: FloatKind<'ctx>> Model<'ctx> for Float<'ctx, N> { type Value = FloatValue<'ctx>; type Type = FloatType<'ctx>; } diff --git a/nac3core/src/codegen/model/int.rs b/nac3core/src/codegen/model/int.rs index b6facd73..3315f97b 100644 --- a/nac3core/src/codegen/model/int.rs +++ b/nac3core/src/codegen/model/int.rs @@ -1,4 +1,4 @@ -use std::{cmp::Ordering, fmt}; +use std::{cmp::Ordering, fmt, marker::PhantomData}; use inkwell::{ context::Context, @@ -66,11 +66,14 @@ impl<'ctx> IntKind<'ctx> for AnyInt<'ctx> { } #[derive(Debug, Clone, Copy, Default)] -pub struct Int(pub N); +pub struct Int<'ctx, N: IntKind<'ctx>> { + kind: N, + _phantom: PhantomData<&'ctx ()>, +} -impl<'ctx, N: IntKind<'ctx>> ModelBase<'ctx> for Int { +impl<'ctx, N: IntKind<'ctx>> ModelBase<'ctx> for Int<'ctx, N> { fn llvm_type_impl(&self, size_t: IntType<'ctx>, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> { - self.0.get_int_type(size_t, ctx).into() + self.kind.get_int_type(size_t, ctx).into() } fn check_type_impl( @@ -83,7 +86,7 @@ impl<'ctx, N: IntKind<'ctx>> ModelBase<'ctx> for Int { return Err(ModelError(format!("Expecting IntType, but got {ty:?}"))); }; - let exp_ty = self.0.get_int_type(size_t, ctx); + let exp_ty = self.kind.get_int_type(size_t, ctx); if ty.get_bit_width() != exp_ty.get_bit_width() { return Err(ModelError(format!( "Expecting IntType to have {} bit(s), but got {} bit(s)", @@ -96,12 +99,16 @@ impl<'ctx, N: IntKind<'ctx>> ModelBase<'ctx> for Int { } } -impl<'ctx, N: IntKind<'ctx>> Model<'ctx> for Int { +impl<'ctx, N: IntKind<'ctx>> Model<'ctx> for Int<'ctx, N> { type Type = IntType<'ctx>; type Value = IntValue<'ctx>; } -impl<'ctx, N: IntKind<'ctx>> Int { +impl<'ctx, N: IntKind<'ctx>> Int<'ctx, N> { + pub fn new(kind: N) -> Self { + Int { kind, _phantom: PhantomData } + } + pub fn const_int( &self, generator: &mut G, @@ -146,7 +153,10 @@ impl<'ctx, N: IntKind<'ctx>> Int { ) -> Instance<'ctx, Self> { assert!( value.get_type().get_bit_width() - <= self.0.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width() + <= self + .kind + .get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx) + .get_bit_width() ); let value = ctx .builder @@ -163,7 +173,7 @@ impl<'ctx, N: IntKind<'ctx>> Int { ) -> Instance<'ctx, Self> { assert!( value.get_type().get_bit_width() - < self.0.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width() + < self.kind.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width() ); let value = ctx.builder.build_int_s_extend(value, self.llvm_type(generator, ctx.ctx), "").unwrap(); @@ -178,7 +188,10 @@ impl<'ctx, N: IntKind<'ctx>> Int { ) -> Instance<'ctx, Self> { assert!( value.get_type().get_bit_width() - <= self.0.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width() + <= self + .kind + .get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx) + .get_bit_width() ); let value = ctx .builder @@ -195,7 +208,7 @@ impl<'ctx, N: IntKind<'ctx>> Int { ) -> Instance<'ctx, Self> { assert!( value.get_type().get_bit_width() - < self.0.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width() + < self.kind.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width() ); let value = ctx.builder.build_int_z_extend(value, self.llvm_type(generator, ctx.ctx), "").unwrap(); @@ -210,7 +223,10 @@ impl<'ctx, N: IntKind<'ctx>> Int { ) -> Instance<'ctx, Self> { assert!( value.get_type().get_bit_width() - >= self.0.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width() + >= self + .kind + .get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx) + .get_bit_width() ); let value = ctx .builder @@ -227,7 +243,7 @@ impl<'ctx, N: IntKind<'ctx>> Int { ) -> Instance<'ctx, Self> { assert!( value.get_type().get_bit_width() - > self.0.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width() + > self.kind.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width() ); let value = ctx.builder.build_int_truncate(value, self.llvm_type(generator, ctx.ctx), "").unwrap(); @@ -243,7 +259,7 @@ impl<'ctx, N: IntKind<'ctx>> Int { ) -> Instance<'ctx, Self> { let their_width = value.get_type().get_bit_width(); let our_width = - self.0.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width(); + self.kind.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width(); match their_width.cmp(&our_width) { Ordering::Less => self.s_extend(generator, ctx, value), Ordering::Equal => unsafe { self.believe_value(value) }, @@ -260,7 +276,7 @@ impl<'ctx, N: IntKind<'ctx>> Int { ) -> Instance<'ctx, Self> { let their_width = value.get_type().get_bit_width(); let our_width = - self.0.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width(); + self.kind.get_int_type(generator.get_size_type(ctx.ctx), ctx.ctx).get_bit_width(); match their_width.cmp(&our_width) { Ordering::Less => self.z_extend(generator, ctx, value), Ordering::Equal => unsafe { self.believe_value(value) }, @@ -269,9 +285,9 @@ impl<'ctx, N: IntKind<'ctx>> Int { } } -impl Int { +impl<'ctx> Int<'ctx, Bool> { #[must_use] - pub fn const_false<'ctx, G: CodeGenerator + ?Sized>( + pub fn const_false( &self, generator: &mut G, ctx: &'ctx Context, @@ -280,7 +296,7 @@ impl Int { } #[must_use] - pub fn const_true<'ctx, G: CodeGenerator + ?Sized>( + pub fn const_true( &self, generator: &mut G, ctx: &'ctx Context, @@ -289,14 +305,14 @@ impl Int { } } -impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int> { +impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int<'ctx, N>> { pub fn s_extend_or_bit_cast, G: CodeGenerator + ?Sized>( &self, generator: &mut G, ctx: &CodeGenContext<'ctx, '_>, to_int_kind: NewN, - ) -> Instance<'ctx, Int> { - Int(to_int_kind).s_extend_or_bit_cast(generator, ctx, self.value) + ) -> Instance<'ctx, Int<'ctx, NewN>> { + Int::new(to_int_kind).s_extend_or_bit_cast(generator, ctx, self.value) } pub fn s_extend, G: CodeGenerator + ?Sized>( @@ -304,8 +320,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int> { generator: &mut G, ctx: &CodeGenContext<'ctx, '_>, to_int_kind: NewN, - ) -> Instance<'ctx, Int> { - Int(to_int_kind).s_extend(generator, ctx, self.value) + ) -> Instance<'ctx, Int<'ctx, NewN>> { + Int::new(to_int_kind).s_extend(generator, ctx, self.value) } pub fn z_extend_or_bit_cast, G: CodeGenerator + ?Sized>( @@ -313,8 +329,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int> { generator: &mut G, ctx: &CodeGenContext<'ctx, '_>, to_int_kind: NewN, - ) -> Instance<'ctx, Int> { - Int(to_int_kind).z_extend_or_bit_cast(generator, ctx, self.value) + ) -> Instance<'ctx, Int<'ctx, NewN>> { + Int::new(to_int_kind).z_extend_or_bit_cast(generator, ctx, self.value) } pub fn z_extend, G: CodeGenerator + ?Sized>( @@ -322,8 +338,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int> { generator: &mut G, ctx: &CodeGenContext<'ctx, '_>, to_int_kind: NewN, - ) -> Instance<'ctx, Int> { - Int(to_int_kind).z_extend(generator, ctx, self.value) + ) -> Instance<'ctx, Int<'ctx, NewN>> { + Int::new(to_int_kind).z_extend(generator, ctx, self.value) } pub fn truncate_or_bit_cast, G: CodeGenerator + ?Sized>( @@ -331,8 +347,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int> { generator: &mut G, ctx: &CodeGenContext<'ctx, '_>, to_int_kind: NewN, - ) -> Instance<'ctx, Int> { - Int(to_int_kind).truncate_or_bit_cast(generator, ctx, self.value) + ) -> Instance<'ctx, Int<'ctx, NewN>> { + Int::new(to_int_kind).truncate_or_bit_cast(generator, ctx, self.value) } pub fn truncate, G: CodeGenerator + ?Sized>( @@ -340,8 +356,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int> { generator: &mut G, ctx: &CodeGenContext<'ctx, '_>, to_int_kind: NewN, - ) -> Instance<'ctx, Int> { - Int(to_int_kind).truncate(generator, ctx, self.value) + ) -> Instance<'ctx, Int<'ctx, NewN>> { + Int::new(to_int_kind).truncate(generator, ctx, self.value) } pub fn s_extend_or_truncate, G: CodeGenerator + ?Sized>( @@ -349,8 +365,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int> { generator: &mut G, ctx: &CodeGenContext<'ctx, '_>, to_int_kind: NewN, - ) -> Instance<'ctx, Int> { - Int(to_int_kind).s_extend_or_truncate(generator, ctx, self.value) + ) -> Instance<'ctx, Int<'ctx, NewN>> { + Int::new(to_int_kind).s_extend_or_truncate(generator, ctx, self.value) } pub fn z_extend_or_truncate, G: CodeGenerator + ?Sized>( @@ -358,8 +374,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int> { generator: &mut G, ctx: &CodeGenContext<'ctx, '_>, to_int_kind: NewN, - ) -> Instance<'ctx, Int> { - Int(to_int_kind).z_extend_or_truncate(generator, ctx, self.value) + ) -> Instance<'ctx, Int<'ctx, NewN>> { + Int::new(to_int_kind).z_extend_or_truncate(generator, ctx, self.value) } #[must_use] @@ -385,8 +401,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int> { ctx: &CodeGenContext<'ctx, '_>, op: IntPredicate, other: Self, - ) -> Instance<'ctx, Int> { + ) -> Instance<'ctx, Int<'ctx, Bool>> { let value = ctx.builder.build_int_compare(op, self.value, other.value, "").unwrap(); - unsafe { Int(Bool).believe_value(value) } + unsafe { Int::new(Bool).believe_value(value) } } } diff --git a/nac3core/src/codegen/model/ptr.rs b/nac3core/src/codegen/model/ptr.rs index a15531f4..baff1497 100644 --- a/nac3core/src/codegen/model/ptr.rs +++ b/nac3core/src/codegen/model/ptr.rs @@ -15,14 +15,24 @@ use super::*; /// // TODO: LLVM 15: `Item` is a Rust type-hint for the LLVM type of value the `.store()/.load()` family // of functions return. If a truly opaque pointer is needed, tell the programmer to use `OpaquePtr`. +// +// NOTE: Do not put `Item: ModelBase<'ctx>`. See the LLVM 15 note above. #[derive(Debug, Clone, Copy, Default)] -pub struct Ptr(pub Item); +pub struct Ptr { + pub item: Item, +} /// An opaque pointer. Like [`Ptr`] but without any Rust type-hints about its element type. /// /// `.load()/.store()` is not available for [`Instance`]s of opaque pointers. pub type OpaquePtr = Ptr<()>; +impl Ptr { + pub fn new(item: Item) -> Self { + Ptr { item } + } +} + // TODO: LLVM 15: `Item: ModelBase<'ctx>` don't even need to be a model anymore. It will only be // a type-hint for the `.load()/.store()` functions for the `pointee_ty`. // @@ -30,7 +40,7 @@ pub type OpaquePtr = Ptr<()>; impl<'ctx, Item: ModelBase<'ctx>> ModelBase<'ctx> for Ptr { fn llvm_type_impl(&self, size_t: IntType<'ctx>, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> { // TODO: LLVM 15: ctx.ptr_type(AddressSpace::default()) - let item = self.0.llvm_type_impl(size_t, ctx); + let item = self.item.llvm_type_impl(size_t, ctx); item.ptr_type(AddressSpace::default()).into() } @@ -53,7 +63,7 @@ impl<'ctx, Item: ModelBase<'ctx>> ModelBase<'ctx> for Ptr { // TODO: inkwell `get_element_type()` will be deprecated. // Remove the check for `get_element_type()` when the time comes. - self.0 + self.item .check_type_impl(size_t, ctx, elem_ty) .map_err(|err| err.under_context("a PointerType"))?; @@ -162,7 +172,7 @@ impl<'ctx, Item: Model<'ctx>> Instance<'ctx, Ptr> { ctx: &CodeGenContext<'ctx, '_>, ) -> Instance<'ctx, Item> { let value = ctx.builder.build_load(self.value, "").unwrap(); - self.model.0.check_value(generator, ctx.ctx, value).unwrap() // If unwrap() panics, there is a logic error. + self.model.item.check_value(generator, ctx.ctx, value).unwrap() // If unwrap() panics, there is a logic error. } /// Store a value with [`inkwell::builder::Builder::build_store`]. @@ -178,19 +188,19 @@ impl<'ctx, Item: Model<'ctx>> Instance<'ctx, Ptr> { new_item: NewItem, ) -> Instance<'ctx, Ptr> { // TODO: LLVM 15: Write in an impl where `Item` does not have to be `Model<'ctx>`. - Ptr(new_item).pointer_cast(generator, ctx, self.value) + Ptr::new(new_item).pointer_cast(generator, ctx, self.value) } /// Check if the pointer is null with [`inkwell::builder::Builder::build_is_null`]. - pub fn is_null(&self, ctx: &CodeGenContext<'ctx, '_>) -> Instance<'ctx, Int> { + pub fn is_null(&self, ctx: &CodeGenContext<'ctx, '_>) -> Instance<'ctx, Int<'ctx, Bool>> { let value = ctx.builder.build_is_null(self.value, "").unwrap(); - unsafe { Int(Bool).believe_value(value) } + unsafe { Int::new(Bool).believe_value(value) } } /// Check if the pointer is not null with [`inkwell::builder::Builder::build_is_not_null`]. - pub fn is_not_null(&self, ctx: &CodeGenContext<'ctx, '_>) -> Instance<'ctx, Int> { + pub fn is_not_null(&self, ctx: &CodeGenContext<'ctx, '_>) -> Instance<'ctx, Int<'ctx, Bool>> { let value = ctx.builder.build_is_not_null(self.value, "").unwrap(); - unsafe { Int(Bool).believe_value(value) } + unsafe { Int::new(Bool).believe_value(value) } } /// `memcpy` from another pointer. @@ -203,8 +213,8 @@ impl<'ctx, Item: Model<'ctx>> Instance<'ctx, Ptr> { ) { // Force extend `num_items` and `itemsize` to `i64` so their types would match. let itemsize = self.model.size_of(generator, ctx.ctx); - let itemsize = Int(Int64).z_extend_or_truncate(generator, ctx, itemsize); - let num_items = Int(Int64).z_extend_or_truncate(generator, ctx, num_items); + let itemsize = Int::new(Int64).z_extend_or_truncate(generator, ctx, itemsize); + let num_items = Int::new(Int64).z_extend_or_truncate(generator, ctx, num_items); let totalsize = itemsize.mul(ctx, num_items); let is_volatile = ctx.ctx.bool_type().const_zero(); // is_volatile = false diff --git a/nac3core/src/codegen/model/structure.rs b/nac3core/src/codegen/model/structure.rs index 8b17aee3..76cc6bab 100644 --- a/nac3core/src/codegen/model/structure.rs +++ b/nac3core/src/codegen/model/structure.rs @@ -79,23 +79,14 @@ pub trait StructKind<'ctx>: fmt::Debug + Clone + Copy { } #[derive(Debug, Clone, Copy, Default)] -pub struct Struct(pub S); - -impl<'ctx, S: StructKind<'ctx>> Struct { - pub fn const_struct( - &self, - generator: &mut G, - ctx: &'ctx Context, - fields: &[BasicValueEnum<'ctx>], - ) -> Instance<'ctx, Self> { - let val = ctx.const_struct(fields, false); - self.check_value(generator, ctx, val).unwrap() - } +pub struct Struct<'ctx, S: StructKind<'ctx>> { + pub kind: S, + _phantom: PhantomData<&'ctx ()>, } -impl<'ctx, S: StructKind<'ctx>> ModelBase<'ctx> for Struct { +impl<'ctx, S: StructKind<'ctx>> ModelBase<'ctx> for Struct<'ctx, S> { fn llvm_type_impl(&self, size_t: IntType<'ctx>, ctx: &'ctx Context) -> BasicTypeEnum<'ctx> { - self.0.get_struct_type(size_t, ctx).as_basic_type_enum() + self.kind.get_struct_type(size_t, ctx).as_basic_type_enum() } fn check_type_impl( @@ -108,7 +99,7 @@ impl<'ctx, S: StructKind<'ctx>> ModelBase<'ctx> for Struct { return Err(ModelError(format!("Expecting StructType, but got {ty:?}"))); }; - let entries = self.0.entries(); + let entries = self.kind.entries(); let field_types = ty.get_field_types(); // Check the number of fields. @@ -132,12 +123,28 @@ impl<'ctx, S: StructKind<'ctx>> ModelBase<'ctx> for Struct { } } -impl<'ctx, S: StructKind<'ctx>> Model<'ctx> for Struct { +impl<'ctx, S: StructKind<'ctx>> Model<'ctx> for Struct<'ctx, S> { type Type = StructType<'ctx>; type Value = StructValue<'ctx>; } -impl<'ctx, S: StructKind<'ctx>> Instance<'ctx, Struct> { +impl<'ctx, S: StructKind<'ctx>> Struct<'ctx, S> { + pub fn new(kind: S) -> Self { + Struct { kind, _phantom: PhantomData } + } + + pub fn const_struct( + &self, + generator: &mut G, + ctx: &'ctx Context, + fields: &[BasicValueEnum<'ctx>], + ) -> Instance<'ctx, Self> { + let val = ctx.const_struct(fields, false); + self.check_value(generator, ctx, val).unwrap() + } +} + +impl<'ctx, S: StructKind<'ctx>> Instance<'ctx, Struct<'ctx, S>> { /// Get a field with [`StructValue::get_field_at_index`]. pub fn get_field( &self, @@ -149,13 +156,13 @@ impl<'ctx, S: StructKind<'ctx>> Instance<'ctx, Struct> { M: Model<'ctx>, GetField: FnOnce(S::Fields) -> Field, { - let field = get_field(self.model.0.fields()); + let field = get_field(self.model.kind.fields()); let val = self.value.get_field_at_index(field.gep_index).unwrap(); field.model.check_value(generator, ctx, val).unwrap() } } -impl<'ctx, S: StructKind<'ctx>> Instance<'ctx, Ptr>> { +impl<'ctx, S: StructKind<'ctx>> Instance<'ctx, Ptr>> { /// Get a pointer to a field with [`Builder::build_in_bounds_gep`]. pub fn gep( &self, @@ -166,7 +173,7 @@ impl<'ctx, S: StructKind<'ctx>> Instance<'ctx, Ptr>> { M: Model<'ctx>, GetField: FnOnce(S::Fields) -> Field, { - let field = get_field(self.model.0 .0.fields()); + let field = get_field(self.model.item.kind.fields()); let llvm_i32 = ctx.ctx.i32_type(); let ptr = unsafe { @@ -179,7 +186,7 @@ impl<'ctx, S: StructKind<'ctx>> Instance<'ctx, Ptr>> { .unwrap() }; - unsafe { Ptr(field.model).believe_value(ptr) } + unsafe { Ptr::new(field.model).believe_value(ptr) } } /// Convenience function equivalent to `.gep(...).load(...)`. @@ -215,19 +222,19 @@ impl<'ctx, S: StructKind<'ctx>> Instance<'ctx, Ptr>> { // Example: NDArray. // // Compared to List, it has no generic models. -pub struct NDArrayFields { - data: Field>>, - itemsize: Field>, - ndims: Field>, - shape: Field>>, - strides: Field>>, +pub struct NDArrayFields<'ctx> { + data: Field>>, + itemsize: Field>, + ndims: Field>, + shape: Field>>, + strides: Field>>, } #[derive(Debug, Clone, Copy, Default)] struct NDArray; impl<'ctx> StructKind<'ctx> for NDArray { - type Fields = NDArrayFields; + type Fields = NDArrayFields<'ctx>; fn iter_fields(&self, mapper: &mut FieldMapper<'ctx>) -> Self::Fields { NDArrayFields { @@ -245,7 +252,7 @@ impl<'ctx> StructKind<'ctx> for NDArray { // Compared to NDArray, it has generic models. pub struct ListFields<'ctx, Item: Model<'ctx>> { items: Field>, - len: Field>, + len: Field>, _phantom: PhantomData<&'ctx ()>, } @@ -260,7 +267,7 @@ impl<'ctx, Item: Model<'ctx> + 'ctx> StructKind<'ctx> for List<'ctx, Item> { fn iter_fields(&self, mapper: &mut FieldMapper<'ctx>) -> Self::Fields { ListFields { - items: mapper.add("items", Ptr(self.item)), + items: mapper.add("items", Ptr::new(self.item)), len: mapper.add_auto("len"), _phantom: PhantomData, }