diff --git a/nac3core/src/codegen/object/mod.rs b/nac3core/src/codegen/object/mod.rs index 98574036..0235d3b9 100644 --- a/nac3core/src/codegen/object/mod.rs +++ b/nac3core/src/codegen/object/mod.rs @@ -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; diff --git a/nac3core/src/codegen/object/ndarray/indexing.rs b/nac3core/src/codegen/object/ndarray/indexing.rs index ae8b2d66..c99fb92f 100644 --- a/nac3core/src/codegen/object/ndarray/indexing.rs +++ b/nac3core/src/codegen/object/ndarray/indexing.rs @@ -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>, - pub start: F::Out>, - pub stop_defined: F::Out>, - pub stop: F::Out>, - pub step_defined: F::Out>, - pub step: F::Out>, -} - -/// 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> = SliceFields<'ctx, F>; - - fn traverse_fields>(&self, traversal: &mut F) -> Self::Fields { - 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>>, - pub stop: Option>>, - pub step: Option>>, -} - -impl<'ctx> RustSlice<'ctx> { - /// Write the contents to an LLVM [`Slice`]. - pub fn write_to_slice( - &self, - generator: &mut G, - ctx: &CodeGenContext<'ctx, '_>, - dst_slice_ptr: Instance<'ctx, Ptr>>, - ) { - 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>), // 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 diff --git a/nac3core/src/codegen/object/slice.rs b/nac3core/src/codegen/object/slice.rs new file mode 100644 index 00000000..b34961e5 --- /dev/null +++ b/nac3core/src/codegen/object/slice.rs @@ -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>, + pub start: F::Out>, + pub stop_defined: F::Out>, + pub stop: F::Out>, + pub step_defined: F::Out>, + pub step: F::Out>, +} + +/// An IRRT representation of an (unresolved) slice. +#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] +pub struct Slice(pub N); + +impl<'ctx, N: IntKind<'ctx>> StructKind<'ctx> for Slice { + type Fields> = SliceFields<'ctx, F, N>; + + fn traverse_fields>(&self, traversal: &mut F) -> Self::Fields { + 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>>, + pub stop: Option>>, + pub step: Option>>, +} + +impl<'ctx, N: IntKind<'ctx>> RustSlice<'ctx, N> { + /// Write the contents to an LLVM [`Slice`]. + pub fn write_to_slice( + &self, + generator: &mut G, + ctx: &CodeGenContext<'ctx, '_>, + dst_slice_ptr: Instance<'ctx, Ptr>>>, + ) { + 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_), + } + } +}