diff options
| author | Folkert de Vries <folkert@folkertdev.nl> | 2025-07-11 22:10:56 +0200 |
|---|---|---|
| committer | Folkert de Vries <folkert@folkertdev.nl> | 2025-07-19 02:11:15 +0200 |
| commit | 3051039b945f77a55e2fbbd1aceabfd147542746 (patch) | |
| tree | 14a6ba0e5c2ac9d7d2abde0010fb43b9817ca9b8 | |
| parent | 83804bf2ce8198c19144bc89e6e8e0f2c571b449 (diff) | |
| download | rust-3051039b945f77a55e2fbbd1aceabfd147542746.tar.gz rust-3051039b945f77a55e2fbbd1aceabfd147542746.zip | |
generate arrays of type-erased function pointers
4 files changed, 73 insertions, 83 deletions
diff --git a/library/stdarch/crates/intrinsic-test/src/arm/types.rs b/library/stdarch/crates/intrinsic-test/src/arm/types.rs index 77f5e8d0e56..c06e9355c44 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/types.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/types.rs @@ -33,25 +33,6 @@ impl IntrinsicTypeDefinition for ArmIntrinsicType { } } - fn rust_type(&self) -> String { - let rust_prefix = self.0.kind.rust_prefix(); - let c_prefix = self.0.kind.c_prefix(); - if self.0.ptr_constant { - self.c_type() - } else if let (Some(bit_len), simd_len, vec_len) = - (self.0.bit_len, self.0.simd_len, self.0.vec_len) - { - match (simd_len, vec_len) { - (None, None) => format!("{rust_prefix}{bit_len}"), - (Some(simd), None) => format!("{c_prefix}{bit_len}x{simd}_t"), - (Some(simd), Some(vec)) => format!("{c_prefix}{bit_len}x{simd}x{vec}_t"), - (None, Some(_)) => todo!("{:#?}", self), // Likely an invalid case - } - } else { - todo!("{:#?}", self) - } - } - /// Determines the load function for this type. fn get_load_function(&self, language: Language) -> String { if let IntrinsicType { diff --git a/library/stdarch/crates/intrinsic-test/src/common/argument.rs b/library/stdarch/crates/intrinsic-test/src/common/argument.rs index 9cba8c90d9f..1550cbd97f5 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/argument.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/argument.rs @@ -114,14 +114,6 @@ where .join(", ") } - pub fn as_constraint_parameters_rust(&self) -> String { - self.iter() - .filter(|a| a.has_constraint()) - .map(|arg| arg.name.clone()) - .collect::<Vec<String>>() - .join(", ") - } - /// Creates a line for each argument that initializes an array for C from which `loads` argument /// values can be loaded as a sliding window. /// e.g `const int32x2_t a_vals = {0x3effffff, 0x3effffff, 0x3f7fffff}`, if loads=2. diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs index 96b09b09f31..60bb577a80c 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs @@ -1,7 +1,6 @@ use itertools::Itertools; use std::process::Command; -use super::argument::Argument; use super::indentation::Indentation; use super::intrinsic::{IntrinsicDefinition, format_f16_return_value}; use super::intrinsic_helpers::IntrinsicTypeDefinition; @@ -188,66 +187,87 @@ pub fn generate_rust_test_loop<T: IntrinsicTypeDefinition>( w: &mut impl std::io::Write, intrinsic: &dyn IntrinsicDefinition<T>, indentation: Indentation, - additional: &str, + specializations: &[Vec<u8>], passes: u32, ) -> std::io::Result<()> { - let constraints = intrinsic.arguments().as_constraint_parameters_rust(); - let constraints = if !constraints.is_empty() { - format!("::<{constraints}>") - } else { - constraints - }; + let intrinsic_name = intrinsic.name(); + + // Each function (and each specialization) has its own type. Erase that type with a cast. + let mut coerce = String::from("unsafe fn("); + for _ in intrinsic.arguments().iter().filter(|a| !a.has_constraint()) { + coerce += "_, "; + } + coerce += ") -> _"; + + match specializations { + [] => { + writeln!(w, " let specializations = [(\"\", {intrinsic_name})];")?; + } + [const_args] if const_args.is_empty() => { + writeln!(w, " let specializations = [(\"\", {intrinsic_name})];")?; + } + _ => { + writeln!(w, " let specializations = [")?; + + for specialization in specializations { + let mut specialization: Vec<_> = + specialization.iter().map(|d| d.to_string()).collect(); + + let const_args = specialization.join(","); + + // The identifier is reversed. + specialization.reverse(); + let id = specialization.join("-"); + + writeln!( + w, + " (\"-{id}\", {intrinsic_name}::<{const_args}> as {coerce})," + )?; + } + + writeln!(w, " ];")?; + } + } let return_value = format_f16_return_value(intrinsic); let indentation2 = indentation.nested(); let indentation3 = indentation2.nested(); writeln!( w, - "{indentation}for i in 0..{passes} {{\n\ - {indentation2}unsafe {{\n\ - {loaded_args}\ - {indentation3}let __return_value = {intrinsic_call}{const}({args});\n\ - {indentation3}println!(\"Result {additional}-{{}}: {{:?}}\", i + 1, {return_value});\n\ - {indentation2}}}\n\ - {indentation}}}", + "\ + for (id, f) in specializations {{\n\ + for i in 0..{passes} {{\n\ + unsafe {{\n\ + {loaded_args}\ + let __return_value = f({args});\n\ + println!(\"Result {{id}}-{{}}: {{:?}}\", i + 1, {return_value});\n\ + }}\n\ + }}\n\ + }}", loaded_args = intrinsic.arguments().load_values_rust(indentation3), - intrinsic_call = intrinsic.name(), - const = constraints, args = intrinsic.arguments().as_call_param_rust(), ) } -fn generate_rust_constraint_blocks<'a, T: IntrinsicTypeDefinition + 'a>( - w: &mut impl std::io::Write, - intrinsic: &dyn IntrinsicDefinition<T>, - indentation: Indentation, - constraints: &mut (impl Iterator<Item = &'a Argument<T>> + Clone), - name: String, -) -> std::io::Result<()> { - let Some(current) = constraints.next() else { - return generate_rust_test_loop(w, intrinsic, indentation, &name, PASSES); - }; - - let body_indentation = indentation.nested(); - for i in current.constraint.iter().flat_map(|c| c.to_range()) { - let ty = current.ty.rust_type(); - - writeln!(w, "{indentation}{{")?; - - writeln!(w, "{body_indentation}const {}: {ty} = {i};", current.name)?; - - generate_rust_constraint_blocks( - w, - intrinsic, - body_indentation, - &mut constraints.clone(), - format!("{name}-{i}"), - )?; - - writeln!(w, "{indentation}}}")?; +/// Generate the specializations (unique sequences of const-generic arguments) for this intrinsic. +fn generate_rust_specializations<'a>( + constraints: &mut impl Iterator<Item = std::ops::Range<i64>>, +) -> Vec<Vec<u8>> { + let mut specializations = vec![vec![]]; + + for constraint in constraints { + specializations = constraint + .flat_map(|right| { + specializations.iter().map(move |left| { + let mut left = left.clone(); + left.push(u8::try_from(right).unwrap()); + left + }) + }) + .collect(); } - Ok(()) + specializations } // Top-level function to create complete test program @@ -265,13 +285,13 @@ pub fn create_rust_test_module<T: IntrinsicTypeDefinition>( arguments.gen_arglists_rust(w, indentation.nested(), PASSES)?; // Define any const generics as `const` items, then generate the actual test loop. - generate_rust_constraint_blocks( - w, - intrinsic, - indentation.nested(), - &mut arguments.iter().rev().filter(|i| i.has_constraint()), - Default::default(), - )?; + let specializations = generate_rust_specializations( + &mut arguments + .iter() + .filter_map(|i| i.constraint.as_ref().map(|v| v.to_range())), + ); + + generate_rust_test_loop(w, intrinsic, indentation, &specializations, PASSES)?; writeln!(w, "}}")?; diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs index 697f9c8754d..b53047b2d38 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs @@ -332,7 +332,4 @@ pub trait IntrinsicTypeDefinition: Deref<Target = IntrinsicType> { /// can be directly defined in `impl` blocks fn c_single_vector_type(&self) -> String; - - /// can be defined in `impl` blocks - fn rust_type(&self) -> String; } |
