Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crates/intrinsic-test/src/arm/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ use crate::common::intrinsic_helpers::IntrinsicType;
use std::ops::{Deref, DerefMut};

#[derive(Debug, Clone, PartialEq)]
pub struct ArmIntrinsicType(pub IntrinsicType);
pub struct ArmType(pub IntrinsicType);

impl Deref for ArmIntrinsicType {
impl Deref for ArmType {
type Target = IntrinsicType;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for ArmIntrinsicType {
impl DerefMut for ArmType {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
Expand Down
19 changes: 8 additions & 11 deletions crates/intrinsic-test/src/arm/json_parser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use super::intrinsic::ArmIntrinsicType;
use super::intrinsic::ArmType;
use crate::arm::Arm;
use crate::arm::types::parse_intrinsic_type;
use crate::common::argument::{Argument, ArgumentList};
use crate::common::constraint::Constraint;
Expand Down Expand Up @@ -59,7 +60,7 @@ struct JsonIntrinsic {

pub fn get_neon_intrinsics(
filename: &Path,
) -> Result<Vec<Intrinsic<ArmIntrinsicType>>, Box<dyn std::error::Error>> {
) -> Result<Vec<Intrinsic<Arm>>, Box<dyn std::error::Error>> {
let file = std::fs::File::open(filename)?;
let reader = std::io::BufReader::new(file);
let json: Vec<JsonIntrinsic> = serde_json::from_reader(reader).expect("Couldn't parse JSON");
Expand All @@ -79,10 +80,10 @@ pub fn get_neon_intrinsics(

fn json_to_intrinsic(
mut intr: JsonIntrinsic,
) -> Result<Intrinsic<ArmIntrinsicType>, Box<dyn std::error::Error>> {
) -> Result<Intrinsic<Arm>, Box<dyn std::error::Error>> {
let name = intr.name.replace(['[', ']'], "");

let result_ty = ArmIntrinsicType(parse_intrinsic_type(&intr.return_type.value)?);
let result_ty = ArmType(parse_intrinsic_type(&intr.return_type.value)?);

let args = intr
.arguments
Expand Down Expand Up @@ -120,12 +121,8 @@ fn json_to_intrinsic(
}
});

let mut arg = Argument::<ArmIntrinsicType>::new(
i,
String::from(arg_name),
ArmIntrinsicType(arg_ty),
constraint,
);
let mut arg =
Argument::<Arm>::new(i, String::from(arg_name), ArmType(arg_ty), constraint);

// The JSON doesn't list immediates as const
let IntrinsicType {
Expand All @@ -138,7 +135,7 @@ fn json_to_intrinsic(
})
.collect();

let arguments = ArgumentList::<ArmIntrinsicType> { args };
let arguments = ArgumentList::<Arm> { args };

Ok(Intrinsic {
name,
Expand Down
19 changes: 9 additions & 10 deletions crates/intrinsic-test/src/arm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@ mod intrinsic;
mod json_parser;
mod types;

use crate::common::SupportedArchitectureTest;
use crate::common::SupportedArchitecture;
use crate::common::cli::{CcArgStyle, ProcessedCli};
use crate::common::intrinsic::Intrinsic;
use crate::common::intrinsic_helpers::TypeKind;
use intrinsic::ArmIntrinsicType;
use intrinsic::ArmType;
use json_parser::get_neon_intrinsics;

pub struct ArmArchitectureTest {
intrinsics: Vec<Intrinsic<ArmIntrinsicType>>,
}
#[derive(PartialEq)]
pub struct Arm(Vec<Intrinsic<Arm>>);

impl SupportedArchitectureTest for ArmArchitectureTest {
type IntrinsicImpl = ArmIntrinsicType;
impl SupportedArchitecture for Arm {
type Type = ArmType;

fn intrinsics(&self) -> &[Intrinsic<ArmIntrinsicType>] {
&self.intrinsics
fn intrinsics(&self) -> &[Intrinsic<Self>] {
&self.0
}

const NOTICE: &str = config::NOTICE;
Expand Down Expand Up @@ -66,6 +65,6 @@ impl SupportedArchitectureTest for ArmArchitectureTest {
.take(sample_size)
.collect::<Vec<_>>();

Self { intrinsics }
Self(intrinsics)
}
}
8 changes: 3 additions & 5 deletions crates/intrinsic-test/src/arm/types.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use super::intrinsic::ArmIntrinsicType;
use crate::common::intrinsic_helpers::{
IntrinsicType, IntrinsicTypeDefinition, Sign, SimdLen, TypeKind,
};
use super::intrinsic::ArmType;
use crate::common::intrinsic_helpers::{IntrinsicType, Sign, SimdLen, TypeDefinition, TypeKind};

impl IntrinsicTypeDefinition for ArmIntrinsicType {
impl TypeDefinition for ArmType {
/// Gets a string containing the typename for this type in C format.
fn c_type(&self) -> String {
let prefix = self.kind.c_prefix();
Expand Down
23 changes: 12 additions & 11 deletions crates/intrinsic-test/src/common/argument.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
use itertools::Itertools;

use crate::common::SupportedArchitecture;
use crate::common::intrinsic_helpers::TypeKind;
use crate::common::values::test_values_array_name;

use super::PASSES;
use super::constraint::Constraint;
use super::intrinsic_helpers::IntrinsicTypeDefinition;
use super::intrinsic_helpers::TypeDefinition;

/// An argument for the intrinsic.
#[derive(Debug, PartialEq, Clone)]
pub struct Argument<T: IntrinsicTypeDefinition> {
pub struct Argument<A: SupportedArchitecture> {
/// 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: T,
pub ty: A::Type,
/// Any constraints that are on this argument
pub constraint: Option<Constraint>,
}

impl<T> Argument<T>
impl<A> Argument<A>
where
T: IntrinsicTypeDefinition,
A: SupportedArchitecture,
{
pub fn new(pos: usize, name: String, ty: T, constraint: Option<Constraint>) -> Self {
pub fn new(pos: usize, name: String, ty: A::Type, constraint: Option<Constraint>) -> Self {
Argument {
pos,
name,
Expand Down Expand Up @@ -63,13 +64,13 @@ where

/// Arguments of an intrinsic - including parameters that end up being const generics.
#[derive(Debug, PartialEq, Clone)]
pub struct ArgumentList<T: IntrinsicTypeDefinition> {
pub args: Vec<Argument<T>>,
pub struct ArgumentList<A: SupportedArchitecture> {
pub args: Vec<Argument<A>>,
}

impl<T> ArgumentList<T>
impl<A> ArgumentList<A>
where
T: IntrinsicTypeDefinition,
A: SupportedArchitecture,
{
/// Returns a string with the arguments in `self` as a parameter list for a wrapper fn
/// definition in C (e.g. `$ty1 $arg1, $ty2 $arg2`).
Expand Down Expand Up @@ -196,7 +197,7 @@ where
}

/// Returns an iterator over the contained arguments
pub fn iter(&self) -> std::slice::Iter<'_, Argument<T>> {
pub fn iter(&self) -> std::slice::Iter<'_, Argument<A>> {
self.args.iter()
}
}
8 changes: 4 additions & 4 deletions crates/intrinsic-test/src/common/gen_c.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use itertools::Itertools;

use crate::common::intrinsic::Intrinsic;
use crate::common::{SupportedArchitecture, intrinsic::Intrinsic};

use super::intrinsic_helpers::IntrinsicTypeDefinition;
use super::intrinsic_helpers::TypeDefinition;

/// Generates a C source file containing wrapper functions around each specialisation of each
/// intrinsic (that is, intrinsics with specific values for the the immediate arguments). Each
Expand All @@ -14,11 +14,11 @@ use super::intrinsic_helpers::IntrinsicTypeDefinition;
/// *__dst = __crc32cd(a, b);
/// }
/// ```
pub fn write_wrapper_c<T: IntrinsicTypeDefinition>(
pub fn write_wrapper_c<A: SupportedArchitecture>(
w: &mut impl std::io::Write,
notice: &str,
platform_headers: &[&str],
intrinsics: &[Intrinsic<T>],
intrinsics: &[Intrinsic<A>],
) -> std::io::Result<()> {
write!(w, "{notice}")?;

Expand Down
29 changes: 13 additions & 16 deletions crates/intrinsic-test/src/common/gen_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ use std::process::Command;

use itertools::Itertools;

use super::intrinsic_helpers::IntrinsicTypeDefinition;
use crate::common::PASSES;
use super::intrinsic_helpers::TypeDefinition;
use crate::common::cli::{CcArgStyle, ProcessedCli};
use crate::common::intrinsic::Intrinsic;
use crate::common::intrinsic_helpers::TypeKind;
use crate::common::values::{test_values_array_name, test_values_array_static};
use crate::common::{PASSES, SupportedArchitecture};

/// Rust definitions that are included verbatim in the generated source. In particular, defines
/// a wrapper around float types that defines `NaN`s to be equal reflexively to enable
Expand Down Expand Up @@ -102,15 +102,12 @@ pub fn write_lib_cargo_toml(w: &mut impl std::io::Write, name: &str) -> std::io:

/// Writes a Rust source file into `w` with common definitions, static arrays with test values,
/// declarations of C wrapper functions for FFI and Rust test functions.
pub fn write_lib_rs<T: IntrinsicTypeDefinition>(
pub fn write_lib_rs<A: SupportedArchitecture>(
w: &mut impl std::io::Write,
notice: &str,
cfg: &str,
definitions: &str,
i: usize,
intrinsics: &[Intrinsic<T>],
intrinsics: &[Intrinsic<A>],
) -> std::io::Result<()> {
write!(w, "{notice}")?;
write!(w, "{}", A::NOTICE)?;

writeln!(w, "#![feature(simd_ffi)]")?;
writeln!(w, "#![feature(f16)]")?;
Expand All @@ -121,11 +118,11 @@ pub fn write_lib_rs<T: IntrinsicTypeDefinition>(
writeln!(w, "#![allow(non_camel_case_types)]")?;
writeln!(w, "#![allow(non_snake_case)]")?;

writeln!(w, "{cfg}")?;
writeln!(w, "{}", A::PLATFORM_RUST_CFGS)?;

writeln!(w, "{}", COMMON_RUST_DEFINITIONS)?;

writeln!(w, "{definitions}")?;
writeln!(w, "{}", A::PLATFORM_RUST_DEFINITIONS)?;

let mut seen = std::collections::HashSet::new();

Expand Down Expand Up @@ -157,9 +154,9 @@ pub fn write_lib_rs<T: IntrinsicTypeDefinition>(
/// (first loop) `PASSES` number of times (second loop). For a given iteration of a given
/// specialisation, test values are loaded for each argument and passed to the Rust intrinsic
/// and the C wrapper function, and the results are compared.
fn generate_rust_test_loop<T: IntrinsicTypeDefinition>(
fn generate_rust_test_loop<A: SupportedArchitecture>(
w: &mut impl std::io::Write,
intrinsic: &Intrinsic<T>,
intrinsic: &Intrinsic<A>,
) -> std::io::Result<()> {
let intrinsic_name = &intrinsic.name;

Expand Down Expand Up @@ -251,9 +248,9 @@ fn generate_rust_test_loop<T: IntrinsicTypeDefinition>(

/// Writes a test function for an given intrinsic to `w`, with a body generated by
/// `generate_rust_test_loop`.
fn create_rust_test<T: IntrinsicTypeDefinition>(
fn create_rust_test<A: SupportedArchitecture>(
w: &mut impl std::io::Write,
intrinsic: &Intrinsic<T>,
intrinsic: &Intrinsic<A>,
) -> std::io::Result<()> {
trace!("generating `{}`", intrinsic.name);

Expand All @@ -272,10 +269,10 @@ fn create_rust_test<T: IntrinsicTypeDefinition>(

/// Writes an `extern "C"` block with function declarations for each of the C wrapper functions into
/// `w`.
pub fn write_bindings_rust<T: IntrinsicTypeDefinition>(
pub fn write_bindings_rust<A: SupportedArchitecture>(
w: &mut impl std::io::Write,
i: usize,
intrinsics: &[Intrinsic<T>],
intrinsics: &[Intrinsic<A>],
) -> std::io::Result<()> {
write!(
w,
Expand Down
12 changes: 5 additions & 7 deletions crates/intrinsic-test/src/common/intrinsic.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,17 @@
use crate::common::constraint::Constraint;

use super::argument::ArgumentList;
use super::intrinsic_helpers::IntrinsicTypeDefinition;
use crate::common::{SupportedArchitecture, constraint::Constraint};

/// An intrinsic
#[derive(Debug, PartialEq, Clone)]
pub struct Intrinsic<T: IntrinsicTypeDefinition> {
pub struct Intrinsic<A: SupportedArchitecture> {
/// The function name of this intrinsic.
pub name: String,

/// Any arguments for this intrinsic.
pub arguments: ArgumentList<T>,
pub arguments: ArgumentList<A>,

/// The return type of this intrinsic.
pub results: T,
pub results: A::Type,

/// Any architecture-specific tags.
pub arch_tags: Vec<String>,
Expand All @@ -40,7 +38,7 @@ fn recurse_specializations<'a, E>(
}
}

impl<T: IntrinsicTypeDefinition> Intrinsic<T> {
impl<A: SupportedArchitecture> Intrinsic<A> {
/// Invokes `f` for "specialisation" of the intrinsic - a specific instantiation of the
/// constant generics of the intrinsic. `f` takes a slice where the `i`th element corresponds
/// to the value of the `i`th const generic argument of the intrinsic.
Expand Down
2 changes: 1 addition & 1 deletion crates/intrinsic-test/src/common/intrinsic_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ impl IntrinsicType {
}
}

pub trait IntrinsicTypeDefinition: Deref<Target = IntrinsicType> {
pub trait TypeDefinition: Clone + Deref<Target = IntrinsicType> {
/// Determines the load function for this type.
fn get_load_function(&self) -> String;

Expand Down
17 changes: 5 additions & 12 deletions crates/intrinsic-test/src/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::common::{
run_rustfmt, write_bin_cargo_toml, write_build_rs, write_lib_cargo_toml, write_lib_rs,
},
intrinsic::Intrinsic,
intrinsic_helpers::IntrinsicTypeDefinition,
intrinsic_helpers::TypeDefinition,
};

pub mod argument;
Expand All @@ -29,10 +29,10 @@ pub(crate) const PASSES: u32 = 20;

/// Architectures must support this trait
/// to be successfully tested.
pub trait SupportedArchitectureTest {
type IntrinsicImpl: IntrinsicTypeDefinition + Sync;
pub trait SupportedArchitecture: Sized {
type Type: TypeDefinition + std::fmt::Debug + PartialEq + Sync;

fn intrinsics(&self) -> &[Intrinsic<Self::IntrinsicImpl>];
fn intrinsics(&self) -> &[Intrinsic<Self>];

fn create(cli_options: &ProcessedCli) -> Self;

Expand Down Expand Up @@ -81,14 +81,7 @@ pub trait SupportedArchitectureTest {
trace!("generating `{rust_filename}`");
let mut file = File::create(&rust_filename)?;

write_lib_rs(
&mut file,
Self::NOTICE,
Self::PLATFORM_RUST_CFGS,
Self::PLATFORM_RUST_DEFINITIONS,
i,
chunk,
)?;
write_lib_rs(&mut file, i, chunk)?;
run_rustfmt(&rust_filename);

let toml_filename = format!("rust_programs/mod_{i}/Cargo.toml");
Expand Down
Loading