forked from M-Labs/nac3
trait bound everything
This commit is contained in:
parent
0c73eecc19
commit
44ee84b1d0
|
@ -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<Len, Item> {
|
||||
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<Len, Item> {
|
||||
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<Len,
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ctx, Len: ArrayLen, Item: Model<'ctx>> Model<'ctx> for Array<Len, Item> {
|
||||
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<Array<Len, Item>>> {
|
||||
impl<'ctx, Len: ArrayLen, Item: Model<'ctx>> Instance<'ctx, Ptr<Array<'ctx, Len, Item>>> {
|
||||
/// 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<Array<Len, Item>
|
|||
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<Item>> {
|
||||
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);
|
||||
|
|
|
@ -154,7 +154,7 @@ pub trait Model<'ctx>: fmt::Debug + Clone + Copy + ModelBase<'ctx> {
|
|||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
) -> Instance<'ctx, Ptr<Self>> {
|
||||
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<Self>> {
|
||||
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<G: CodeGenerator + ?Sized>(
|
||||
|
@ -177,7 +177,7 @@ pub trait Model<'ctx>: fmt::Debug + Clone + Copy + ModelBase<'ctx> {
|
|||
) -> Result<Instance<'ctx, Ptr<Self>>, 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<G: CodeGenerator + ?Sized>(
|
||||
|
@ -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<AnyLen, Self>> {
|
||||
) -> 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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<N>(pub N);
|
||||
pub struct Float<'ctx, N: FloatKind<'ctx>> {
|
||||
kind: N,
|
||||
_phantom: PhantomData<&'ctx ()>,
|
||||
}
|
||||
|
||||
impl<'ctx, N: FloatKind<'ctx>> ModelBase<'ctx> for Float<N> {
|
||||
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<N> {
|
|||
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<N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ctx, N: FloatKind<'ctx>> Model<'ctx> for Float<N> {
|
||||
impl<'ctx, N: FloatKind<'ctx>> Model<'ctx> for Float<'ctx, N> {
|
||||
type Value = FloatValue<'ctx>;
|
||||
type Type = FloatType<'ctx>;
|
||||
}
|
||||
|
|
|
@ -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<N>(pub N);
|
||||
pub struct Int<'ctx, N: IntKind<'ctx>> {
|
||||
kind: N,
|
||||
_phantom: PhantomData<&'ctx ()>,
|
||||
}
|
||||
|
||||
impl<'ctx, N: IntKind<'ctx>> ModelBase<'ctx> for Int<N> {
|
||||
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<N> {
|
|||
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<N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ctx, N: IntKind<'ctx>> Model<'ctx> for Int<N> {
|
||||
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<N> {
|
||||
impl<'ctx, N: IntKind<'ctx>> Int<'ctx, N> {
|
||||
pub fn new(kind: N) -> Self {
|
||||
Int { kind, _phantom: PhantomData }
|
||||
}
|
||||
|
||||
pub fn const_int<G: CodeGenerator + ?Sized>(
|
||||
&self,
|
||||
generator: &mut G,
|
||||
|
@ -146,7 +153,10 @@ impl<'ctx, N: IntKind<'ctx>> Int<N> {
|
|||
) -> 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<N> {
|
|||
) -> 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<N> {
|
|||
) -> 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<N> {
|
|||
) -> 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<N> {
|
|||
) -> 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<N> {
|
|||
) -> 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<N> {
|
|||
) -> 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<N> {
|
|||
) -> 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<N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Int<Bool> {
|
||||
impl<'ctx> Int<'ctx, Bool> {
|
||||
#[must_use]
|
||||
pub fn const_false<'ctx, G: CodeGenerator + ?Sized>(
|
||||
pub fn const_false<G: CodeGenerator + ?Sized>(
|
||||
&self,
|
||||
generator: &mut G,
|
||||
ctx: &'ctx Context,
|
||||
|
@ -280,7 +296,7 @@ impl Int<Bool> {
|
|||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn const_true<'ctx, G: CodeGenerator + ?Sized>(
|
||||
pub fn const_true<G: CodeGenerator + ?Sized>(
|
||||
&self,
|
||||
generator: &mut G,
|
||||
ctx: &'ctx Context,
|
||||
|
@ -289,14 +305,14 @@ impl Int<Bool> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int<N>> {
|
||||
impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int<'ctx, N>> {
|
||||
pub fn s_extend_or_bit_cast<NewN: IntKind<'ctx>, G: CodeGenerator + ?Sized>(
|
||||
&self,
|
||||
generator: &mut G,
|
||||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
to_int_kind: NewN,
|
||||
) -> Instance<'ctx, Int<NewN>> {
|
||||
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<NewN: IntKind<'ctx>, G: CodeGenerator + ?Sized>(
|
||||
|
@ -304,8 +320,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int<N>> {
|
|||
generator: &mut G,
|
||||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
to_int_kind: NewN,
|
||||
) -> Instance<'ctx, Int<NewN>> {
|
||||
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<NewN: IntKind<'ctx>, G: CodeGenerator + ?Sized>(
|
||||
|
@ -313,8 +329,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int<N>> {
|
|||
generator: &mut G,
|
||||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
to_int_kind: NewN,
|
||||
) -> Instance<'ctx, Int<NewN>> {
|
||||
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<NewN: IntKind<'ctx>, G: CodeGenerator + ?Sized>(
|
||||
|
@ -322,8 +338,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int<N>> {
|
|||
generator: &mut G,
|
||||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
to_int_kind: NewN,
|
||||
) -> Instance<'ctx, Int<NewN>> {
|
||||
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<NewN: IntKind<'ctx>, G: CodeGenerator + ?Sized>(
|
||||
|
@ -331,8 +347,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int<N>> {
|
|||
generator: &mut G,
|
||||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
to_int_kind: NewN,
|
||||
) -> Instance<'ctx, Int<NewN>> {
|
||||
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<NewN: IntKind<'ctx>, G: CodeGenerator + ?Sized>(
|
||||
|
@ -340,8 +356,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int<N>> {
|
|||
generator: &mut G,
|
||||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
to_int_kind: NewN,
|
||||
) -> Instance<'ctx, Int<NewN>> {
|
||||
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<NewN: IntKind<'ctx>, G: CodeGenerator + ?Sized>(
|
||||
|
@ -349,8 +365,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int<N>> {
|
|||
generator: &mut G,
|
||||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
to_int_kind: NewN,
|
||||
) -> Instance<'ctx, Int<NewN>> {
|
||||
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<NewN: IntKind<'ctx>, G: CodeGenerator + ?Sized>(
|
||||
|
@ -358,8 +374,8 @@ impl<'ctx, N: IntKind<'ctx>> Instance<'ctx, Int<N>> {
|
|||
generator: &mut G,
|
||||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
to_int_kind: NewN,
|
||||
) -> Instance<'ctx, Int<NewN>> {
|
||||
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<N>> {
|
|||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
op: IntPredicate,
|
||||
other: Self,
|
||||
) -> Instance<'ctx, Int<Bool>> {
|
||||
) -> 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) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Item>(pub Item);
|
||||
pub struct Ptr<Item> {
|
||||
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<Item> Ptr<Item> {
|
||||
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<Item> {
|
||||
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<Item> {
|
|||
|
||||
// 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<Item>> {
|
|||
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<Item>> {
|
|||
new_item: NewItem,
|
||||
) -> Instance<'ctx, Ptr<NewItem>> {
|
||||
// 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<Bool>> {
|
||||
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<Bool>> {
|
||||
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<Item>> {
|
|||
) {
|
||||
// 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
|
||||
|
|
|
@ -79,23 +79,14 @@ pub trait StructKind<'ctx>: fmt::Debug + Clone + Copy {
|
|||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct Struct<S>(pub S);
|
||||
|
||||
impl<'ctx, S: StructKind<'ctx>> Struct<S> {
|
||||
pub fn const_struct<G: CodeGenerator + ?Sized>(
|
||||
&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<S> {
|
||||
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<S> {
|
|||
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<S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'ctx, S: StructKind<'ctx>> Model<'ctx> for Struct<S> {
|
||||
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<S>> {
|
||||
impl<'ctx, S: StructKind<'ctx>> Struct<'ctx, S> {
|
||||
pub fn new(kind: S) -> Self {
|
||||
Struct { kind, _phantom: PhantomData }
|
||||
}
|
||||
|
||||
pub fn const_struct<G: CodeGenerator + ?Sized>(
|
||||
&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<G: CodeGenerator + ?Sized, M, GetField>(
|
||||
&self,
|
||||
|
@ -149,13 +156,13 @@ impl<'ctx, S: StructKind<'ctx>> Instance<'ctx, Struct<S>> {
|
|||
M: Model<'ctx>,
|
||||
GetField: FnOnce(S::Fields) -> Field<M>,
|
||||
{
|
||||
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<Struct<S>>> {
|
||||
impl<'ctx, S: StructKind<'ctx>> Instance<'ctx, Ptr<Struct<'ctx, S>>> {
|
||||
/// Get a pointer to a field with [`Builder::build_in_bounds_gep`].
|
||||
pub fn gep<M, GetField>(
|
||||
&self,
|
||||
|
@ -166,7 +173,7 @@ impl<'ctx, S: StructKind<'ctx>> Instance<'ctx, Ptr<Struct<S>>> {
|
|||
M: Model<'ctx>,
|
||||
GetField: FnOnce(S::Fields) -> Field<M>,
|
||||
{
|
||||
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<Struct<S>>> {
|
|||
.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<Struct<S>>> {
|
|||
// Example: NDArray.
|
||||
//
|
||||
// Compared to List, it has no generic models.
|
||||
pub struct NDArrayFields {
|
||||
data: Field<Ptr<Int<Byte>>>,
|
||||
itemsize: Field<Int<SizeT>>,
|
||||
ndims: Field<Int<SizeT>>,
|
||||
shape: Field<Ptr<Int<SizeT>>>,
|
||||
strides: Field<Ptr<Int<SizeT>>>,
|
||||
pub struct NDArrayFields<'ctx> {
|
||||
data: Field<Ptr<Int<'ctx, Byte>>>,
|
||||
itemsize: Field<Int<'ctx, SizeT>>,
|
||||
ndims: Field<Int<'ctx, SizeT>>,
|
||||
shape: Field<Ptr<Int<'ctx, SizeT>>>,
|
||||
strides: Field<Ptr<Int<'ctx, SizeT>>>,
|
||||
}
|
||||
|
||||
#[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<Ptr<Item>>,
|
||||
len: Field<Int<SizeT>>,
|
||||
len: Field<Int<'ctx, SizeT>>,
|
||||
_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,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue