about summary refs log tree commit diff
path: root/library/stdarch/crates/intrinsic-test/src
diff options
context:
space:
mode:
Diffstat (limited to 'library/stdarch/crates/intrinsic-test/src')
-rw-r--r--library/stdarch/crates/intrinsic-test/src/arm/config.rs33
-rw-r--r--library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs85
-rw-r--r--library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs2
-rw-r--r--library/stdarch/crates/intrinsic-test/src/arm/mod.rs180
-rw-r--r--library/stdarch/crates/intrinsic-test/src/arm/types.rs66
-rw-r--r--library/stdarch/crates/intrinsic-test/src/common/gen_c.rs38
-rw-r--r--library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs29
-rw-r--r--library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs25
-rw-r--r--library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs5
-rw-r--r--library/stdarch/crates/intrinsic-test/src/common/mod.rs177
-rw-r--r--library/stdarch/crates/intrinsic-test/src/main.rs21
11 files changed, 334 insertions, 327 deletions
diff --git a/library/stdarch/crates/intrinsic-test/src/arm/config.rs b/library/stdarch/crates/intrinsic-test/src/arm/config.rs
index 9a7b37253d1..72e997de154 100644
--- a/library/stdarch/crates/intrinsic-test/src/arm/config.rs
+++ b/library/stdarch/crates/intrinsic-test/src/arm/config.rs
@@ -1,14 +1,17 @@
-pub fn build_notices(line_prefix: &str) -> String {
-    format!(
-        "\
-{line_prefix}This is a transient test file, not intended for distribution. Some aspects of the
-{line_prefix}test are derived from a JSON specification, published under the same license as the
-{line_prefix}`intrinsic-test` crate.\n
-"
-    )
-}
+pub const NOTICE: &str = "\
+// This is a transient test file, not intended for distribution. Some aspects of the
+// test are derived from a JSON specification, published under the same license as the
+// `intrinsic-test` crate.\n";
+
+pub const POLY128_OSTREAM_DECL: &str = r#"
+#ifdef __aarch64__
+std::ostream& operator<<(std::ostream& os, poly128_t value);
+#endif
+"#;
 
-pub const POLY128_OSTREAM_DEF: &str = r#"std::ostream& operator<<(std::ostream& os, poly128_t value) {
+pub const POLY128_OSTREAM_DEF: &str = r#"
+#ifdef __aarch64__
+std::ostream& operator<<(std::ostream& os, poly128_t value) {
     std::stringstream temp;
     do {
       int n = value % 10;
@@ -19,7 +22,9 @@ pub const POLY128_OSTREAM_DEF: &str = r#"std::ostream& operator<<(std::ostream&
     std::string res(tempstr.rbegin(), tempstr.rend());
     os << res;
     return os;
-}"#;
+}
+#endif
+"#;
 
 // Format f16 values (and vectors containing them) in a way that is consistent with C.
 pub const F16_FORMATTING_DEF: &str = r#"
@@ -118,4 +123,10 @@ pub const AARCH_CONFIGURATIONS: &str = r#"
 #![cfg_attr(any(target_arch = "aarch64", target_arch = "arm64ec"), feature(stdarch_neon_ftts))]
 #![feature(fmt_helpers_for_derive)]
 #![feature(stdarch_neon_f16)]
+
+#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
+use core::arch::aarch64::*;
+
+#[cfg(target_arch = "arm")]
+use core::arch::arm::*;
 "#;
diff --git a/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs
index fd93eff76e0..29343bee4c3 100644
--- a/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs
+++ b/library/stdarch/crates/intrinsic-test/src/arm/intrinsic.rs
@@ -1,7 +1,4 @@
-use crate::common::argument::ArgumentList;
-use crate::common::indentation::Indentation;
-use crate::common::intrinsic::{Intrinsic, IntrinsicDefinition};
-use crate::common::intrinsic_helpers::{IntrinsicType, IntrinsicTypeDefinition, Sign, TypeKind};
+use crate::common::intrinsic_helpers::IntrinsicType;
 use std::ops::{Deref, DerefMut};
 
 #[derive(Debug, Clone, PartialEq)]
@@ -23,83 +20,3 @@ impl DerefMut for ArmIntrinsicType {
         &mut self.data
     }
 }
