diff options
Diffstat (limited to 'library/stdarch/crates/intrinsic-test/src/argument.rs')
-rw-r--r-- | library/stdarch/crates/intrinsic-test/src/argument.rs | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/library/stdarch/crates/intrinsic-test/src/argument.rs b/library/stdarch/crates/intrinsic-test/src/argument.rs new file mode 100644 index 000000000..f4cb77992 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/argument.rs @@ -0,0 +1,139 @@ +use std::ops::Range; + +use crate::types::IntrinsicType; +use crate::Language; + +/// An argument for the intrinsic. +#[derive(Debug, PartialEq, Clone)] +pub struct Argument { + /// The argument's index in the intrinsic function call. + pub pos: usize, + /// The argument name. + pub name: String, + /// The type of the argument. + pub ty: IntrinsicType, + /// Any constraints that are on this argument + pub constraints: Vec<Constraint>, +} + +#[derive(Debug, PartialEq, Clone)] +pub enum Constraint { + Equal(i64), + Range(Range<i64>), +} + +impl Constraint { + pub fn to_range(&self) -> Range<i64> { + match self { + Constraint::Equal(eq) => *eq..*eq + 1, + Constraint::Range(range) => range.clone(), + } + } +} + +impl Argument { + fn to_c_type(&self) -> String { + self.ty.c_type() + } + + fn is_simd(&self) -> bool { + self.ty.is_simd() + } + + pub fn is_ptr(&self) -> bool { + self.ty.is_ptr() + } + + pub fn has_constraint(&self) -> bool { + !self.constraints.is_empty() + } +} + +#[derive(Debug, PartialEq, Clone)] +pub struct ArgumentList { + pub args: Vec<Argument>, +} + +impl ArgumentList { + /// Converts the argument list into the call parameters for a C function call. + /// e.g. this would generate something like `a, &b, c` + pub fn as_call_param_c(&self) -> String { + self.args + .iter() + .map(|arg| match arg.ty { + IntrinsicType::Ptr { .. } => { + format!("&{}", arg.name) + } + IntrinsicType::Type { .. } => arg.name.clone(), + }) + .collect::<Vec<String>>() + .join(", ") + } + + /// Converts the argument list into the call parameters for a Rust function. + /// e.g. this would generate something like `a, b, c` + pub fn as_call_param_rust(&self) -> String { + self.args + .iter() + .filter(|a| !a.has_constraint()) + .map(|arg| arg.name.clone()) + .collect::<Vec<String>>() + .join(", ") + } + + pub fn as_constraint_parameters_rust(&self) -> String { + self.args + .iter() + .filter(|a| a.has_constraint()) + .map(|arg| arg.name.clone()) + .collect::<Vec<String>>() + .join(", ") + } + + /// Creates a line that initializes this argument for C code. + /// e.g. `int32x2_t a = { 0x1, 0x2 };` + pub fn init_random_values_c(&self, pass: usize) -> String { + self.iter() + .filter_map(|arg| { + (!arg.has_constraint()).then(|| { + format!( + "{ty} {name} = {{ {values} }};", + ty = arg.to_c_type(), + name = arg.name, + values = arg.ty.populate_random(pass, &Language::C) + ) + }) + }) + .collect::<Vec<_>>() + .join("\n ") + } + + /// Creates a line that initializes this argument for Rust code. + /// e.g. `let a = transmute([0x1, 0x2]);` + pub fn init_random_values_rust(&self, pass: usize) -> String { + self.iter() + .filter_map(|arg| { + (!arg.has_constraint()).then(|| { + if arg.is_simd() { + format!( + "let {name} = ::std::mem::transmute([{values}]);", + name = arg.name, + values = arg.ty.populate_random(pass, &Language::Rust), + ) + } else { + format!( + "let {name} = {value};", + name = arg.name, + value = arg.ty.populate_random(pass, &Language::Rust) + ) + } + }) + }) + .collect::<Vec<_>>() + .join("\n ") + } + + pub fn iter(&self) -> std::slice::Iter<'_, Argument> { + self.args.iter() + } +} |