diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs index 85b963bb..715ef6d4 100644 --- a/nac3core/src/codegen/mod.rs +++ b/nac3core/src/codegen/mod.rs @@ -44,6 +44,7 @@ pub mod llvm_intrinsics; pub mod model; pub mod numpy; pub mod stmt; +pub mod structs; #[cfg(test)] mod test; diff --git a/nac3core/src/codegen/structs/cslice.rs b/nac3core/src/codegen/structs/cslice.rs new file mode 100644 index 00000000..38e177bb --- /dev/null +++ b/nac3core/src/codegen/structs/cslice.rs @@ -0,0 +1,50 @@ +use crate::codegen::{model::*, CodeGenContext}; + +/// Fields of [`CSlice<'ctx>`]. +pub struct CSliceFields<'ctx> { + /// Pointer to the data. + pub base: Field>, + /// Number of bytes of the data. + pub len: Field>, +} + +/// See . +/// +/// Additionally, see ) +/// for ARTIQ-specific notes. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct CSlice<'ctx> { + pub sizet: SizeTModel<'ctx>, +} + +impl<'ctx> StructKind<'ctx> for CSlice<'ctx> { + type Fields = CSliceFields<'ctx>; + + fn struct_name(&self) -> &'static str { + "CSlice" + } + + fn build_fields(&self, builder: &mut FieldBuilder<'ctx>) -> Self::Fields { + Self::Fields { + base: builder.add_field_auto("content"), + len: builder.add_field("length", self.sizet), + } + } +} + +impl<'ctx> StructModel> { + /// Create a [`CSlice`]. + /// + /// `base` and `len` must be LLVM global constants. + pub fn create_const( + &self, + ctx: &CodeGenContext<'ctx, '_>, + base: Pointer<'ctx, ByteModel>, + len: SizeT<'ctx>, + ) -> Struct<'ctx, CSlice<'ctx>> { + let value = self + .get_struct_type(ctx.ctx) + .const_named_struct(&[base.value.into(), len.value.into()]); + self.believe_value(value) + } +} diff --git a/nac3core/src/codegen/structs/exception.rs b/nac3core/src/codegen/structs/exception.rs new file mode 100644 index 00000000..62cc3812 --- /dev/null +++ b/nac3core/src/codegen/structs/exception.rs @@ -0,0 +1,78 @@ +use crate::codegen::model::*; + +use super::cslice::CSlice; + +/// The LLVM int type of an Exception ID. +pub type ExceptionId = Int32; + +/// Fields of [`Exception<'ctx>`] +/// +/// The definition came from `pub struct Exception<'a>` in +/// . +pub struct ExceptionFields<'ctx> { + /// nac3core's ID of the exception + pub exception_id: Field>, + /// The name of the file this `Exception` was raised in. + pub filename: Field>>, + /// The line number in the file this `Exception` was raised in. + pub line: Field>, + /// The column number in the file this `Exception` was raised in. + pub column: Field>, + /// The name of the Python function this `Exception` was raised in. + pub function_name: Field>>, + /// The message of this Exception. + /// + /// The message can optionally contain integer parameters `{0}`, `{1}`, and `{2}` in its string, + /// where they will be substituted by `params[0]`, `params[1]`, and `params[2]` respectively (as `int64_t`s). + /// Here is an example: + /// + /// ```ignore + /// "Index {0} is out of bounds! List only has {1} element(s)." + /// ``` + /// + /// In this case, `params[0]` and `params[1]` must be specified, and `params[2]` is ***unused***. + /// Having only 3 parameters is a constraint in ARTIQ. + pub message: Field>>, + pub params: [Field>; 3], +} + +/// nac3core & ARTIQ's Exception +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Exception<'ctx> { + /// The `SizeT` type of this string. + pub sizet: SizeTModel<'ctx>, +} + +impl<'ctx> StructKind<'ctx> for Exception<'ctx> { + type Fields = ExceptionFields<'ctx>; + + fn struct_name(&self) -> &'static str { + "Exception" + } + + fn build_fields(&self, builder: &mut FieldBuilder<'ctx>) -> Self::Fields { + let str = StructModel(CSlice { sizet: self.sizet }); + + let exception_id = builder.add_field_auto("exception_id"); + let file_name = builder.add_field("file_name", str); + let line = builder.add_field_auto("line"); + let column = builder.add_field_auto("column"); + let function_name = builder.add_field("function_name", str); + let message = builder.add_field("message", str); + let params = [ + builder.add_field_auto("param0"), + builder.add_field_auto("param1"), + builder.add_field_auto("param2"), + ]; + + Self::Fields { + exception_id, + filename: file_name, + line, + column, + function_name, + message, + params, + } + } +} diff --git a/nac3core/src/codegen/structs/mod.rs b/nac3core/src/codegen/structs/mod.rs new file mode 100644 index 00000000..14b596fb --- /dev/null +++ b/nac3core/src/codegen/structs/mod.rs @@ -0,0 +1,2 @@ +pub mod cslice; +pub mod exception;