forked from M-Labs/nac3
1
0
Fork 0

core/model: add CSlice & Exception models

This commit is contained in:
lyken 2024-07-26 13:20:06 +08:00
parent afab0a997c
commit 679315acad
4 changed files with 131 additions and 0 deletions

View File

@ -44,6 +44,7 @@ pub mod llvm_intrinsics;
pub mod model; pub mod model;
pub mod numpy; pub mod numpy;
pub mod stmt; pub mod stmt;
pub mod structs;
#[cfg(test)] #[cfg(test)]
mod test; mod test;

View File

@ -0,0 +1,50 @@
use crate::codegen::{model::*, CodeGenContext};
/// Fields of [`CSlice<'ctx>`].
pub struct CSliceFields<'ctx> {
/// Pointer to the data.
pub base: Field<PointerModel<ByteModel>>,
/// Number of bytes of the data.
pub len: Field<SizeTModel<'ctx>>,
}
/// See <https://crates.io/crates/cslice>.
///
/// Additionally, see <https://github.com/m-labs/artiq/blob/b0d2705c385f64b6e6711c1726cd9178f40b598e/artiq/firmware/libeh/eh_artiq.rs>)
/// 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<CSlice<'ctx>> {
/// 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)
}
}

View File

@ -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
/// <https://github.com/m-labs/artiq/blob/master/artiq/firmware/libeh/eh_artiq.rs>.
pub struct ExceptionFields<'ctx> {
/// nac3core's ID of the exception
pub exception_id: Field<NIntModel<ExceptionId>>,
/// The name of the file this `Exception` was raised in.
pub filename: Field<StructModel<CSlice<'ctx>>>,
/// The line number in the file this `Exception` was raised in.
pub line: Field<NIntModel<Int32>>,
/// The column number in the file this `Exception` was raised in.
pub column: Field<NIntModel<Int32>>,
/// The name of the Python function this `Exception` was raised in.
pub function_name: Field<StructModel<CSlice<'ctx>>>,
/// 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<StructModel<CSlice<'ctx>>>,
pub params: [Field<NIntModel<Int64>>; 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,
}
}
}

View File

@ -0,0 +1,2 @@
pub mod cslice;
pub mod exception;