1
0
forked from M-Labs/nac3

core: move Slice and RustSlice to its own file & genericize their IntKind

This commit is contained in:
lyken 2024-08-25 19:49:26 +08:00
parent f698b0c1fa
commit a6e1d354b6
No known key found for this signature in database
GPG Key ID: 3BD5FC6AC8325DD8
3 changed files with 91 additions and 78 deletions

View File

@ -4,5 +4,6 @@ pub mod exception;
pub mod list;
pub mod ndarray;
pub mod range;
pub mod slice;
pub mod str;
pub mod tuple;

View File

@ -1,4 +1,9 @@
use crate::codegen::{irrt::call_nac3_ndarray_index, model::*, CodeGenContext, CodeGenerator};
use crate::codegen::{
irrt::call_nac3_ndarray_index,
model::*,
object::slice::{RustSlice, Slice},
CodeGenContext, CodeGenerator,
};
use super::NDArrayObject;
@ -23,86 +28,11 @@ impl<'ctx> StructKind<'ctx> for NDIndex {
}
}
/// Fields of [`Slice`]
#[derive(Debug, Clone)]
pub struct SliceFields<'ctx, F: FieldTraversal<'ctx>> {
pub start_defined: F::Out<Int<Bool>>,
pub start: F::Out<Int<Int32>>,
pub stop_defined: F::Out<Int<Bool>>,
pub stop: F::Out<Int<Int32>>,
pub step_defined: F::Out<Int<Bool>>,
pub step: F::Out<Int<Int32>>,
}
/// An IRRT representation of an (unresolved) slice.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Slice;
impl<'ctx> StructKind<'ctx> for Slice {
type Fields<F: FieldTraversal<'ctx>> = SliceFields<'ctx, F>;
fn traverse_fields<F: FieldTraversal<'ctx>>(&self, traversal: &mut F) -> Self::Fields<F> {
Self::Fields {
start_defined: traversal.add_auto("start_defined"),
start: traversal.add_auto("start"),
stop_defined: traversal.add_auto("stop_defined"),
stop: traversal.add_auto("stop"),
step_defined: traversal.add_auto("step_defined"),
step: traversal.add_auto("step"),
}
}
}
/// A convenience structure to prepare a [`Slice`].
#[derive(Debug, Clone)]
pub struct RustSlice<'ctx> {
pub start: Option<Instance<'ctx, Int<Int32>>>,
pub stop: Option<Instance<'ctx, Int<Int32>>>,
pub step: Option<Instance<'ctx, Int<Int32>>>,
}
impl<'ctx> RustSlice<'ctx> {
/// Write the contents to an LLVM [`Slice`].
pub fn write_to_slice<G: CodeGenerator + ?Sized>(
&self,
generator: &mut G,
ctx: &CodeGenContext<'ctx, '_>,
dst_slice_ptr: Instance<'ctx, Ptr<Struct<Slice>>>,
) {
let false_ = Int(Bool).const_false(generator, ctx.ctx);
let true_ = Int(Bool).const_true(generator, ctx.ctx);
match self.start {
Some(start) => {
dst_slice_ptr.gep(ctx, |f| f.start_defined).store(ctx, true_);
dst_slice_ptr.gep(ctx, |f| f.start).store(ctx, start);
}
None => dst_slice_ptr.gep(ctx, |f| f.start_defined).store(ctx, false_),
}
match self.stop {
Some(stop) => {
dst_slice_ptr.gep(ctx, |f| f.stop_defined).store(ctx, true_);
dst_slice_ptr.gep(ctx, |f| f.stop).store(ctx, stop);
}
None => dst_slice_ptr.gep(ctx, |f| f.stop_defined).store(ctx, false_),
}
match self.step {
Some(step) => {
dst_slice_ptr.gep(ctx, |f| f.step_defined).store(ctx, true_);
dst_slice_ptr.gep(ctx, |f| f.step).store(ctx, step);
}
None => dst_slice_ptr.gep(ctx, |f| f.step_defined).store(ctx, false_),
}
}
}
// A convenience enum to prepare an [`NDIndex`].
#[derive(Debug, Clone)]
pub enum RustNDIndex<'ctx> {
SingleElement(Instance<'ctx, Int<Int32>>), // TODO: To be SizeT
Slice(RustSlice<'ctx>),
Slice(RustSlice<'ctx, Int32>), // TODO: To be SizeT
NewAxis,
Ellipsis,
}
@ -143,7 +73,7 @@ impl<'ctx> RustNDIndex<'ctx> {
.store(ctx, index_ptr.pointer_cast(generator, ctx, Int(Byte)));
}
RustNDIndex::Slice(in_rust_slice) => {
let user_slice_ptr = Struct(Slice).alloca(generator, ctx);
let user_slice_ptr = Struct(Slice(Int32)).alloca(generator, ctx);
in_rust_slice.write_to_slice(generator, ctx, user_slice_ptr);
dst_ndindex_ptr

View File

@ -0,0 +1,82 @@
use crate::codegen::{model::*, CodeGenContext, CodeGenerator};
/// Fields of [`Slice`]
#[derive(Debug, Clone)]
pub struct SliceFields<'ctx, F: FieldTraversal<'ctx>, N: IntKind<'ctx>> {
pub start_defined: F::Out<Int<Bool>>,
pub start: F::Out<Int<N>>,
pub stop_defined: F::Out<Int<Bool>>,
pub stop: F::Out<Int<N>>,
pub step_defined: F::Out<Int<Bool>>,
pub step: F::Out<Int<N>>,
}
/// An IRRT representation of an (unresolved) slice.
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
pub struct Slice<N>(pub N);
impl<'ctx, N: IntKind<'ctx>> StructKind<'ctx> for Slice<N> {
type Fields<F: FieldTraversal<'ctx>> = SliceFields<'ctx, F, N>;
fn traverse_fields<F: FieldTraversal<'ctx>>(&self, traversal: &mut F) -> Self::Fields<F> {
Self::Fields {
start_defined: traversal.add_auto("start_defined"),
start: traversal.add("start", Int(self.0)),
stop_defined: traversal.add_auto("stop_defined"),
stop: traversal.add("stop", Int(self.0)),
step_defined: traversal.add_auto("step_defined"),
step: traversal.add("step", Int(self.0)),
}
}
}
/// A Rust structure that has [`Slice`] utilities and looks like a [`Slice`] but
/// `start`, `stop` and `step` are held by LLVM registers only and possibly
/// [`Option::None`] if unspecified.
///
/// This structure exists because many implementations use [`Slice`] utilities but
/// it might not be good to alloca an actual [`Slice`] value on the stack in order
/// to perform calculations.
#[derive(Debug, Clone)]
pub struct RustSlice<'ctx, N: IntKind<'ctx>> {
pub start: Option<Instance<'ctx, Int<N>>>,
pub stop: Option<Instance<'ctx, Int<N>>>,
pub step: Option<Instance<'ctx, Int<N>>>,
}
impl<'ctx, N: IntKind<'ctx>> RustSlice<'ctx, N> {
/// Write the contents to an LLVM [`Slice`].
pub fn write_to_slice<G: CodeGenerator + ?Sized>(
&self,
generator: &mut G,
ctx: &CodeGenContext<'ctx, '_>,
dst_slice_ptr: Instance<'ctx, Ptr<Struct<Slice<N>>>>,
) {
let false_ = Int(Bool).const_false(generator, ctx.ctx);
let true_ = Int(Bool).const_true(generator, ctx.ctx);
match self.start {
Some(start) => {
dst_slice_ptr.gep(ctx, |f| f.start_defined).store(ctx, true_);
dst_slice_ptr.gep(ctx, |f| f.start).store(ctx, start);
}
None => dst_slice_ptr.gep(ctx, |f| f.start_defined).store(ctx, false_),
}
match self.stop {
Some(stop) => {
dst_slice_ptr.gep(ctx, |f| f.stop_defined).store(ctx, true_);
dst_slice_ptr.gep(ctx, |f| f.stop).store(ctx, stop);
}
None => dst_slice_ptr.gep(ctx, |f| f.stop_defined).store(ctx, false_),
}
match self.step {
Some(step) => {
dst_slice_ptr.gep(ctx, |f| f.step_defined).store(ctx, true_);
dst_slice_ptr.gep(ctx, |f| f.step).store(ctx, step);
}
None => dst_slice_ptr.gep(ctx, |f| f.step_defined).store(ctx, false_),
}
}
}