diff options
| author | Madhav Madhusoodanan <madhavmadhusoodanan@gmail.com> | 2025-05-25 23:52:56 +0530 |
|---|---|---|
| committer | Amanieu d'Antras <amanieu@gmail.com> | 2025-05-27 23:27:38 +0000 |
| commit | d8469bea64c29fabe2d8e022cadf3af18ed0c2cf (patch) | |
| tree | ee8ab07d35c15de5a631992673e6e1587aedc588 | |
| parent | 54e277cdd58d6ceed114d5fca92405ec6f68d213 (diff) | |
| download | rust-d8469bea64c29fabe2d8e022cadf3af18ed0c2cf.tar.gz rust-d8469bea64c29fabe2d8e022cadf3af18ed0c2cf.zip | |
fix: moved common code (that required no architecture-specific
modifications) outside the IntrinsicDefinition trait
5 files changed, 243 insertions, 268 deletions
diff --git a/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs index e3b0fbbce93..773dabf4d75 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs @@ -92,57 +92,4 @@ impl IntrinsicDefinition<ArmIntrinsicType> for Intrinsic<ArmIntrinsicType> { close = if self.results.is_simd() { ")" } else { "" }, ) } - - fn generate_loop_c( - &self, - indentation: Indentation, - additional: &str, - passes: u32, - _target: &str, - ) -> String { - let body_indentation = indentation.nested(); - format!( - "{indentation}for (int i=0; i<{passes}; i++) {{\n\ - {loaded_args}\ - {body_indentation}auto __return_value = {intrinsic_call}({args});\n\ - {print_result}\n\ - {indentation}}}", - loaded_args = self.arguments.load_values_c(body_indentation), - intrinsic_call = self.name, - args = self.arguments.as_call_param_c(), - print_result = self.print_result_c(body_indentation, additional) - ) - } - - fn generate_loop_rust( - &self, - indentation: Indentation, - additional: &str, - passes: u32, - ) -> String { - let constraints = self.arguments.as_constraint_parameters_rust(); - let constraints = if !constraints.is_empty() { - format!("::<{constraints}>") - } else { - constraints - }; - - let return_value = self.format_f16_return_value(); - let indentation2 = indentation.nested(); - let indentation3 = indentation2.nested(); - - format!( - "{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}}}", - loaded_args = self.arguments.load_values_rust(indentation3), - intrinsic_call = self.name, - const = constraints, - args = self.arguments.as_call_param_rust(), - ) - } } diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs index a2a4115da62..6f91d676dc5 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs @@ -3,6 +3,14 @@ use rayon::prelude::*; use std::collections::BTreeMap; use std::process::Command; +use super::argument::Argument; +use super::indentation::Indentation; +use super::intrinsic::IntrinsicDefinition; +use super::intrinsic_helpers::IntrinsicTypeDefinition; + +// The number of times each intrinsic will be called. +const PASSES: u32 = 20; + pub fn generate_c_program( notices: &str, header_files: &[&str], @@ -89,3 +97,99 @@ pub fn create_c_filenames(identifiers: &Vec<String>) -> BTreeMap<&String, String }) .collect::<BTreeMap<&String, String>>() } + +pub fn generate_loop_c<T: IntrinsicTypeDefinition + Sized>( + intrinsic: &dyn IntrinsicDefinition<T>, + indentation: Indentation, + additional: &str, + passes: u32, + _target: &str, +) -> String { + let body_indentation = indentation.nested(); + format!( + "{indentation}for (int i=0; i<{passes}; i++) {{\n\ + {loaded_args}\ + {body_indentation}auto __return_value = {intrinsic_call}({args});\n\ + {print_result}\n\ + {indentation}}}", + loaded_args = intrinsic.arguments().load_values_c(body_indentation), + intrinsic_call = intrinsic.name(), + args = intrinsic.arguments().as_call_param_c(), + print_result = intrinsic.print_result_c(body_indentation, additional) + ) +} + +pub fn gen_code_c<T: IntrinsicTypeDefinition>( + intrinsic: &dyn IntrinsicDefinition<T>, + indentation: Indentation, + constraints: &[&Argument<T>], + name: String, + target: &str, +) -> String { + if let Some((current, constraints)) = constraints.split_last() { + let range = current + .constraint + .iter() + .map(|c| c.to_range()) + .flat_map(|r| r.into_iter()); + + let body_indentation = indentation.nested(); + range + .map(|i| { + format!( + "{indentation}{{\n\ + {body_indentation}{ty} {name} = {val};\n\ + {pass}\n\ + {indentation}}}", + name = current.name, + ty = current.ty.c_type(), + val = i, + pass = gen_code_c( + intrinsic, + body_indentation, + constraints, + format!("{name}-{i}"), + target, + ) + ) + }) + .join("\n") + } else { + generate_loop_c(intrinsic, indentation, &name, PASSES, target) + } +} + +pub fn gen_c_program<T: IntrinsicTypeDefinition>( + intrinsic: &dyn IntrinsicDefinition<T>, + header_files: &[&str], + target: &str, + c_target: &str, + notices: &str, + arch_specific_definitions: &[&str], +) -> String { + let arguments = intrinsic.arguments(); + let constraints = arguments + .iter() + .filter(|&i| i.has_constraint()) + .collect_vec(); + + let indentation = Indentation::default(); + generate_c_program( + notices, + header_files, + c_target, + arch_specific_definitions, + intrinsic + .arguments() + .gen_arglists_c(indentation, PASSES) + .as_str(), + gen_code_c( + intrinsic, + indentation.nested(), + constraints.as_slice(), + Default::default(), + target, + ) + .as_str(), + ) +} 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 260ff1b010d..06380b2c43e 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs @@ -5,6 +5,14 @@ use std::fs::File; use std::io::Write; 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; + +// The number of times each intrinsic will be called. +const PASSES: u32 = 20; + pub fn generate_rust_program( notices: &str, definitions: &str, @@ -129,3 +137,105 @@ pub fn create_rust_filenames(identifiers: &Vec<String>) -> BTreeMap<&String, Str }) .collect::<BTreeMap<&String, String>>() } + +pub fn generate_loop_rust<T: IntrinsicTypeDefinition>( + intrinsic: &dyn IntrinsicDefinition<T>, + indentation: Indentation, + additional: &str, + passes: u32, +) -> String { + let constraints = intrinsic.arguments().as_constraint_parameters_rust(); + let constraints = if !constraints.is_empty() { + format!("::<{constraints}>") + } else { + constraints + }; + + let return_value = format_f16_return_value(intrinsic); + let indentation2 = indentation.nested(); + let indentation3 = indentation2.nested(); + format!( + "{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}}}", + loaded_args = intrinsic.arguments().load_values_rust(indentation3), + intrinsic_call = intrinsic.name(), + const = constraints, + args = intrinsic.arguments().as_call_param_rust(), + ) +} + +pub fn gen_code_rust<T: IntrinsicTypeDefinition>( + intrinsic: &dyn IntrinsicDefinition<T>, + indentation: Indentation, + constraints: &[&Argument<T>], + name: String, +) -> String { + if let Some((current, constraints)) = constraints.split_last() { + let range = current + .constraint + .iter() + .map(|c| c.to_range()) + .flat_map(|r| r.into_iter()); + + let body_indentation = indentation.nested(); + range + .map(|i| { + format!( + "{indentation}{{\n\ + {body_indentation}const {name}: {ty} = {val};\n\ + {pass}\n\ + {indentation}}}", + name = current.name, + ty = current.ty.rust_type(), + val = i, + pass = gen_code_rust( + intrinsic, + body_indentation, + constraints, + format!("{name}-{i}") + ) + ) + }) + .join("\n") + } else { + generate_loop_rust(intrinsic, indentation, &name, PASSES) + } +} + +pub fn gen_rust_program<T: IntrinsicTypeDefinition>( + intrinsic: &dyn IntrinsicDefinition<T>, + target: &str, + notice: &str, + definitions: &str, + cfg: &str, +) -> String { + let arguments = intrinsic.arguments(); + let constraints = arguments + .iter() + .filter(|i| i.has_constraint()) + .collect_vec(); + + let indentation = Indentation::default(); + generate_rust_program( + notice, + definitions, + cfg, + target, + intrinsic + .arguments() + .gen_arglists_rust(indentation.nested(), PASSES) + .as_str(), + gen_code_rust( + intrinsic, + indentation.nested(), + &constraints, + Default::default(), + ) + .as_str(), + ) +} diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs index 9a2bf74a63d..61891e7c97d 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs @@ -1,15 +1,7 @@ +use super::intrinsic_helpers::TypeKind; use crate::common::argument::ArgumentList; use crate::common::indentation::Indentation; use crate::common::intrinsic_helpers::IntrinsicTypeDefinition; -use itertools::Itertools; - -use super::argument::Argument; -use super::gen_c::generate_c_program; -use super::gen_rust::generate_rust_program; -use super::intrinsic_helpers::TypeKind; - -// The number of times each intrinsic will be called. -const PASSES: u32 = 20; /// An intrinsic #[derive(Debug, PartialEq, Clone)] @@ -41,205 +33,20 @@ where /// rust debug output format for the return type. The generated line assumes /// there is an int i in scope which is the current pass number. fn print_result_c(&self, _indentation: Indentation, _additional: &str) -> String; +} - fn format_f16_return_value(&self) -> String { - // the `intrinsic-test` crate compares the output of C and Rust intrinsics. Currently, It uses - // a string representation of the output value to compare. In C, f16 values are currently printed - // as hexadecimal integers. Since https://github.com/rust-lang/rust/pull/127013, rust does print - // them as decimal floating point values. To keep the intrinsics tests working, for now, format - // vectors containing f16 values like C prints them. - let return_value = match self.results().kind() { - TypeKind::Float if self.results().inner_size() == 16 => "debug_f16(__return_value)", - _ => "format_args!(\"{__return_value:.150?}\")", - }; - - String::from(return_value) - } - - fn generate_loop_c( - &self, - indentation: Indentation, - additional: &str, - passes: u32, - _target: &str, - ) -> String { - let body_indentation = indentation.nested(); - format!( - "{indentation}for (int i=0; i<{passes}; i++) {{\n\ - {loaded_args}\ - {body_indentation}auto __return_value = {intrinsic_call}({args});\n\ - {print_result}\n\ - {indentation}}}", - loaded_args = self.arguments().load_values_c(body_indentation), - intrinsic_call = self.name(), - args = self.arguments().as_call_param_c(), - print_result = self.print_result_c(body_indentation, additional) - ) - } - - fn generate_loop_rust( - &self, - indentation: Indentation, - additional: &str, - passes: u32, - ) -> String { - let constraints = self.arguments().as_constraint_parameters_rust(); - let constraints = if !constraints.is_empty() { - format!("::<{constraints}>") - } else { - constraints - }; - - let indentation2 = indentation.nested(); - let indentation3 = indentation2.nested(); - format!( - "{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}-{{}}: {{:.150?}}\", i + 1, __return_value);\n\ - {indentation2}}}\n\ - {indentation}}}", - loaded_args = self.arguments().load_values_rust(indentation3), - intrinsic_call = self.name(), - const = constraints, - args = self.arguments().as_call_param_rust(), - ) - } - - fn gen_code_c( - &self, - indentation: Indentation, - constraints: &[&Argument<T>], - name: String, - target: &str, - ) -> String { - if let Some((current, constraints)) = constraints.split_last() { - let range = current - .constraint - .iter() - .map(|c| c.to_range()) - .flat_map(|r| r.into_iter()); - - let body_indentation = indentation.nested(); - range - .map(|i| { - format!( - "{indentation}{{\n\ - {body_indentation}{ty} {name} = {val};\n\ - {pass}\n\ - {indentation}}}", - name = current.name, - ty = current.ty.c_type(), - val = i, - pass = self.gen_code_c( - body_indentation, - constraints, - format!("{name}-{i}"), - target, - ) - ) - }) - .join("\n") - } else { - self.generate_loop_c(indentation, &name, PASSES, target) - } - } - - fn generate_c_program( - &self, - header_files: &[&str], - target: &str, - c_target: &str, - notices: &str, - arch_specific_definitions: &[&str], - ) -> String { - let arguments = self.arguments(); - let constraints = arguments - .iter() - .filter(|&i| i.has_constraint()) - .collect_vec(); - - let indentation = Indentation::default(); - generate_c_program( - notices, - header_files, - c_target, - arch_specific_definitions, - self.arguments() - .gen_arglists_c(indentation, PASSES) - .as_str(), - self.gen_code_c( - indentation.nested(), - constraints.as_slice(), - Default::default(), - target, - ) - .as_str(), - ) - } - - fn gen_code_rust( - &self, - indentation: Indentation, - constraints: &[&Argument<T>], - name: String, - ) -> String { - if let Some((current, constraints)) = constraints.split_last() { - let range = current - .constraint - .iter() - .map(|c| c.to_range()) - .flat_map(|r| r.into_iter()); - - let body_indentation = indentation.nested(); - range - .map(|i| { - format!( - "{indentation}{{\n\ - {body_indentation}const {name}: {ty} = {val};\n\ - {pass}\n\ - {indentation}}}", - name = current.name, - ty = current.ty.rust_type(), - val = i, - pass = self.gen_code_rust( - body_indentation, - constraints, - format!("{name}-{i}") - ) - ) - }) - .join("\n") - } else { - self.generate_loop_rust(indentation, &name, PASSES) - } - } - - fn generate_rust_program( - &self, - target: &str, - notice: &str, - definitions: &str, - cfg: &str, - ) -> String { - let arguments = self.arguments(); - let constraints = arguments - .iter() - .filter(|i| i.has_constraint()) - .collect_vec(); - - let indentation = Indentation::default(); - generate_rust_program( - notice, - definitions, - cfg, - target, - self.arguments() - .gen_arglists_rust(indentation.nested(), PASSES) - .as_str(), - self.gen_code_rust(indentation.nested(), &constraints, Default::default()) - .as_str(), - ) - } +pub fn format_f16_return_value<T: IntrinsicTypeDefinition>( + intrinsic: &dyn IntrinsicDefinition<T>, +) -> String { + // the `intrinsic-test` crate compares the output of C and Rust intrinsics. Currently, It uses + // a string representation of the output value to compare. In C, f16 values are currently printed + // as hexadecimal integers. Since https://github.com/rust-lang/rust/pull/127013, rust does print + // them as decimal floating point values. To keep the intrinsics tests working, for now, format + // vectors containing f16 values like C prints them. + let return_value = match intrinsic.results().kind() { + TypeKind::Float if intrinsic.results().inner_size() == 16 => "debug_f16(__return_value)", + _ => "format_args!(\"{__return_value:.150?}\")", + }; + + String::from(return_value) } diff --git a/library/stdarch/crates/intrinsic-test/src/common/write_file.rs b/library/stdarch/crates/intrinsic-test/src/common/write_file.rs index 88644fa7de1..503b9e82304 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/write_file.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/write_file.rs @@ -1,6 +1,7 @@ +use super::gen_c::gen_c_program; +use super::gen_rust::{create_rust_filenames, gen_rust_program}; use super::intrinsic_helpers::IntrinsicTypeDefinition; use crate::common::gen_c::create_c_filenames; -use crate::common::gen_rust::create_rust_filenames; use crate::common::intrinsic::IntrinsicDefinition; use crate::common::write_file; @@ -18,9 +19,15 @@ pub fn write_c_testfiles<T: IntrinsicTypeDefinition + Sized>( .collect::<Vec<_>>(); let filename_mapping = create_c_filenames(&intrinsics_name_list); - intrinsics.iter().for_each(|i| { - let c_code = - i.generate_c_program(headers, target, c_target, notice, arch_specific_definitions); + intrinsics.iter().for_each(|&i| { + let c_code = gen_c_program( + i, + headers, + target, + c_target, + notice, + arch_specific_definitions, + ); match filename_mapping.get(&i.name()) { Some(filename) => write_file(filename, c_code), None => {} @@ -43,8 +50,8 @@ pub fn write_rust_testfiles<T: IntrinsicTypeDefinition>( .collect::<Vec<_>>(); let filename_mapping = create_rust_filenames(&intrinsics_name_list); - intrinsics.iter().for_each(|i| { - let rust_code = i.generate_rust_program(rust_target, notice, definitions, cfg); + intrinsics.iter().for_each(|&i| { + let rust_code = gen_rust_program(i, rust_target, notice, definitions, cfg); match filename_mapping.get(&i.name()) { Some(filename) => write_file(filename, rust_code), None => {} |
