mirror of
https://github.com/Noratrieb/intringen.git
synced 2026-01-14 13:55:02 +01:00
generate tests
This commit is contained in:
parent
8f49c199cc
commit
1dcfb83114
9 changed files with 268 additions and 41 deletions
69
Cargo.lock
generated
69
Cargo.lock
generated
|
|
@ -8,6 +8,12 @@ version = "0.5.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3a8241f3ebb85c056b509d4327ad0358fbbba6ffb340bf388f26350aeda225b1"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "eyre"
|
||||
version = "0.6.11"
|
||||
|
|
@ -31,9 +37,21 @@ dependencies = [
|
|||
"eyre",
|
||||
"heck",
|
||||
"logos",
|
||||
"rand",
|
||||
"strong-xml",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
|
|
@ -49,6 +67,9 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
|
|||
[[package]]
|
||||
name = "intringen"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jetscii"
|
||||
|
|
@ -62,6 +83,12 @@ version = "1.4.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.151"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
||||
|
||||
[[package]]
|
||||
name = "logos"
|
||||
version = "0.13.0"
|
||||
|
|
@ -106,6 +133,12 @@ version = "1.19.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.74"
|
||||
|
|
@ -124,6 +157,36 @@ dependencies = [
|
|||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.6.29"
|
||||
|
|
@ -182,6 +245,12 @@ version = "1.0.12"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "xmlparser"
|
||||
version = "0.13.6"
|
||||
|
|
|
|||
|
|
@ -9,4 +9,5 @@ edition = "2021"
|
|||
eyre = "0.6.11"
|
||||
heck = "0.4.1"
|
||||
logos = "0.13.0"
|
||||
rand = { version = "0.8.5", features = ["small_rng"] }
|
||||
strong-xml = "0.6.3"
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use crate::{
|
|||
Intrinsic,
|
||||
};
|
||||
use eyre::{bail, Context, OptionExt, Result};
|
||||
use rand::{rngs::SmallRng, Rng, SeedableRng};
|
||||
|
||||
pub fn generate(intrinsics: &[Intrinsic]) -> Result<()> {
|
||||
println!("impl<C: super::Core> Intrinsics for C {{}}");
|
||||
|
|
@ -14,7 +15,9 @@ pub fn generate(intrinsics: &[Intrinsic]) -> Result<()> {
|
|||
println!("}}");
|
||||
|
||||
println!();
|
||||
generate_soft_arch_module(intrinsics).context("generating soft_arch module")?;
|
||||
generate_soft_arch_module(intrinsics).wrap_err("generating soft_arch module")?;
|
||||
|
||||
generate_test_module(intrinsics).wrap_err("generating test module")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -33,6 +36,21 @@ fn generate_soft_arch_module(intrinsics: &[Intrinsic]) -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_test_module(intrinsics: &[Intrinsic]) -> Result<()> {
|
||||
println!("#[cfg(all(test, target_arch = \"x86_64\"))]");
|
||||
println!("pub mod tests {{");
|
||||
println!(" use super::super::compare_test_helper::hard_soft_same_128;");
|
||||
let rng = &mut SmallRng::seed_from_u64(44);
|
||||
|
||||
for intr in intrinsics {
|
||||
generate_intr_test(intr, rng)
|
||||
.wrap_err_with(|| format!("generating soft_arch `{}`", intr.name))?;
|
||||
}
|
||||
|
||||
println!("}}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_intr(intr: &Intrinsic) -> Result<(), eyre::Error> {
|
||||
eprintln!("generating {}...", intr.name);
|
||||
let signature = signature(intr)?;
|
||||
|
|
@ -53,6 +71,20 @@ fn generate_intr_soft_arch_wrap(intr: &Intrinsic) -> Result<(), eyre::Error> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_intr_test(intr: &Intrinsic, rng: &mut SmallRng) -> Result<(), eyre::Error> {
|
||||
eprintln!("generating test {}...", intr.name);
|
||||
println!(" #[test]");
|
||||
let name = &intr.name;
|
||||
println!(" fn {name}() {{");
|
||||
// TODO: non-128
|
||||
println!(" hard_soft_same_128! {{");
|
||||
let body = generate_body_test(intr, rng).wrap_err("generating body")?;
|
||||
println!("{}", indent(&body, 12));
|
||||
println!(" }}");
|
||||
println!(" }}");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn generate_body_soft_arch(intr: &Intrinsic) -> Result<String> {
|
||||
let mut rust_stmts = Vec::<String>::new();
|
||||
|
||||
|
|
@ -74,6 +106,47 @@ fn generate_body_soft_arch(intr: &Intrinsic) -> Result<String> {
|
|||
Ok(rust_stmts.join("\n"))
|
||||
}
|
||||
|
||||
fn generate_body_test(intr: &Intrinsic, rng: &mut SmallRng) -> Result<String> {
|
||||
let mut rust_stmts = Vec::<String>::new();
|
||||
|
||||
let args = intr
|
||||
.parameter
|
||||
.iter()
|
||||
.map(|param| -> Result<&str> {
|
||||
let name = param.varname.as_deref().unwrap();
|
||||
let ty = map_type_to_rust(param.r#type.as_deref().unwrap());
|
||||
|
||||
rust_stmts.push(format!("let {name} = {};", random_value(ty, rng)?));
|
||||
Ok(name)
|
||||
})
|
||||
.collect::<Result<Vec<_>>>()
|
||||
.wrap_err("preparing arguments")?
|
||||
.join(", ");
|
||||
|
||||
let name = &intr.name;
|
||||
rust_stmts.push(format!("{name}({args})"));
|
||||
|
||||
Ok(rust_stmts.join("\n"))
|
||||
}
|
||||
|
||||
fn random_value(ty: &str, rng: &mut SmallRng) -> Result<String> {
|
||||
Ok(match ty {
|
||||
"i16" => rng.gen::<i16>().to_string(),
|
||||
"__m128i" => format!(
|
||||
"_mm_setr_epi16({}, {}, {}, {}, {}, {}, {}, {})",
|
||||
rng.gen::<i16>().to_string(),
|
||||
rng.gen::<i16>().to_string(),
|
||||
rng.gen::<i16>().to_string(),
|
||||
rng.gen::<i16>().to_string(),
|
||||
rng.gen::<i16>().to_string(),
|
||||
rng.gen::<i16>().to_string(),
|
||||
rng.gen::<i16>().to_string(),
|
||||
rng.gen::<i16>().to_string(),
|
||||
),
|
||||
_ => bail!("unknown type: {ty}"),
|
||||
})
|
||||
}
|
||||
|
||||
fn indent(input: &str, indent: usize) -> String {
|
||||
let replace = format!("\n{}", " ".repeat(indent));
|
||||
let mut s = " ".repeat(indent);
|
||||
|
|
@ -98,6 +171,7 @@ impl VariableType {
|
|||
_ => bail!("unknown type: {ty}"),
|
||||
};
|
||||
let (is_signed, elem_width) = match etype {
|
||||
"SI8" => (true, 8),
|
||||
"SI16" => (true, 16),
|
||||
"UI8" => (false, 8),
|
||||
"UI16" => (false, 16),
|
||||
|
|
|
|||
|
|
@ -86,4 +86,4 @@ fn main() -> Result<()> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
const INTRINSICS_GENERATE: &[&str] = &["_mm_packus_epi16", "_mm_setr_epi16"];
|
||||
const INTRINSICS_GENERATE: &[&str] = &["_mm_packus_epi16", "_mm_packs_epi16", "_mm_setr_epi16"];
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use eyre::{bail, ContextCompat, OptionExt, Result};
|
||||
use eyre::{bail, OptionExt, Result};
|
||||
use logos::Logos;
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) enum Stmt {
|
||||
FnDef,
|
||||
Assign {
|
||||
|
|
@ -16,6 +17,7 @@ pub(crate) enum Stmt {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[allow(dead_code)]
|
||||
pub(crate) enum Expr {
|
||||
Int(u64),
|
||||
Ident(String),
|
||||
|
|
@ -133,7 +135,7 @@ fn parse_expr_call(parser: &mut Parser) -> Result<Expr> {
|
|||
loop {
|
||||
if parser.eat(Token::ParenOpen) {
|
||||
let arg = parse_expr(parser)?;
|
||||
parser.expect(Token::ParenClose);
|
||||
parser.expect(Token::ParenClose)?;
|
||||
let Expr::Ident(ident) = lhs else {
|
||||
panic!("lhs of function must be ident");
|
||||
};
|
||||
|
|
@ -145,7 +147,7 @@ fn parse_expr_call(parser: &mut Parser) -> Result<Expr> {
|
|||
}
|
||||
if parser.eat(Token::BracketOpen) {
|
||||
let arg = parse_expr(parser)?;
|
||||
parser.expect(Token::BracketClose);
|
||||
parser.expect(Token::BracketClose)?;
|
||||
lhs = Expr::Index {
|
||||
lhs: Box::new(lhs),
|
||||
idx: Box::new(arg),
|
||||
|
|
|
|||
|
|
@ -6,3 +6,6 @@ edition = "2021"
|
|||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
|
||||
[dev-dependencies]
|
||||
rand = { version = "0.8.5", features = ["small_rng"] }
|
||||
|
|
|
|||
|
|
@ -18,6 +18,56 @@ pub trait Intrinsics: super::Core {
|
|||
let __tmp = self.cast_sign_i16_u16(e0);
|
||||
self.set_lane___m128i_u16(dst, 7, __tmp);
|
||||
}
|
||||
fn _mm_packs_epi16(&mut self, dst: &mut Self::__m128i, a: Self::__m128i, b: Self::__m128i) {
|
||||
let __tmp = self.get_lane___m128i_i16(a, 0);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 0, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(a, 1);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 1, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(a, 2);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 2, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(a, 3);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 3, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(a, 4);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 4, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(a, 5);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 5, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(a, 6);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 6, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(a, 7);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 7, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(b, 0);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 8, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(b, 1);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 9, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(b, 2);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 10, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(b, 3);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 11, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(b, 4);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 12, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(b, 5);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 13, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(b, 6);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 14, __tmp);
|
||||
let __tmp = self.get_lane___m128i_i16(b, 7);
|
||||
let __tmp = self.saturate8(__tmp);
|
||||
self.set_lane___m128i_i8(dst, 15, __tmp);
|
||||
}
|
||||
fn _mm_packus_epi16(&mut self, dst: &mut Self::__m128i, a: Self::__m128i, b: Self::__m128i) {
|
||||
let __tmp = self.get_lane___m128i_i16(a, 0);
|
||||
let __tmp = self.saturate_u8(__tmp);
|
||||
|
|
@ -78,9 +128,48 @@ pub mod soft_arch {
|
|||
super::super::ValueCore._mm_setr_epi16(&mut output, e7, e6, e5, e4, e3, e2, e1, e0);
|
||||
output
|
||||
}
|
||||
pub fn _mm_packs_epi16(a: __m128i, b: __m128i) -> __m128i {
|
||||
let mut output = unsafe { std::mem::zeroed() };
|
||||
super::super::ValueCore._mm_packs_epi16(&mut output, a, b);
|
||||
output
|
||||
}
|
||||
pub fn _mm_packus_epi16(a: __m128i, b: __m128i) -> __m128i {
|
||||
let mut output = unsafe { std::mem::zeroed() };
|
||||
super::super::ValueCore._mm_packus_epi16(&mut output, a, b);
|
||||
output
|
||||
}
|
||||
}
|
||||
#[cfg(all(test, target_arch = "x86_64"))]
|
||||
pub mod tests {
|
||||
use super::super::compare_test_helper::hard_soft_same_128;
|
||||
#[test]
|
||||
fn _mm_setr_epi16() {
|
||||
hard_soft_same_128! {
|
||||
let e7 = -24391;
|
||||
let e6 = 19541;
|
||||
let e5 = -16509;
|
||||
let e4 = 7733;
|
||||
let e3 = -15140;
|
||||
let e2 = 30719;
|
||||
let e1 = 16513;
|
||||
let e0 = 22878;
|
||||
_mm_setr_epi16(e7, e6, e5, e4, e3, e2, e1, e0)
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn _mm_packs_epi16() {
|
||||
hard_soft_same_128! {
|
||||
let a = _mm_setr_epi16(23986, 27900, -8343, -10648, 4841, 14610, -17251, -3971);
|
||||
let b = _mm_setr_epi16(22390, -23547, 15401, 15832, -14212, -1286, -18062, 22296);
|
||||
_mm_packs_epi16(a, b)
|
||||
}
|
||||
}
|
||||
#[test]
|
||||
fn _mm_packus_epi16() {
|
||||
hard_soft_same_128! {
|
||||
let a = _mm_setr_epi16(18077, 23617, -9205, 21233, -4332, -31339, 23623, -22080);
|
||||
let b = _mm_setr_epi16(-1436, -30227, 8629, 10922, -16731, -1013, -14310, 2892);
|
||||
_mm_packus_epi16(a, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ pub trait Core {
|
|||
fn set_lane___m128i_i8(&mut self, place: &mut Self::__m128i, idx: u64, value: Self::i8);
|
||||
fn set_lane___m128i_u16(&mut self, place: &mut Self::__m128i, idx: u64, value: Self::u16);
|
||||
|
||||
fn saturate8(&mut self, elem: Self::i16) -> Self::i8;
|
||||
fn saturate_u8(&mut self, elem: Self::i16) -> Self::u8;
|
||||
}
|
||||
|
||||
|
|
@ -77,6 +78,11 @@ impl Core for ValueCore {
|
|||
place[(idx * 2 + 1) as usize] = second;
|
||||
}
|
||||
|
||||
fn saturate8(&mut self, elem: Self::i16) -> Self::i8 {
|
||||
let clamp = elem.clamp(i8::MIN as i16, i8::MAX as i16);
|
||||
clamp as i8
|
||||
}
|
||||
|
||||
fn saturate_u8(&mut self, elem: Self::i16) -> Self::u8 {
|
||||
let clamp = elem.clamp(0, u8::MAX as i16);
|
||||
clamp as u8
|
||||
|
|
@ -87,5 +93,22 @@ mod soft_arch_types {
|
|||
pub type __m128i = [u8; 16];
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
#[cfg(all(test, target_arch = "x86_64"))]
|
||||
mod compare_test_helper {
|
||||
macro_rules! hard_soft_same_128 {
|
||||
($($stmt:tt)*) => {
|
||||
let soft = {
|
||||
use crate::x86::soft_arch::*;
|
||||
$($stmt)*
|
||||
};
|
||||
let hard = unsafe {
|
||||
std::mem::transmute::<_, [u8; 16]>({
|
||||
use core::arch::x86_64::*;
|
||||
$($stmt)*
|
||||
})
|
||||
};
|
||||
assert_eq!(soft, hard);
|
||||
};
|
||||
}
|
||||
pub(super) use hard_soft_same_128;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,34 +0,0 @@
|
|||
#[cfg(target_arch = "x86_64")]
|
||||
mod x86_compare {
|
||||
macro_rules! hard_soft_same_128 {
|
||||
($($stmt:tt)*) => {
|
||||
let soft = {
|
||||
use crate::x86::soft_arch::*;
|
||||
$($stmt)*
|
||||
};
|
||||
let hard = unsafe {
|
||||
std::mem::transmute::<_, [u8; 16]>({
|
||||
use core::arch::x86_64::*;
|
||||
$($stmt)*
|
||||
})
|
||||
};
|
||||
assert_eq!(soft, hard);
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn _mm_setr_epi16() {
|
||||
hard_soft_same_128! {
|
||||
_mm_setr_epi16(0, -1, 100, 3535, 35, 2, i16::MIN, i16::MAX)
|
||||
};
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn _mm_packus_epi16() {
|
||||
hard_soft_same_128! {
|
||||
let a = _mm_setr_epi16(0x100, -1, 0, 0, 0, 0, 0, 0);
|
||||
let b = _mm_setr_epi16(0, 0, 0, 0, 0, 0, -1, 0x100);
|
||||
_mm_packus_epi16(a, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue