rewrite codegen to syn

This commit is contained in:
nora 2024-01-05 23:48:53 +01:00
parent 1dcfb83114
commit 2f60340a3b
5 changed files with 367 additions and 279 deletions

26
Cargo.lock generated
View file

@ -37,8 +37,12 @@ dependencies = [
"eyre", "eyre",
"heck", "heck",
"logos", "logos",
"prettyplease",
"proc-macro2",
"quote",
"rand", "rand",
"strong-xml", "strong-xml",
"syn 2.0.48",
] ]
[[package]] [[package]]
@ -109,7 +113,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"regex-syntax", "regex-syntax",
"syn 2.0.46", "syn 2.0.48",
] ]
[[package]] [[package]]
@ -140,10 +144,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]] [[package]]
name = "proc-macro2" name = "prettyplease"
version = "1.0.74" version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2de98502f212cfcea8d0bb305bd0f49d7ebdd75b64ba0a68f937d888f4e0d6db" checksum = "a41cf62165e97c7f814d2221421dbb9afcbcdb0a88068e5ea206e19951c2cbb5"
dependencies = [
"proc-macro2",
"syn 2.0.48",
]
[[package]]
name = "proc-macro2"
version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
@ -230,9 +244,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.46" version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89456b690ff72fddcecf231caedbe615c59480c93358a93dfae7fc29e3ebbf0e" checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",

View file

@ -9,5 +9,9 @@ edition = "2021"
eyre = "0.6.11" eyre = "0.6.11"
heck = "0.4.1" heck = "0.4.1"
logos = "0.13.0" logos = "0.13.0"
prettyplease = "0.2.16"
proc-macro2 = "1.0.75"
quote = "1.0.35"
rand = { version = "0.8.5", features = ["small_rng"] } rand = { version = "0.8.5", features = ["small_rng"] }
strong-xml = "0.6.3" strong-xml = "0.6.3"
syn = "2.0.48"

View file

@ -5,155 +5,180 @@ use crate::{
use eyre::{bail, Context, OptionExt, Result}; use eyre::{bail, Context, OptionExt, Result};
use rand::{rngs::SmallRng, Rng, SeedableRng}; use rand::{rngs::SmallRng, Rng, SeedableRng};
pub fn generate(intrinsics: &[Intrinsic]) -> Result<()> { pub fn generate(intrinsics: &[Intrinsic]) -> Result<syn::File> {
println!("impl<C: super::Core> Intrinsics for C {{}}"); let blanket: syn::ItemImpl = syn::parse_quote! {
println!("pub trait Intrinsics: super::Core {{"); impl<C: super::Core> Intrinsics for C {}
};
let mut trait_def: syn::ItemTrait = syn::parse_quote! {
pub trait Intrinsics: super::Core {}
};
for intr in intrinsics { for intr in intrinsics {
generate_intr(intr).wrap_err_with(|| format!("generating `{}`", intr.name))?; let item = generate_intr(intr).wrap_err_with(|| format!("generating `{}`", intr.name))?;
trait_def.items.push(item);
} }
println!("}}"); let soft_arch =
println!();
generate_soft_arch_module(intrinsics).wrap_err("generating soft_arch module")?; generate_soft_arch_module(intrinsics).wrap_err("generating soft_arch module")?;
generate_test_module(intrinsics).wrap_err("generating test module")?; let test = generate_test_module(intrinsics).wrap_err("generating test module")?;
Ok(()) let mut file: syn::File = syn::parse_quote! {};
file.items = vec![
blanket.into(),
trait_def.into(),
soft_arch.into(),
test.into(),
];
Ok(file)
} }
fn generate_soft_arch_module(intrinsics: &[Intrinsic]) -> Result<()> { fn generate_soft_arch_module(intrinsics: &[Intrinsic]) -> Result<syn::ItemMod> {
println!("pub mod soft_arch {{"); let mut module: syn::ItemMod = syn::parse_quote! {
println!(" pub use super::super::soft_arch_types::*;"); pub mod soft_arch {
println!(" use super::Intrinsics;"); pub use super::super::soft_arch_types::*;
use super::Intrinsics;
}
};
for intr in intrinsics { for intr in intrinsics {
generate_intr_soft_arch_wrap(intr) let item = generate_intr_soft_arch_wrap(intr)
.wrap_err_with(|| format!("generating soft_arch `{}`", intr.name))?; .wrap_err_with(|| format!("generating `{}`", intr.name))?;
module.content.as_mut().unwrap().1.push(item.into());
} }
println!("}}"); Ok(module)
Ok(())
} }
fn generate_test_module(intrinsics: &[Intrinsic]) -> Result<()> { fn generate_test_module(intrinsics: &[Intrinsic]) -> Result<syn::ItemMod> {
println!("#[cfg(all(test, target_arch = \"x86_64\"))]"); let mut module: syn::ItemMod = syn::parse_quote! {
println!("pub mod tests {{"); #[cfg(all(test, target_arch = "x86_64"))]
println!(" use super::super::compare_test_helper::hard_soft_same_128;"); pub mod tests {
use super::super::compare_test_helper::hard_soft_same_128;
}
};
let rng = &mut SmallRng::seed_from_u64(44); let rng = &mut SmallRng::seed_from_u64(44);
for intr in intrinsics { for intr in intrinsics {
generate_intr_test(intr, rng) let item = generate_intr_test(intr, rng)
.wrap_err_with(|| format!("generating soft_arch `{}`", intr.name))?; .wrap_err_with(|| format!("generating soft_arch `{}`", intr.name))?;
module.content.as_mut().unwrap().1.push(item.into());
} }
println!("}}"); Ok(module)
Ok(())
} }
fn generate_intr(intr: &Intrinsic) -> Result<(), eyre::Error> { fn generate_intr(intr: &Intrinsic) -> Result<syn::TraitItem, eyre::Error> {
eprintln!("generating {}...", intr.name); eprintln!("generating {}...", intr.name);
let signature = signature(intr)?;
println!(" {signature} {{");
let body = generate_body(intr).wrap_err("generating body")?; let body = generate_body(intr).wrap_err("generating body")?;
println!("{}", indent(&body, 8));
println!(" }}"); signature(intr, body)
Ok(())
} }
fn generate_intr_soft_arch_wrap(intr: &Intrinsic) -> Result<(), eyre::Error> { fn generate_intr_soft_arch_wrap(intr: &Intrinsic) -> Result<syn::ItemFn, eyre::Error> {
eprintln!("generating soft_arch wrapper {}...", intr.name); eprintln!("generating soft_arch wrapper {}...", intr.name);
let signature = signature_soft_arch(intr)?;
println!(" {signature} {{");
let body = generate_body_soft_arch(intr).wrap_err("generating body")?; let body = generate_body_soft_arch(intr).wrap_err("generating body")?;
println!("{}", indent(&body, 8));
println!(" }}"); signature_soft_arch(intr, body)
Ok(())
} }
fn generate_intr_test(intr: &Intrinsic, rng: &mut SmallRng) -> Result<(), eyre::Error> { fn generate_intr_test(intr: &Intrinsic, rng: &mut SmallRng) -> Result<syn::ItemFn, eyre::Error> {
eprintln!("generating test {}...", intr.name); eprintln!("generating test {}...", intr.name);
println!(" #[test]");
let name = &intr.name; let name = ident(&intr.name);
println!(" fn {name}() {{");
// TODO: non-128
println!(" hard_soft_same_128! {{");
let body = generate_body_test(intr, rng).wrap_err("generating body")?; let body = generate_body_test(intr, rng).wrap_err("generating body")?;
println!("{}", indent(&body, 12));
println!(" }}"); Ok(syn::parse_quote! {
println!(" }}"); #[test]
Ok(()) fn #name() {
hard_soft_same_128! {
#body
}
}
})
} }
fn generate_body_soft_arch(intr: &Intrinsic) -> Result<String> { fn generate_body_soft_arch(intr: &Intrinsic) -> Result<syn::Block> {
let mut rust_stmts = Vec::<String>::new(); let mut rust_stmts = Vec::<syn::Stmt>::new();
rust_stmts.push("let mut output = unsafe { std::mem::zeroed() };".into()); rust_stmts.push(syn::parse_quote! { let mut output = unsafe { std::mem::zeroed() }; });
let name = &intr.name; let name = ident(&intr.name);
let args = intr
.parameter
.iter()
.map(|param| param.varname.as_deref().ok_or_eyre("parameter has no name"))
.collect::<Result<Vec<_>>>()?
.join(", ");
rust_stmts.push(format!(
"super::super::ValueCore.{name}(&mut output, {args});"
));
rust_stmts.push("output".into()); let args = intr.parameter.iter().map(|param| -> syn::Expr {
let name = ident_opt_s(&param.varname).unwrap();
syn::parse_quote! { #name }
});
Ok(rust_stmts.join("\n")) rust_stmts.push(syn::parse_quote! {
super::super::ValueCore.#name(&mut output, #(#args),*);
});
rust_stmts.push(syn::Stmt::Expr(syn::parse_quote! { output }, None));
Ok(syn::parse_quote! {
{ #(#rust_stmts)* }
})
} }
fn generate_body_test(intr: &Intrinsic, rng: &mut SmallRng) -> Result<String> { fn generate_body_test(intr: &Intrinsic, rng: &mut SmallRng) -> Result<syn::Block> {
let mut rust_stmts = Vec::<String>::new(); let mut rust_stmts = Vec::<syn::Stmt>::new();
let args = intr let args = intr
.parameter .parameter
.iter() .iter()
.map(|param| -> Result<&str> { .map(|param| -> Result<syn::Expr> {
let name = param.varname.as_deref().unwrap(); let name = ident_opt_s(&param.varname).unwrap();
let ty = map_type_to_rust(param.r#type.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)?)); let random = random_value(ty, rng)?;
Ok(name) rust_stmts.push(syn::parse_quote! { let #name = #random; });
Ok(syn::parse_quote! { #name })
}) })
.collect::<Result<Vec<_>>>() .collect::<Result<Vec<syn::Expr>>>()
.wrap_err("preparing arguments")? .wrap_err("preparing arguments")?;
.join(", ");
let name = &intr.name; let name = ident(&intr.name);
rust_stmts.push(format!("{name}({args})")); rust_stmts.push(syn::Stmt::Expr(
syn::parse_quote!(#name( #(#args),* )),
None,
));
Ok(rust_stmts.join("\n")) Ok(syn::parse_quote! {
{ #(#rust_stmts)* }
})
} }
fn random_value(ty: &str, rng: &mut SmallRng) -> Result<String> { fn random_value(ty: &str, rng: &mut SmallRng) -> Result<syn::Expr> {
let quotei16 = |n| {
syn::parse_quote! { #n }
};
Ok(match ty { Ok(match ty {
"i16" => rng.gen::<i16>().to_string(), "i16" => quotei16(rng.gen::<i16>()),
"__m128i" => format!( "__m128i" => {
"_mm_setr_epi16({}, {}, {}, {}, {}, {}, {}, {})", let args = [
rng.gen::<i16>().to_string(), quotei16(rng.gen::<i16>()),
rng.gen::<i16>().to_string(), quotei16(rng.gen::<i16>()),
rng.gen::<i16>().to_string(), quotei16(rng.gen::<i16>()),
rng.gen::<i16>().to_string(), quotei16(rng.gen::<i16>()),
rng.gen::<i16>().to_string(), quotei16(rng.gen::<i16>()),
rng.gen::<i16>().to_string(), quotei16(rng.gen::<i16>()),
rng.gen::<i16>().to_string(), quotei16(rng.gen::<i16>()),
rng.gen::<i16>().to_string(), quotei16(rng.gen::<i16>()),
), ];
syn::parse_quote! {
_mm_setr_epi16(#(#args),*)
}
}
_ => bail!("unknown type: {ty}"), _ => bail!("unknown type: {ty}"),
}) })
} }
fn indent(input: &str, indent: usize) -> String {
let replace = format!("\n{}", " ".repeat(indent));
let mut s = " ".repeat(indent);
s.push_str(&input.trim_end().replace("\n", &replace));
s
}
struct VariableType { struct VariableType {
is_signed: bool, is_signed: bool,
rawtype_signed: bool, rawtype_signed: bool,
@ -192,9 +217,9 @@ impl VariableType {
} }
} }
fn generate_body(instr: &Intrinsic) -> Result<String> { fn generate_body(instr: &Intrinsic) -> Result<syn::Block> {
let opstmts = parse_op(instr)?; let opstmts = parse_op(instr)?;
let mut rust_stmts = Vec::<String>::new(); let mut rust_stmts = Vec::<syn::Stmt>::new();
let type_of_ident = |ident: &str| -> Result<VariableType> { let type_of_ident = |ident: &str| -> Result<VariableType> {
for param in &instr.parameter { for param in &instr.parameter {
@ -222,7 +247,7 @@ fn generate_body(instr: &Intrinsic) -> Result<String> {
let Expr::Index { lhs, idx } = lhs else { let Expr::Index { lhs, idx } = lhs else {
bail!("lhs of assign must be indexing"); bail!("lhs of assign must be indexing");
}; };
let Expr::Ident(ident) = *lhs else { let Expr::Ident(identifier) = *lhs else {
bail!("lhs of indexing must be identifier"); bail!("lhs of indexing must be identifier");
}; };
let Expr::Range { left, right } = *idx else { let Expr::Range { left, right } = *idx else {
@ -243,7 +268,7 @@ fn generate_body(instr: &Intrinsic) -> Result<String> {
bail!("indexing size must be power of two"); bail!("indexing size must be power of two");
} }
let ty = type_of_ident(&ident)?; let ty = type_of_ident(&identifier)?;
if size != ty.elem_width { if size != ty.elem_width {
bail!( bail!(
"unsupported not-direct element indexing, size={size}, element size={}", "unsupported not-direct element indexing, size={size}, element size={}",
@ -254,37 +279,48 @@ fn generate_body(instr: &Intrinsic) -> Result<String> {
let raw = &ty.raw_type; let raw = &ty.raw_type;
let rust_type = ty.rust_type(); let rust_type = ty.rust_type();
let lane_idx = low / ty.elem_width; let lane_idx = low / ty.elem_width;
rust_stmts.push(format!(
"self.set_lane_{raw}_{rust_type}({ident}, {lane_idx}, {expr});" let method = ident(&format!("set_lane_{raw}_{rust_type}"));
)); let identifier = ident(&identifier);
rust_stmts.push(syn::parse_quote! {
self.#method(#identifier, #lane_idx, #expr);
});
} }
_ => todo!(), _ => todo!(),
} }
} }
Ok(rust_stmts.join("\n")) Ok(syn::parse_quote! {
{ #(#rust_stmts)* }
})
} }
fn generate_expr_tmp( fn generate_expr_tmp(
rust_stmts: &mut Vec<String>, rust_stmts: &mut Vec<syn::Stmt>,
expr: Expr, expr: Expr,
type_of_ident: &impl Fn(&str) -> Result<VariableType>, type_of_ident: &impl Fn(&str) -> Result<VariableType>,
) -> Result<String> { ) -> Result<syn::Expr> {
let result = match expr { let tmp = |rust_stmts: &mut Vec<syn::Stmt>, inner: syn::Expr| {
Expr::Int(int) => int.to_string(), let stmt = syn::parse_quote! { let __tmp = #inner; };
Expr::Ident(ident) => { rust_stmts.push(stmt);
let ty = type_of_ident(&ident)?; syn::parse_quote! { __tmp }
};
let result: syn::Expr = match expr {
Expr::Int(int) => syn::parse_quote! { #int },
Expr::Ident(identifier) => {
let ty = type_of_ident(&identifier)?;
let identifier = ident(&identifier);
if ty.is_signed != ty.rawtype_signed { if ty.is_signed != ty.rawtype_signed {
let from = &ty.raw_type; let from = &ty.raw_type;
let to = ty.rust_type(); let to = ty.rust_type();
let stmt = format!("let __tmp = self.cast_sign_{from}_{to}({ident});"); let method = ident(&format!("cast_sign_{from}_{to}"));
rust_stmts.push(stmt); tmp(rust_stmts, syn::parse_quote! { self.#method(#identifier) })
"__tmp".into()
} else { } else {
ident syn::parse_quote! { #identifier }
} }
} }
Expr::Index { lhs, idx } => { Expr::Index { lhs, idx } => {
let Expr::Ident(ident) = *lhs else { let Expr::Ident(identifier) = *lhs else {
bail!("lhs of indexing must be identifier"); bail!("lhs of indexing must be identifier");
}; };
let Expr::Range { left, right } = *idx else { let Expr::Range { left, right } = *idx else {
@ -304,7 +340,7 @@ fn generate_expr_tmp(
bail!("indexing size must be power of two"); bail!("indexing size must be power of two");
} }
let ty = type_of_ident(&ident)?; let ty = type_of_ident(&identifier)?;
if size != ty.elem_width { if size != ty.elem_width {
bail!( bail!(
"unsupported not-direct element indexing, size={size}, element size={}", "unsupported not-direct element indexing, size={size}, element size={}",
@ -314,21 +350,27 @@ fn generate_expr_tmp(
let raw = &ty.raw_type; let raw = &ty.raw_type;
let rust_type = ty.rust_type(); let rust_type = ty.rust_type();
let lane_idx = low / ty.elem_width; let lane_idx = low / ty.elem_width;
let stmt = format!("let __tmp = self.get_lane_{raw}_{rust_type}({ident}, {lane_idx});");
rust_stmts.push(stmt); let identifier = ident(&identifier);
"__tmp".into() let method = ident(&format!("get_lane_{raw}_{rust_type}"));
tmp(
rust_stmts,
syn::parse_quote! { self.#method(#identifier, #lane_idx) },
)
} }
Expr::Range { .. } => todo!(), Expr::Range { .. } => todo!(),
Expr::Call { function, args } => { Expr::Call { function, args } => {
let function = heck::AsSnekCase(function); let function = ident(&heck::ToSnekCase::to_snek_case(function.as_str()));
let args = args let args = args
.into_iter() .into_iter()
.map(|arg| generate_expr_tmp(rust_stmts, arg, type_of_ident)) .map(|arg| generate_expr_tmp(rust_stmts, arg, type_of_ident))
.collect::<Result<Vec<_>>>()? .collect::<Result<Vec<syn::Expr>>>()?;
.join(", ");
let stmt = format!("let __tmp = self.{function}({args});"); tmp(
rust_stmts.push(stmt); rust_stmts,
"__tmp".into() syn::parse_quote! { self.#function( #(#args),* ) },
)
} }
Expr::BinaryOp { .. } => todo!(), Expr::BinaryOp { .. } => todo!(),
}; };
@ -343,49 +385,48 @@ fn parse_op(intr: &Intrinsic) -> Result<Vec<Stmt>> {
Ok(stmts) Ok(stmts)
} }
fn signature(intr: &Intrinsic) -> Result<String> { fn ident(s: &str) -> syn::Ident {
let name = &intr.name; syn::Ident::new(s, proc_macro2::Span::call_site())
}
let args = intr fn ident_opt_s(s: &Option<String>) -> Result<syn::Ident> {
.parameter let s = s.as_deref().ok_or_eyre("missing")?;
.iter() Ok(ident(s))
.map(|param| {
format!(
"{}: Self::{}",
param.varname.as_ref().unwrap(),
map_type_to_rust(param.r#type.as_ref().unwrap())
)
})
.collect::<Vec<_>>()
.join(", ");
let ret_name = intr.ret.varname.as_ref().unwrap();
let ret_ty = map_type_to_rust(intr.ret.r#type.as_ref().unwrap());
Ok(format!(
"fn {name}(&mut self, {ret_name}: &mut Self::{ret_ty}, {args})"
))
} }
fn signature_soft_arch(intr: &Intrinsic) -> Result<String> { fn signature(intr: &Intrinsic, body: syn::Block) -> Result<syn::TraitItem> {
let name = &intr.name; let name = ident(&intr.name);
let args = intr let ret_name = ident_opt_s(&intr.ret.varname)?;
.parameter let ret_ty = ident(map_type_to_rust(intr.ret.r#type.as_ref().unwrap()));
.iter()
.map(|param| {
format!(
"{}: {}",
param.varname.as_ref().unwrap(),
map_type_to_rust(param.r#type.as_ref().unwrap())
)
})
.collect::<Vec<_>>()
.join(", ");
let ret_ty = map_type_to_rust(intr.ret.r#type.as_ref().unwrap()); let args = [
syn::parse_quote! { &mut self },
syn::parse_quote! { #ret_name: &mut Self::#ret_ty },
]
.into_iter()
.chain(intr.parameter.iter().map(|param| -> syn::FnArg {
let varname = ident_opt_s(&param.varname).unwrap();
let ty = ident(map_type_to_rust(param.r#type.as_ref().unwrap()));
Ok(format!("pub fn {name}({args}) -> {ret_ty}")) syn::parse_quote! { #varname: Self::#ty }
}));
Ok(syn::parse_quote! { fn #name(#(#args),*) #body })
}
fn signature_soft_arch(intr: &Intrinsic, body: syn::Block) -> Result<syn::ItemFn> {
let name = ident(&intr.name);
let args = intr.parameter.iter().map(|param| -> syn::FnArg {
let varname = ident_opt_s(&param.varname).unwrap();
let ty = ident(map_type_to_rust(param.r#type.as_ref().unwrap()));
syn::parse_quote! { #varname: #ty }
});
let ret_ty = ident(map_type_to_rust(intr.ret.r#type.as_ref().unwrap()));
Ok(syn::parse_quote! { pub fn #name( #(#args),* ) -> #ret_ty #body })
} }
fn map_type_to_rust(ty: &str) -> &str { fn map_type_to_rust(ty: &str) -> &str {

View file

@ -81,7 +81,9 @@ fn main() -> Result<()> {
eprintln!("filtered: {}", list.len()); eprintln!("filtered: {}", list.len());
generate::generate(&list).wrap_err("generating rust code")?; let generated_mod = generate::generate(&list).wrap_err("generating rust code")?;
println!("{}", prettyplease::unparse(&generated_mod));
Ok(()) Ok(())
} }

View file

@ -1,131 +1,161 @@
impl<C: super::Core> Intrinsics for C {} impl<C: super::Core> Intrinsics for C {}
pub trait Intrinsics: super::Core { pub trait Intrinsics: super::Core {
fn _mm_setr_epi16(&mut self, dst: &mut Self::__m128i, e7: Self::i16, e6: Self::i16, e5: Self::i16, e4: Self::i16, e3: Self::i16, e2: Self::i16, e1: Self::i16, e0: Self::i16) { fn _mm_setr_epi16(
&mut self,
dst: &mut Self::__m128i,
e7: Self::i16,
e6: Self::i16,
e5: Self::i16,
e4: Self::i16,
e3: Self::i16,
e2: Self::i16,
e1: Self::i16,
e0: Self::i16,
) {
let __tmp = self.cast_sign_i16_u16(e7); let __tmp = self.cast_sign_i16_u16(e7);
self.set_lane___m128i_u16(dst, 0, __tmp); self.set_lane___m128i_u16(dst, 0u64, __tmp);
let __tmp = self.cast_sign_i16_u16(e6); let __tmp = self.cast_sign_i16_u16(e6);
self.set_lane___m128i_u16(dst, 1, __tmp); self.set_lane___m128i_u16(dst, 1u64, __tmp);
let __tmp = self.cast_sign_i16_u16(e5); let __tmp = self.cast_sign_i16_u16(e5);
self.set_lane___m128i_u16(dst, 2, __tmp); self.set_lane___m128i_u16(dst, 2u64, __tmp);
let __tmp = self.cast_sign_i16_u16(e4); let __tmp = self.cast_sign_i16_u16(e4);
self.set_lane___m128i_u16(dst, 3, __tmp); self.set_lane___m128i_u16(dst, 3u64, __tmp);
let __tmp = self.cast_sign_i16_u16(e3); let __tmp = self.cast_sign_i16_u16(e3);
self.set_lane___m128i_u16(dst, 4, __tmp); self.set_lane___m128i_u16(dst, 4u64, __tmp);
let __tmp = self.cast_sign_i16_u16(e2); let __tmp = self.cast_sign_i16_u16(e2);
self.set_lane___m128i_u16(dst, 5, __tmp); self.set_lane___m128i_u16(dst, 5u64, __tmp);
let __tmp = self.cast_sign_i16_u16(e1); let __tmp = self.cast_sign_i16_u16(e1);
self.set_lane___m128i_u16(dst, 6, __tmp); self.set_lane___m128i_u16(dst, 6u64, __tmp);
let __tmp = self.cast_sign_i16_u16(e0); let __tmp = self.cast_sign_i16_u16(e0);
self.set_lane___m128i_u16(dst, 7, __tmp); self.set_lane___m128i_u16(dst, 7u64, __tmp);
} }
fn _mm_packs_epi16(&mut self, dst: &mut Self::__m128i, a: Self::__m128i, b: Self::__m128i) { fn _mm_packs_epi16(
let __tmp = self.get_lane___m128i_i16(a, 0); &mut self,
dst: &mut Self::__m128i,
a: Self::__m128i,
b: Self::__m128i,
) {
let __tmp = self.get_lane___m128i_i16(a, 0u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 0, __tmp); self.set_lane___m128i_i8(dst, 0u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 1); let __tmp = self.get_lane___m128i_i16(a, 1u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 1, __tmp); self.set_lane___m128i_i8(dst, 1u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 2); let __tmp = self.get_lane___m128i_i16(a, 2u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 2, __tmp); self.set_lane___m128i_i8(dst, 2u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 3); let __tmp = self.get_lane___m128i_i16(a, 3u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 3, __tmp); self.set_lane___m128i_i8(dst, 3u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 4); let __tmp = self.get_lane___m128i_i16(a, 4u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 4, __tmp); self.set_lane___m128i_i8(dst, 4u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 5); let __tmp = self.get_lane___m128i_i16(a, 5u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 5, __tmp); self.set_lane___m128i_i8(dst, 5u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 6); let __tmp = self.get_lane___m128i_i16(a, 6u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 6, __tmp); self.set_lane___m128i_i8(dst, 6u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 7); let __tmp = self.get_lane___m128i_i16(a, 7u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 7, __tmp); self.set_lane___m128i_i8(dst, 7u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 0); let __tmp = self.get_lane___m128i_i16(b, 0u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 8, __tmp); self.set_lane___m128i_i8(dst, 8u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 1); let __tmp = self.get_lane___m128i_i16(b, 1u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 9, __tmp); self.set_lane___m128i_i8(dst, 9u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 2); let __tmp = self.get_lane___m128i_i16(b, 2u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 10, __tmp); self.set_lane___m128i_i8(dst, 10u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 3); let __tmp = self.get_lane___m128i_i16(b, 3u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 11, __tmp); self.set_lane___m128i_i8(dst, 11u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 4); let __tmp = self.get_lane___m128i_i16(b, 4u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 12, __tmp); self.set_lane___m128i_i8(dst, 12u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 5); let __tmp = self.get_lane___m128i_i16(b, 5u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 13, __tmp); self.set_lane___m128i_i8(dst, 13u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 6); let __tmp = self.get_lane___m128i_i16(b, 6u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 14, __tmp); self.set_lane___m128i_i8(dst, 14u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 7); let __tmp = self.get_lane___m128i_i16(b, 7u64);
let __tmp = self.saturate8(__tmp); let __tmp = self.saturate8(__tmp);
self.set_lane___m128i_i8(dst, 15, __tmp); self.set_lane___m128i_i8(dst, 15u64, __tmp);
} }
fn _mm_packus_epi16(&mut self, dst: &mut Self::__m128i, a: Self::__m128i, b: Self::__m128i) { fn _mm_packus_epi16(
let __tmp = self.get_lane___m128i_i16(a, 0); &mut self,
dst: &mut Self::__m128i,
a: Self::__m128i,
b: Self::__m128i,
) {
let __tmp = self.get_lane___m128i_i16(a, 0u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 0, __tmp); self.set_lane___m128i_u8(dst, 0u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 1); let __tmp = self.get_lane___m128i_i16(a, 1u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 1, __tmp); self.set_lane___m128i_u8(dst, 1u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 2); let __tmp = self.get_lane___m128i_i16(a, 2u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 2, __tmp); self.set_lane___m128i_u8(dst, 2u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 3); let __tmp = self.get_lane___m128i_i16(a, 3u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 3, __tmp); self.set_lane___m128i_u8(dst, 3u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 4); let __tmp = self.get_lane___m128i_i16(a, 4u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 4, __tmp); self.set_lane___m128i_u8(dst, 4u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 5); let __tmp = self.get_lane___m128i_i16(a, 5u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 5, __tmp); self.set_lane___m128i_u8(dst, 5u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 6); let __tmp = self.get_lane___m128i_i16(a, 6u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 6, __tmp); self.set_lane___m128i_u8(dst, 6u64, __tmp);
let __tmp = self.get_lane___m128i_i16(a, 7); let __tmp = self.get_lane___m128i_i16(a, 7u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 7, __tmp); self.set_lane___m128i_u8(dst, 7u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 0); let __tmp = self.get_lane___m128i_i16(b, 0u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 8, __tmp); self.set_lane___m128i_u8(dst, 8u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 1); let __tmp = self.get_lane___m128i_i16(b, 1u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 9, __tmp); self.set_lane___m128i_u8(dst, 9u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 2); let __tmp = self.get_lane___m128i_i16(b, 2u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 10, __tmp); self.set_lane___m128i_u8(dst, 10u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 3); let __tmp = self.get_lane___m128i_i16(b, 3u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 11, __tmp); self.set_lane___m128i_u8(dst, 11u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 4); let __tmp = self.get_lane___m128i_i16(b, 4u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 12, __tmp); self.set_lane___m128i_u8(dst, 12u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 5); let __tmp = self.get_lane___m128i_i16(b, 5u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 13, __tmp); self.set_lane___m128i_u8(dst, 13u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 6); let __tmp = self.get_lane___m128i_i16(b, 6u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 14, __tmp); self.set_lane___m128i_u8(dst, 14u64, __tmp);
let __tmp = self.get_lane___m128i_i16(b, 7); let __tmp = self.get_lane___m128i_i16(b, 7u64);
let __tmp = self.saturate_u8(__tmp); let __tmp = self.saturate_u8(__tmp);
self.set_lane___m128i_u8(dst, 15, __tmp); self.set_lane___m128i_u8(dst, 15u64, __tmp);
} }
} }
pub mod soft_arch { pub mod soft_arch {
pub use super::super::soft_arch_types::*; pub use super::super::soft_arch_types::*;
use super::Intrinsics; use super::Intrinsics;
pub fn _mm_setr_epi16(e7: i16, e6: i16, e5: i16, e4: i16, e3: i16, e2: i16, e1: i16, e0: i16) -> __m128i { pub fn _mm_setr_epi16(
e7: i16,
e6: i16,
e5: i16,
e4: i16,
e3: i16,
e2: i16,
e1: i16,
e0: i16,
) -> __m128i {
let mut output = unsafe { std::mem::zeroed() }; let mut output = unsafe { std::mem::zeroed() };
super::super::ValueCore._mm_setr_epi16(&mut output, e7, e6, e5, e4, e3, e2, e1, e0); super::super::ValueCore
._mm_setr_epi16(&mut output, e7, e6, e5, e4, e3, e2, e1, e0);
output output
} }
pub fn _mm_packs_epi16(a: __m128i, b: __m128i) -> __m128i { pub fn _mm_packs_epi16(a: __m128i, b: __m128i) -> __m128i {
@ -145,31 +175,28 @@ pub mod tests {
#[test] #[test]
fn _mm_setr_epi16() { fn _mm_setr_epi16() {
hard_soft_same_128! { hard_soft_same_128! {
let e7 = -24391; { let e7 = - 24391i16; let e6 = 19541i16; let e5 = - 16509i16; let e4 =
let e6 = 19541; 7733i16; let e3 = - 15140i16; let e2 = 30719i16; let e1 = 16513i16; let e0 =
let e5 = -16509; 22878i16; _mm_setr_epi16(e7, e6, e5, e4, e3, e2, e1, e0) }
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] #[test]
fn _mm_packs_epi16() { fn _mm_packs_epi16() {
hard_soft_same_128! { hard_soft_same_128! {
let a = _mm_setr_epi16(23986, 27900, -8343, -10648, 4841, 14610, -17251, -3971); { let a = _mm_setr_epi16(23986i16, 27900i16, - 8343i16, - 10648i16, 4841i16,
let b = _mm_setr_epi16(22390, -23547, 15401, 15832, -14212, -1286, -18062, 22296); 14610i16, - 17251i16, - 3971i16); let b = _mm_setr_epi16(22390i16, -
_mm_packs_epi16(a, b) 23547i16, 15401i16, 15832i16, - 14212i16, - 1286i16, - 18062i16, 22296i16);
_mm_packs_epi16(a, b) }
} }
} }
#[test] #[test]
fn _mm_packus_epi16() { fn _mm_packus_epi16() {
hard_soft_same_128! { hard_soft_same_128! {
let a = _mm_setr_epi16(18077, 23617, -9205, 21233, -4332, -31339, 23623, -22080); { let a = _mm_setr_epi16(18077i16, 23617i16, - 9205i16, 21233i16, - 4332i16,
let b = _mm_setr_epi16(-1436, -30227, 8629, 10922, -16731, -1013, -14310, 2892); - 31339i16, 23623i16, - 22080i16); let b = _mm_setr_epi16(- 1436i16, -
_mm_packus_epi16(a, b) 30227i16, 8629i16, 10922i16, - 16731i16, - 1013i16, - 14310i16, 2892i16);
_mm_packus_epi16(a, b) }
} }
} }
} }