-
-impl IntrinsicDefinition<ArmIntrinsicType> for Intrinsic<ArmIntrinsicType> {
-    fn arguments(&self) -> ArgumentList<ArmIntrinsicType> {
-        self.arguments.clone()
-    }
-
-    fn results(&self) -> ArmIntrinsicType {
-        self.results.clone()
-    }
-
-    fn name(&self) -> String {
-        self.name.clone()
-    }
-
-    /// Generates a std::cout for the intrinsics results that will match the
-    /// 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 {
-        let lanes = if self.results().num_vectors() > 1 {
-            (0..self.results().num_vectors())
-                .map(|vector| {
-                    format!(
-                        r#""{ty}(" << {lanes} << ")""#,
-                        ty = self.results().c_single_vector_type(),
-                        lanes = (0..self.results().num_lanes())
-                            .map(move |idx| -> std::string::String {
-                                format!(
-                                    "{cast}{lane_fn}(__return_value.val[{vector}], {lane})",
-                                    cast = self.results().c_promotion(),
-                                    lane_fn = self.results().get_lane_function(),
-                                    lane = idx,
-                                    vector = vector,
-                                )
-                            })
-                            .collect::<Vec<_>>()
-                            .join(r#" << ", " << "#)
-                    )
-                })
-                .collect::<Vec<_>>()
-                .join(r#" << ", " << "#)
-        } else if self.results().num_lanes() > 1 {
-            (0..self.results().num_lanes())
-                .map(|idx| -> std::string::String {
-                    format!(
-                        "{cast}{lane_fn}(__return_value, {lane})",
-                        cast = self.results().c_promotion(),
-                        lane_fn = self.results().get_lane_function(),
-                        lane = idx
-                    )
-                })
-                .collect::<Vec<_>>()
-                .join(r#" << ", " << "#)
-        } else {
-            format!(
-                "{promote}cast<{cast}>(__return_value)",
-                cast = match self.results.kind() {
-                    TypeKind::Float if self.results().inner_size() == 16 => "float16_t".to_string(),
-                    TypeKind::Float if self.results().inner_size() == 32 => "float".to_string(),
-                    TypeKind::Float if self.results().inner_size() == 64 => "double".to_string(),
-                    TypeKind::Int(Sign::Signed) => format!("int{}_t", self.results().inner_size()),
-                    TypeKind::Int(Sign::Unsigned) =>
-                        format!("uint{}_t", self.results().inner_size()),
-                    TypeKind::Poly => format!("poly{}_t", self.results().inner_size()),
-                    ty => todo!("print_result_c - Unknown type: {:#?}", ty),
-                },
-                promote = self.results().c_promotion(),
-            )
-        };
-
-        format!(
-            r#"{indentation}std::cout << "Result {additional}-" << i+1 << ": {ty}" << std::fixed << std::setprecision(150) <<  {lanes} << "{close}" << std::endl;"#,
-            ty = if self.results().is_simd() {
-                format!("{}(", self.results().c_type())
-            } else {
-                String::from("")
-            },
-            close = if self.results.is_simd() { ")" } else { "" },
-        )
-    }
-}
diff --git a/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs b/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs
index b019abab213..65c179ef0d0 100644
--- a/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs
+++ b/library/stdarch/crates/intrinsic-test/src/arm/json_parser.rs
@@ -113,7 +113,7 @@ fn json_to_intrinsic(
     Ok(Intrinsic {
         name,
         arguments,
-        results: results,
+        results,
         arch_tags: intr.architectures,
     })
 }
diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs
index 51f5ac42837..08dc2d38702 100644
--- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs
+++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs
@@ -5,20 +5,11 @@ mod intrinsic;
 mod json_parser;
 mod types;
 
-use std::fs::{self, File};
-
-use rayon::prelude::*;
-
+use crate::common::SupportedArchitectureTest;
 use crate::common::cli::ProcessedCli;
-use crate::common::compare::compare_outputs;
-use crate::common::gen_c::{write_main_cpp, write_mod_cpp};
-use crate::common::gen_rust::{
-    compile_rust_programs, write_bin_cargo_toml, write_lib_cargo_toml, write_lib_rs, write_main_rs,
-};
+use crate::common::compile_c::CppCompilation;
 use crate::common::intrinsic::Intrinsic;
 use crate::common::intrinsic_helpers::TypeKind;
-use crate::common::{SupportedArchitectureTest, chunk_info};
-use config::{AARCH_CONFIGURATIONS, F16_FORMATTING_DEF, POLY128_OSTREAM_DEF, build_notices};
 use intrinsic::ArmIntrinsicType;
 use json_parser::get_neon_intrinsics;
 
@@ -28,7 +19,30 @@ pub struct ArmArchitectureTest {
 }
 
 impl SupportedArchitectureTest for ArmArchitectureTest {
-    fn create(cli_options: ProcessedCli) -> Box<Self> {
+    type IntrinsicImpl = ArmIntrinsicType;
+
+    fn cli_options(&self) -> &ProcessedCli {
+        &self.cli_options
+    }
+
+    fn intrinsics(&self) -> &[Intrinsic<ArmIntrinsicType>] {
+        &self.intrinsics
+    }
+
+    const NOTICE: &str = config::NOTICE;
+
+    const PLATFORM_C_HEADERS: &[&str] = &["arm_neon.h", "arm_acle.h", "arm_fp16.h"];
+    const PLATFORM_C_DEFINITIONS: &str = config::POLY128_OSTREAM_DEF;
+    const PLATFORM_C_FORWARD_DECLARATIONS: &str = config::POLY128_OSTREAM_DECL;
+
+    const PLATFORM_RUST_DEFINITIONS: &str = config::F16_FORMATTING_DEF;
+    const PLATFORM_RUST_CFGS: &str = config::AARCH_CONFIGURATIONS;
+
+    fn cpp_compilation(&self) -> Option<CppCompilation> {
+        compile::build_cpp_compilation(&self.cli_options)
+    }
+
+    fn create(cli_options: ProcessedCli) -> Self {
         let a32 = cli_options.target.contains("v7");
         let mut intrinsics = get_neon_intrinsics(&cli_options.filename, &cli_options.target)
             .expect("Error parsing input file");
@@ -50,149 +64,9 @@ impl SupportedArchitectureTest for ArmArchitectureTest {
             .collect::<Vec<_>>();
         intrinsics.dedup();
 
-        Box::new(Self {
+        Self {
             intrinsics,
             cli_options,
-        })
-    }
-
-    fn build_c_file(&self) -> bool {
-        let c_target = "aarch64";
-        let platform_headers = &["arm_neon.h", "arm_acle.h", "arm_fp16.h"];
-
-        let (chunk_size, chunk_count) = chunk_info(self.intrinsics.len());
-
-        let cpp_compiler_wrapped = compile::build_cpp_compilation(&self.cli_options);
-
-        let notice = &build_notices("// ");
-        fs::create_dir_all("c_programs").unwrap();
-        self.intrinsics
-            .par_chunks(chunk_size)
-            .enumerate()
-            .map(|(i, chunk)| {
-                let c_filename = format!("c_programs/mod_{i}.cpp");
-                let mut file = File::create(&c_filename).unwrap();
-                write_mod_cpp(&mut file, notice, c_target, platform_headers, chunk).unwrap();
-
-                // compile this cpp file into a .o file.
-                //
-                // This is done because `cpp_compiler_wrapped` is None when
-                // the --generate-only flag is passed
-                if let Some(cpp_compiler) = cpp_compiler_wrapped.as_ref() {
-                    let output = cpp_compiler
-                        .compile_object_file(&format!("mod_{i}.cpp"), &format!("mod_{i}.o"))?;
-                    assert!(output.status.success(), "{output:?}");
-                }
-
-                Ok(())
-            })
-            .collect::<Result<(), std::io::Error>>()
-            .unwrap();
-
-        let mut file = File::create("c_programs/main.cpp").unwrap();
-        write_main_cpp(
-            &mut file,
-            c_target,
-            POLY128_OSTREAM_DEF,
-            self.intrinsics.iter().map(|i| i.name.as_str()),
-        )
-        .unwrap();
-
-        // This is done because `cpp_compiler_wrapped` is None when
-        // the --generate-only flag is passed
-        if let Some(cpp_compiler) = cpp_compiler_wrapped.as_ref() {
-            // compile this cpp file into a .o file
-            info!("compiling main.cpp");
-            let output = cpp_compiler
-                .compile_object_file("main.cpp", "intrinsic-test-programs.o")
-                .unwrap();
-            assert!(output.status.success(), "{output:?}");
-
-            let object_files = (0..chunk_count)
-                .map(|i| format!("mod_{i}.o"))
-                .chain(["intrinsic-test-programs.o".to_owned()]);
-
-            let output = cpp_compiler
-                .link_executable(object_files, "intrinsic-test-programs")
-                .unwrap();
-            assert!(output.status.success(), "{output:?}");
-        }
-
-        true
-    }
-
-    fn build_rust_file(&self) -> bool {
-        std::fs::create_dir_all("rust_programs/src").unwrap();
-
-        let architecture = if self.cli_options.target.contains("v7") {
-            "arm"
-        } else {
-            "aarch64"
-        };
-
-        let (chunk_size, chunk_count) = chunk_info(self.intrinsics.len());
-
-        let mut cargo = File::create("rust_programs/Cargo.toml").unwrap();
-        write_bin_cargo_toml(&mut cargo, chunk_count).unwrap();
-
-        let mut main_rs = File::create("rust_programs/src/main.rs").unwrap();
-        write_main_rs(
-            &mut main_rs,
-            chunk_count,
-            AARCH_CONFIGURATIONS,
-            "",
-            self.intrinsics.iter().map(|i| i.name.as_str()),
-        )
-        .unwrap();
-
-        let target = &self.cli_options.target;
-        let toolchain = self.cli_options.toolchain.as_deref();
-        let linker = self.cli_options.linker.as_deref();
-
-        let notice = &build_notices("// ");
-        self.intrinsics
-            .par_chunks(chunk_size)
-            .enumerate()
-            .map(|(i, chunk)| {
-                std::fs::create_dir_all(format!("rust_programs/mod_{i}/src"))?;
-
-                let rust_filename = format!("rust_programs/mod_{i}/src/lib.rs");
-                trace!("generating `{rust_filename}`");
-                let mut file = File::create(rust_filename)?;
-
-                let cfg = AARCH_CONFIGURATIONS;
-                let definitions = F16_FORMATTING_DEF;
-                write_lib_rs(&mut file, architecture, notice, cfg, definitions, chunk)?;
-
-                let toml_filename = format!("rust_programs/mod_{i}/Cargo.toml");
-                trace!("generating `{toml_filename}`");
-                let mut file = File::create(toml_filename).unwrap();
-
-                write_lib_cargo_toml(&mut file, &format!("mod_{i}"))?;
-
-                Ok(())
-            })
-            .collect::<Result<(), std::io::Error>>()
-            .unwrap();
-
-        compile_rust_programs(toolchain, target, linker)
-    }
-
-    fn compare_outputs(&self) -> bool {
-        if self.cli_options.toolchain.is_some() {
-            let intrinsics_name_list = self
-                .intrinsics
-                .iter()
-                .map(|i| i.name.clone())
-                .collect::<Vec<_>>();
-
-            compare_outputs(
-                &intrinsics_name_list,
-                &self.cli_options.runner,
-                &self.cli_options.target,
-            )
-        } else {
-            true
         }
     }
 }
diff --git a/library/stdarch/crates/intrinsic-test/src/arm/types.rs b/library/stdarch/crates/intrinsic-test/src/arm/types.rs
index 32f8f106ce2..e86a2c5189f 100644
--- a/library/stdarch/crates/intrinsic-test/src/arm/types.rs
+++ b/library/stdarch/crates/intrinsic-test/src/arm/types.rs
@@ -1,5 +1,6 @@
 use super::intrinsic::ArmIntrinsicType;
 use crate::common::cli::Language;
+use crate::common::indentation::Indentation;
 use crate::common::intrinsic_helpers::{IntrinsicType, IntrinsicTypeDefinition, Sign, TypeKind};
 
 impl IntrinsicTypeDefinition for ArmIntrinsicType {
@@ -98,6 +99,71 @@ impl IntrinsicTypeDefinition for ArmIntrinsicType {
             todo!("get_lane_function IntrinsicType: {:#?}", self)
         }
     }
+
+    /// Generates a std::cout for the intrinsics results that will match the
+    /// 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 {
+        let lanes = if self.num_vectors() > 1 {
+            (0..self.num_vectors())
+                .map(|vector| {
+                    format!(
+                        r#""{ty}(" << {lanes} << ")""#,
+                        ty = self.c_single_vector_type(),
+                        lanes = (0..self.num_lanes())
+                            .map(move |idx| -> std::string::String {
+                                format!(
+                                    "{cast}{lane_fn}(__return_value.val[{vector}], {lane})",
+                                    cast = self.c_promotion(),
+                                    lane_fn = self.get_lane_function(),
+                                    lane = idx,
+                                    vector = vector,
+                                )
+                            })
+                            .collect::<Vec<_>>()
+                            .join(r#" << ", " << "#)
+                    )
+                })
+                .collect::<Vec<_>>()
+                .join(r#" << ", " << "#)
+        } else if self.num_lanes() > 1 {
+            (0..self.num_lanes())
+                .map(|idx| -> std::string::String {
+                    format!(
+                        "{cast}{lane_fn}(__return_value, {lane})",
+                        cast = self.c_promotion(),
+                        lane_fn = self.get_lane_function(),
+                        lane = idx
+                    )
+                })
+                .collect::<Vec<_>>()
+                .join(r#" << ", " << "#)
+        } else {
+            format!(
+                "{promote}cast<{cast}>(__return_value)",
+                cast = match self.kind() {
+                    TypeKind::Float if self.inner_size() == 16 => "float16_t".to_string(),
+                    TypeKind::Float if self.inner_size() == 32 => "float".to_string(),
+                    TypeKind::Float if self.inner_size() == 64 => "double".to_string(),
+                    TypeKind::Int(Sign::Signed) => format!("int{}_t", self.inner_size()),
+                    TypeKind::Int(Sign::Unsigned) => format!("uint{}_t", self.inner_size()),
+                    TypeKind::Poly => format!("poly{}_t", self.inner_size()),
+                    ty => todo!("print_result_c - Unknown type: {:#?}", ty),
+                },
+                promote = self.c_promotion(),
+            )
+        };
+
+        format!(
+            r#"{indentation}std::cout << "Result {additional}-" << i+1 << ": {ty}" << std::fixed << std::setprecision(150) <<  {lanes} << "{close}" << std::endl;"#,
+            ty = if self.is_simd() {
+                format!("{}(", self.c_type())
+            } else {
+                String::from("")
+            },
+            close = if self.is_simd() { ")" } else { "" },
+        )
+    }
 }
 
 impl ArmIntrinsicType {
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 84755ce5250..28902b3dfe9 100644
--- a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs
+++ b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs
@@ -1,6 +1,7 @@
+use crate::common::intrinsic::Intrinsic;
+
 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.
@@ -8,7 +9,7 @@ const PASSES: u32 = 20;
 
 pub fn generate_c_test_loop<T: IntrinsicTypeDefinition + Sized>(
     w: &mut impl std::io::Write,
-    intrinsic: &dyn IntrinsicDefinition<T>,
+    intrinsic: &Intrinsic<T>,
     indentation: Indentation,
     additional: &str,
     passes: u32,
@@ -21,16 +22,18 @@ pub fn generate_c_test_loop<T: IntrinsicTypeDefinition + Sized>(
             {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)
+        loaded_args = intrinsic.arguments.load_values_c(body_indentation),
+        intrinsic_call = intrinsic.name,
+        args = intrinsic.arguments.as_call_param_c(),
+        print_result = intrinsic
+            .results
+            .print_result_c(body_indentation, additional)
     )
 }
 
 pub fn generate_c_constraint_blocks<'a, T: IntrinsicTypeDefinition + 'a>(
     w: &mut impl std::io::Write,
-    intrinsic: &dyn IntrinsicDefinition<T>,
+    intrinsic: &Intrinsic<T>,
     indentation: Indentation,
     constraints: &mut (impl Iterator<Item = &'a Argument<T>> + Clone),
     name: String,
@@ -63,14 +66,14 @@ pub fn generate_c_constraint_blocks<'a, T: IntrinsicTypeDefinition + 'a>(
 // Compiles C test programs using specified compiler
 pub fn create_c_test_function<T: IntrinsicTypeDefinition>(
     w: &mut impl std::io::Write,
-    intrinsic: &dyn IntrinsicDefinition<T>,
+    intrinsic: &Intrinsic<T>,
 ) -> std::io::Result<()> {
     let indentation = Indentation::default();
 
-    writeln!(w, "int run_{}() {{", intrinsic.name())?;
+    writeln!(w, "int run_{}() {{", intrinsic.name)?;
 
     // Define the arrays of arguments.
-    let arguments = intrinsic.arguments();
+    let arguments = &intrinsic.arguments;
     arguments.gen_arglists_c(w, indentation.nested(), PASSES)?;
 
     generate_c_constraint_blocks(
@@ -90,9 +93,9 @@ pub fn create_c_test_function<T: IntrinsicTypeDefinition>(
 pub fn write_mod_cpp<T: IntrinsicTypeDefinition>(
     w: &mut impl std::io::Write,
     notice: &str,
-    architecture: &str,
     platform_headers: &[&str],
-    intrinsics: &[impl IntrinsicDefinition<T>],
+    forward_declarations: &str,
+    intrinsics: &[Intrinsic<T>],
 ) -> std::io::Result<()> {
     write!(w, "{notice}")?;
 
@@ -122,12 +125,7 @@ std::ostream& operator<<(std::ostream& os, float16_t value);
 "#
     )?;
 
-    writeln!(w, "#ifdef __{architecture}__")?;
-    writeln!(
-        w,
-        "std::ostream& operator<<(std::ostream& os, poly128_t value);"
-    )?;
-    writeln!(w, "#endif")?;
+    writeln!(w, "{}", forward_declarations)?;
 
     for intrinsic in intrinsics {
         create_c_test_function(w, intrinsic)?;
@@ -138,7 +136,6 @@ std::ostream& operator<<(std::ostream& os, float16_t value);
 
 pub fn write_main_cpp<'a>(
     w: &mut impl std::io::Write,
-    architecture: &str,
     arch_specific_definitions: &str,
     intrinsics: impl Iterator<Item = &'a str> + Clone,
 ) -> std::io::Result<()> {
@@ -167,9 +164,8 @@ std::ostream& operator<<(std::ostream& os, float16_t value) {{
 "#
     )?;
 
-    writeln!(w, "#ifdef __{architecture}__")?;
+    // NOTE: It's assumed that this value contains the required `ifdef`s.
     writeln!(w, "{arch_specific_definitions }")?;
-    writeln!(w, "#endif")?;
 
     for intrinsic in intrinsics.clone() {
         writeln!(w, "extern int run_{intrinsic}(void);")?;
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 2a02b8fdff1..c6b964a9ce4 100644
--- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs
+++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs
@@ -1,8 +1,10 @@
 use itertools::Itertools;
 use std::process::Command;
 
+use crate::common::intrinsic::Intrinsic;
+
 use super::indentation::Indentation;
-use super::intrinsic::{IntrinsicDefinition, format_f16_return_value};
+use super::intrinsic::format_f16_return_value;
 use super::intrinsic_helpers::IntrinsicTypeDefinition;
 
 // The number of times each intrinsic will be called.
@@ -96,11 +98,10 @@ pub fn write_main_rs<'a>(
 
 pub fn write_lib_rs<T: IntrinsicTypeDefinition>(
     w: &mut impl std::io::Write,
-    architecture: &str,
     notice: &str,
     cfg: &str,
     definitions: &str,
-    intrinsics: &[impl IntrinsicDefinition<T>],
+    intrinsics: &[Intrinsic<T>],
 ) -> std::io::Result<()> {
     write!(w, "{notice}")?;
 
@@ -115,8 +116,6 @@ pub fn write_lib_rs<T: IntrinsicTypeDefinition>(
 
     writeln!(w, "{cfg}")?;
 
-    writeln!(w, "use core_arch::arch::{architecture}::*;")?;
-
     writeln!(w, "{definitions}")?;
 
     for intrinsic in intrinsics {
@@ -189,16 +188,16 @@ pub fn compile_rust_programs(toolchain: Option<&str>, target: &str, linker: Opti
 
 pub fn generate_rust_test_loop<T: IntrinsicTypeDefinition>(
     w: &mut impl std::io::Write,
-    intrinsic: &dyn IntrinsicDefinition<T>,
+    intrinsic: &Intrinsic<T>,
     indentation: Indentation,
     specializations: &[Vec<u8>],
     passes: u32,
 ) -> std::io::Result<()> {
-    let intrinsic_name = intrinsic.name();
+    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()) {
+    for _ in intrinsic.arguments.iter().filter(|a| !a.has_constraint()) {
         coerce += "_, ";
     }
     coerce += ") -> _";
@@ -248,13 +247,13 @@ pub fn generate_rust_test_loop<T: IntrinsicTypeDefinition>(
                     }}\n\
                 }}\n\
             }}",
-        loaded_args = intrinsic.arguments().load_values_rust(indentation3),
-        args = intrinsic.arguments().as_call_param_rust(),
+        loaded_args = intrinsic.arguments.load_values_rust(indentation3),
+        args = intrinsic.arguments.as_call_param_rust(),
     )
 }
 
 /// Generate the specializations (unique sequences of const-generic arguments) for this intrinsic.
-fn generate_rust_specializations<'a>(
+fn generate_rust_specializations(
     constraints: &mut impl Iterator<Item = impl Iterator<Item = i64>>,
 ) -> Vec<Vec<u8>> {
     let mut specializations = vec![vec![]];
@@ -277,15 +276,15 @@ fn generate_rust_specializations<'a>(
 // Top-level function to create complete test program
 pub fn create_rust_test_module<T: IntrinsicTypeDefinition>(
     w: &mut impl std::io::Write,
-    intrinsic: &dyn IntrinsicDefinition<T>,
+    intrinsic: &Intrinsic<T>,
 ) -> std::io::Result<()> {
-    trace!("generating `{}`", intrinsic.name());
+    trace!("generating `{}`", intrinsic.name);
     let indentation = Indentation::default();
 
-    writeln!(w, "pub fn run_{}() {{", intrinsic.name())?;
+    writeln!(w, "pub fn run_{}() {{", intrinsic.name)?;
 
     // Define the arrays of arguments.
-    let arguments = intrinsic.arguments();
+    let arguments = &intrinsic.arguments;
     arguments.gen_arglists_rust(w, indentation.nested(), PASSES)?;
 
     // Define any const generics as `const` items, then generate the actual test loop.
diff --git a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs
index bc46ccfbac4..95276d19b72 100644
--- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs
+++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic.rs
@@ -1,5 +1,4 @@
 use super::argument::ArgumentList;
-use super::indentation::Indentation;
 use super::intrinsic_helpers::{IntrinsicTypeDefinition, TypeKind};
 
 /// An intrinsic
@@ -18,32 +17,14 @@ pub struct Intrinsic<T: IntrinsicTypeDefinition> {
     pub arch_tags: Vec<String>,
 }
 
-pub trait IntrinsicDefinition<T>
-where
-    T: IntrinsicTypeDefinition,
-{
-    fn arguments(&self) -> ArgumentList<T>;
-
-    fn results(&self) -> T;
-
-    fn name(&self) -> String;
-
-    /// Generates a std::cout for the intrinsics results that will match the
-    /// 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;
-}
-
-pub fn format_f16_return_value<T: IntrinsicTypeDefinition>(
-    intrinsic: &dyn IntrinsicDefinition<T>,
-) -> String {
+pub fn format_f16_return_value<T: IntrinsicTypeDefinition>(intrinsic: &Intrinsic<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)",
+    let return_value = match intrinsic.results.kind() {
+        TypeKind::Float if intrinsic.results.inner_size() == 16 => "debug_f16(__return_value)",
         _ => "format_args!(\"{__return_value:.150?}\")",
     };
 
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 f5e84ca97af..7bc1015a387 100644
--- a/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs
+++ b/library/stdarch/crates/intrinsic-test/src/common/intrinsic_helpers.rs
@@ -325,4 +325,9 @@ pub trait IntrinsicTypeDefinition: Deref<Target = IntrinsicType> {
 
     /// can be directly defined in `impl` blocks
     fn c_single_vector_type(&self) -> String;
+
+    /// Generates a std::cout for the intrinsics results that will match the
+    /// 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;
 }
diff --git a/library/stdarch/crates/intrinsic-test/src/common/mod.rs b/library/stdarch/crates/intrinsic-test/src/common/mod.rs
index 5a57c8027db..666b3885c14 100644
--- a/library/stdarch/crates/intrinsic-test/src/common/mod.rs
+++ b/library/stdarch/crates/intrinsic-test/src/common/mod.rs
@@ -1,5 +1,20 @@
+use std::fs::File;
+
+use rayon::prelude::*;
+
 use cli::ProcessedCli;
 
+use crate::common::{
+    compile_c::CppCompilation,
+    gen_c::{write_main_cpp, write_mod_cpp},
+    gen_rust::{
+        compile_rust_programs, write_bin_cargo_toml, write_lib_cargo_toml, write_lib_rs,
+        write_main_rs,
+    },
+    intrinsic::Intrinsic,
+    intrinsic_helpers::IntrinsicTypeDefinition,
+};
+
 pub mod argument;
 pub mod cli;
 pub mod compare;
@@ -15,12 +30,162 @@ pub mod values;
 /// Architectures must support this trait
 /// to be successfully tested.
 pub trait SupportedArchitectureTest {
-    fn create(cli_options: ProcessedCli) -> Box<Self>
-    where
-        Self: Sized;
-    fn build_c_file(&self) -> bool;
-    fn build_rust_file(&self) -> bool;
-    fn compare_outputs(&self) -> bool;
+    type IntrinsicImpl: IntrinsicTypeDefinition + Sync;
+
+    fn cli_options(&self) -> &ProcessedCli;
+    fn intrinsics(&self) -> &[Intrinsic<Self::IntrinsicImpl>];
+
+    fn create(cli_options: ProcessedCli) -> Self;
+
+    const NOTICE: &str;
+
+    const PLATFORM_C_HEADERS: &[&str];
+    const PLATFORM_C_DEFINITIONS: &str;
+    const PLATFORM_C_FORWARD_DECLARATIONS: &str;
+
+    const PLATFORM_RUST_CFGS: &str;
+    const PLATFORM_RUST_DEFINITIONS: &str;
+
+    fn cpp_compilation(&self) -> Option<CppCompilation>;
+
+    fn build_c_file(&self) -> bool {
+        let (chunk_size, chunk_count) = chunk_info(self.intrinsics().len());
+
+        let cpp_compiler_wrapped = self.cpp_compilation();
+
+        std::fs::create_dir_all("c_programs").unwrap();
+        self.intrinsics()
+            .par_chunks(chunk_size)
+            .enumerate()
+            .map(|(i, chunk)| {
+                let c_filename = format!("c_programs/mod_{i}.cpp");
+                let mut file = File::create(&c_filename).unwrap();
+                write_mod_cpp(
+                    &mut file,
+                    Self::NOTICE,
+                    Self::PLATFORM_C_HEADERS,
+                    Self::PLATFORM_C_FORWARD_DECLARATIONS,
+                    chunk,
+                )
+                .unwrap();
+
+                // compile this cpp file into a .o file.
+                //
+                // This is done because `cpp_compiler_wrapped` is None when
+                // the --generate-only flag is passed
+                if let Some(cpp_compiler) = cpp_compiler_wrapped.as_ref() {
+                    let output = cpp_compiler
+                        .compile_object_file(&format!("mod_{i}.cpp"), &format!("mod_{i}.o"))?;
+                    assert!(output.status.success(), "{output:?}");
+                }
+
+                Ok(())
+            })
+            .collect::<Result<(), std::io::Error>>()
+            .unwrap();
+
+        let mut file = File::create("c_programs/main.cpp").unwrap();
+        write_main_cpp(
+            &mut file,
+            Self::PLATFORM_C_DEFINITIONS,
+            self.intrinsics().iter().map(|i| i.name.as_str()),
+        )
+        .unwrap();
+
+        // This is done because `cpp_compiler_wrapped` is None when
+        // the --generate-only flag is passed
+        if let Some(cpp_compiler) = cpp_compiler_wrapped.as_ref() {
+            // compile this cpp file into a .o file
+            info!("compiling main.cpp");
+            let output = cpp_compiler
+                .compile_object_file("main.cpp", "intrinsic-test-programs.o")
+                .unwrap();
+            assert!(output.status.success(), "{output:?}");
+
+            let object_files = (0..chunk_count)
+                .map(|i| format!("mod_{i}.o"))
+                .chain(["intrinsic-test-programs.o".to_owned()]);
+
+            let output = cpp_compiler
+                .link_executable(object_files, "intrinsic-test-programs")
+                .unwrap();
+            assert!(output.status.success(), "{output:?}");
+        }
+
+        true
+    }
+
+    fn build_rust_file(&self) -> bool {
+        std::fs::create_dir_all("rust_programs/src").unwrap();
+
+        let (chunk_size, chunk_count) = chunk_info(self.intrinsics().len());
+
+        let mut cargo = File::create("rust_programs/Cargo.toml").unwrap();
+        write_bin_cargo_toml(&mut cargo, chunk_count).unwrap();
+
+        let mut main_rs = File::create("rust_programs/src/main.rs").unwrap();
+        write_main_rs(
+            &mut main_rs,
+            chunk_count,
+            Self::PLATFORM_RUST_CFGS,
+            "",
+            self.intrinsics().iter().map(|i| i.name.as_str()),
+        )
+        .unwrap();
+
+        let target = &self.cli_options().target;
+        let toolchain = self.cli_options().toolchain.as_deref();
+        let linker = self.cli_options().linker.as_deref();
+
+        self.intrinsics()
+            .par_chunks(chunk_size)
+            .enumerate()
+            .map(|(i, chunk)| {
+                std::fs::create_dir_all(format!("rust_programs/mod_{i}/src"))?;
+
+                let rust_filename = format!("rust_programs/mod_{i}/src/lib.rs");
+                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,
+                    chunk,
+                )?;
+
+                let toml_filename = format!("rust_programs/mod_{i}/Cargo.toml");
+                trace!("generating `{toml_filename}`");
+                let mut file = File::create(toml_filename).unwrap();
+
+                write_lib_cargo_toml(&mut file, &format!("mod_{i}"))?;
+
+                Ok(())
+            })
+            .collect::<Result<(), std::io::Error>>()
+            .unwrap();
+
+        compile_rust_programs(toolchain, target, linker)
+    }
+
+    fn compare_outputs(&self) -> bool {
+        if self.cli_options().toolchain.is_some() {
+            let intrinsics_name_list = self
+                .intrinsics()
+                .iter()
+                .map(|i| i.name.clone())
+                .collect::<Vec<_>>();
+
+            compare::compare_outputs(
+                &intrinsics_name_list,
+                &self.cli_options().runner,
+                &self.cli_options().target,
+            )
+        } else {
+            true
+        }
+    }
 }
 
 pub fn chunk_info(intrinsic_count: usize) -> (usize, usize) {
diff --git a/library/stdarch/crates/intrinsic-test/src/main.rs b/library/stdarch/crates/intrinsic-test/src/main.rs
index 538f317a297..44d7aafd827 100644
--- a/library/stdarch/crates/intrinsic-test/src/main.rs
+++ b/library/stdarch/crates/intrinsic-test/src/main.rs
@@ -13,23 +13,16 @@ fn main() {
     let args: Cli = clap::Parser::parse();
     let processed_cli_options = ProcessedCli::new(args);
 
-    let test_environment_result: Option<Box<dyn SupportedArchitectureTest>> =
-        match processed_cli_options.target.as_str() {
-            "aarch64-unknown-linux-gnu"
-            | "armv7-unknown-linux-gnueabihf"
-            | "aarch64_be-unknown-linux-gnu" => {
-                Some(ArmArchitectureTest::create(processed_cli_options))
-            }
+    match processed_cli_options.target.as_str() {
+        "aarch64-unknown-linux-gnu"
+        | "armv7-unknown-linux-gnueabihf"
+        | "aarch64_be-unknown-linux-gnu" => run(ArmArchitectureTest::create(processed_cli_options)),
 
-            _ => None,
-        };
-
-    if test_environment_result.is_none() {
-        std::process::exit(0);
+        _ => std::process::exit(0),
     }
+}
 
-    let test_environment = test_environment_result.unwrap();
-
+fn run(test_environment: impl SupportedArchitectureTest) {
     info!("building C binaries");
     if !test_environment.build_c_file() {
         std::process::exit(2);