From d09ae822a356e90e68aa98f7abf59d1a759b84e4 Mon Sep 17 00:00:00 2001 From: Madhav Madhusoodanan Date: Fri, 25 Jul 2025 18:21:03 +0530 Subject: [PATCH 1/5] Update constraint.rs --- crates/intrinsic-test/src/common/constraint.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/intrinsic-test/src/common/constraint.rs b/crates/intrinsic-test/src/common/constraint.rs index 269fb7f90c..9c2d8b67f6 100644 --- a/crates/intrinsic-test/src/common/constraint.rs +++ b/crates/intrinsic-test/src/common/constraint.rs @@ -1,9 +1,12 @@ use serde::Deserialize; use std::ops::Range; +/// Describes the values to test for a const generic parameter. #[derive(Debug, PartialEq, Clone, Deserialize)] pub enum Constraint { + /// Test a single value. Equal(i64), + /// Test a range of values, e.g. `0..16`. Range(Range), } From 808fdaef22eb9fb5b78c798d930cc2256470fb19 Mon Sep 17 00:00:00 2001 From: Madhav Madhusoodanan Date: Fri, 25 Jul 2025 23:38:16 +0530 Subject: [PATCH 2/5] chore: handling the case when --generate-only is passed to `intrinsic-test` --- crates/intrinsic-test/src/arm/mod.rs | 53 ++++++++++++++++------------ 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/crates/intrinsic-test/src/arm/mod.rs b/crates/intrinsic-test/src/arm/mod.rs index 5d0320c4cd..f53f6f063f 100644 --- a/crates/intrinsic-test/src/arm/mod.rs +++ b/crates/intrinsic-test/src/arm/mod.rs @@ -4,7 +4,7 @@ mod intrinsic; mod json_parser; mod types; -use std::fs::File; +use std::fs; use rayon::prelude::*; @@ -69,28 +69,31 @@ impl SupportedArchitectureTest for ArmArchitectureTest { let (chunk_size, chunk_count) = chunk_info(self.intrinsics.len()); - let cpp_compiler = compile::build_cpp_compilation(&self.cli_options).unwrap(); + 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(); + let mut file = fs::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 - let output = cpp_compiler - .compile_object_file(&format!("mod_{i}.cpp"), &format!("mod_{i}.o"))?; - assert!(output.status.success(), "{output:?}"); + 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::>() .unwrap(); - let mut file = File::create("c_programs/main.cpp").unwrap(); + let mut file = fs::File::create("c_programs/main.cpp").unwrap(); write_main_cpp( &mut file, c_target, @@ -100,20 +103,22 @@ impl SupportedArchitectureTest for ArmArchitectureTest { .unwrap(); // 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:?}"); + if let Some(cpp_compiler) = cpp_compiler_wrapped.as_ref() { + 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 } @@ -172,7 +177,11 @@ impl SupportedArchitectureTest for ArmArchitectureTest { .collect::>() .unwrap(); - compile_rust_programs(toolchain, target, linker) + if self.cli_options.toolchain.is_some() { + compile_rust_programs(toolchain, target, linker) + } else { + true + } } fn compare_outputs(&self) -> bool { From eec7134c83b7f4ab0c1d14e747a411fa21dd3d71 Mon Sep 17 00:00:00 2001 From: Madhav Madhusoodanan Date: Thu, 24 Jul 2025 12:59:32 +0530 Subject: [PATCH 3/5] feat: added a new variant of Constraint struct, to enable support for discrete constant values --- crates/intrinsic-test/src/common/constraint.rs | 8 +++++--- crates/intrinsic-test/src/common/gen_c.rs | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/crates/intrinsic-test/src/common/constraint.rs b/crates/intrinsic-test/src/common/constraint.rs index 9c2d8b67f6..6acd23c12e 100644 --- a/crates/intrinsic-test/src/common/constraint.rs +++ b/crates/intrinsic-test/src/common/constraint.rs @@ -8,13 +8,15 @@ pub enum Constraint { Equal(i64), /// Test a range of values, e.g. `0..16`. Range(Range), + Set(Vec), } impl Constraint { - pub fn to_range(&self) -> Range { + pub fn to_vector(&self) -> Vec { match self { - Constraint::Equal(eq) => *eq..*eq + 1, - Constraint::Range(range) => range.clone(), + Constraint::Equal(eq) => vec![*eq], + Constraint::Range(range) => range.clone().collect::>(), + Constraint::Set(values) => values.clone(), } } } diff --git a/crates/intrinsic-test/src/common/gen_c.rs b/crates/intrinsic-test/src/common/gen_c.rs index 905efb6d89..04b550858e 100644 --- a/crates/intrinsic-test/src/common/gen_c.rs +++ b/crates/intrinsic-test/src/common/gen_c.rs @@ -40,7 +40,7 @@ pub fn generate_c_constraint_blocks<'a, T: IntrinsicTypeDefinition + 'a>( }; let body_indentation = indentation.nested(); - for i in current.constraint.iter().flat_map(|c| c.to_range()) { + for i in current.constraint.iter().flat_map(|c| c.to_vector()) { let ty = current.ty.c_type(); writeln!(w, "{indentation}{{")?; From 17f35f4898fda7a9377c3753eacb93624f00e3d7 Mon Sep 17 00:00:00 2001 From: Madhav Madhusoodanan Date: Thu, 24 Jul 2025 12:45:08 +0530 Subject: [PATCH 4/5] chore: Move from IntrinsicType::target to intrinsicType::metadata to support architecture-specific use cases --- crates/intrinsic-test/src/arm/argument.rs | 12 +++++++ crates/intrinsic-test/src/arm/json_parser.rs | 17 +++++---- crates/intrinsic-test/src/arm/mod.rs | 1 + crates/intrinsic-test/src/arm/types.rs | 20 +++++++---- crates/intrinsic-test/src/common/argument.rs | 36 +++++-------------- .../src/common/intrinsic_helpers.rs | 9 +++-- 6 files changed, 54 insertions(+), 41 deletions(-) create mode 100644 crates/intrinsic-test/src/arm/argument.rs diff --git a/crates/intrinsic-test/src/arm/argument.rs b/crates/intrinsic-test/src/arm/argument.rs new file mode 100644 index 0000000000..db5501e5d2 --- /dev/null +++ b/crates/intrinsic-test/src/arm/argument.rs @@ -0,0 +1,12 @@ +use crate::arm::intrinsic::ArmIntrinsicType; +use crate::common::argument::Argument; + +impl Argument { + pub fn type_and_name_from_c(arg: &str) -> (&str, &str) { + let split_index = arg + .rfind([' ', '*']) + .expect("Couldn't split type and argname"); + + (arg[..split_index + 1].trim_end(), &arg[split_index + 1..]) + } +} diff --git a/crates/intrinsic-test/src/arm/json_parser.rs b/crates/intrinsic-test/src/arm/json_parser.rs index 58d366c86a..6af61114f6 100644 --- a/crates/intrinsic-test/src/arm/json_parser.rs +++ b/crates/intrinsic-test/src/arm/json_parser.rs @@ -79,20 +79,25 @@ fn json_to_intrinsic( ) -> Result, Box> { let name = intr.name.replace(['[', ']'], ""); - let results = ArmIntrinsicType::from_c(&intr.return_type.value, target)?; + let mut results = ArmIntrinsicType::from_c(&intr.return_type.value)?; + results.set_metadata("target".to_string(), target.to_string()); let args = intr .arguments .into_iter() .enumerate() .map(|(i, arg)| { - let arg_name = Argument::::type_and_name_from_c(&arg).1; - let metadata = intr.args_prep.as_mut(); - let metadata = metadata.and_then(|a| a.remove(arg_name)); - let arg_prep: Option = metadata.and_then(|a| a.try_into().ok()); + let (type_name, arg_name) = Argument::::type_and_name_from_c(&arg); + let ty = ArmIntrinsicType::from_c(type_name) + .unwrap_or_else(|_| panic!("Failed to parse argument '{arg}'")); + + let arg_prep = intr.args_prep.as_mut(); + let arg_prep = arg_prep.and_then(|a| a.remove(arg_name)); + let arg_prep: Option = arg_prep.and_then(|a| a.try_into().ok()); let constraint: Option = arg_prep.and_then(|a| a.try_into().ok()); - let mut arg = Argument::::from_c(i, &arg, target, constraint); + let mut arg = + Argument::::new(i, arg_name.to_string(), ty, constraint); // The JSON doesn't list immediates as const let IntrinsicType { diff --git a/crates/intrinsic-test/src/arm/mod.rs b/crates/intrinsic-test/src/arm/mod.rs index f53f6f063f..a598be6441 100644 --- a/crates/intrinsic-test/src/arm/mod.rs +++ b/crates/intrinsic-test/src/arm/mod.rs @@ -1,3 +1,4 @@ +mod argument; mod compile; mod config; mod intrinsic; diff --git a/crates/intrinsic-test/src/arm/types.rs b/crates/intrinsic-test/src/arm/types.rs index c06e9355c4..a0f20039b4 100644 --- a/crates/intrinsic-test/src/arm/types.rs +++ b/crates/intrinsic-test/src/arm/types.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use super::intrinsic::ArmIntrinsicType; use crate::common::cli::Language; use crate::common::intrinsic_helpers::{IntrinsicType, IntrinsicTypeDefinition, Sign, TypeKind}; @@ -40,7 +42,7 @@ impl IntrinsicTypeDefinition for ArmIntrinsicType { bit_len: Some(bl), simd_len, vec_len, - target, + metadata, .. } = &self.0 { @@ -50,7 +52,11 @@ impl IntrinsicTypeDefinition for ArmIntrinsicType { "" }; - let choose_workaround = language == Language::C && target.contains("v7"); + let choose_workaround = language == Language::C + && metadata + .get("target") + .filter(|value| value.contains("v7")) + .is_some(); format!( "vld{len}{quad}_{type}{size}", type = match k { @@ -102,15 +108,17 @@ impl IntrinsicTypeDefinition for ArmIntrinsicType { } } - fn from_c(s: &str, target: &str) -> Result { + fn from_c(s: &str) -> Result { const CONST_STR: &str = "const"; + let mut metadata: HashMap = HashMap::new(); + metadata.insert("type".to_string(), s.to_string()); if let Some(s) = s.strip_suffix('*') { let (s, constant) = match s.trim().strip_suffix(CONST_STR) { Some(stripped) => (stripped, true), None => (s, false), }; let s = s.trim_end(); - let temp_return = ArmIntrinsicType::from_c(s, target); + let temp_return = ArmIntrinsicType::from_c(s); temp_return.map(|mut op| { op.ptr = true; op.ptr_constant = constant; @@ -151,7 +159,7 @@ impl IntrinsicTypeDefinition for ArmIntrinsicType { bit_len: Some(bit_len), simd_len, vec_len, - target: target.to_string(), + metadata, })) } else { let kind = start.parse::()?; @@ -167,7 +175,7 @@ impl IntrinsicTypeDefinition for ArmIntrinsicType { bit_len, simd_len: None, vec_len: None, - target: target.to_string(), + metadata, })) } } diff --git a/crates/intrinsic-test/src/common/argument.rs b/crates/intrinsic-test/src/common/argument.rs index 1550cbd97f..f38515e40a 100644 --- a/crates/intrinsic-test/src/common/argument.rs +++ b/crates/intrinsic-test/src/common/argument.rs @@ -20,6 +20,15 @@ impl Argument where T: IntrinsicTypeDefinition, { + pub fn new(pos: usize, name: String, ty: T, constraint: Option) -> Self { + Argument { + pos, + name, + ty, + constraint, + } + } + pub fn to_c_type(&self) -> String { self.ty.c_type() } @@ -36,14 +45,6 @@ where self.constraint.is_some() } - pub fn type_and_name_from_c(arg: &str) -> (&str, &str) { - let split_index = arg - .rfind([' ', '*']) - .expect("Couldn't split type and argname"); - - (arg[..split_index + 1].trim_end(), &arg[split_index + 1..]) - } - /// The binding keyword (e.g. "const" or "let") for the array of possible test inputs. fn rust_vals_array_binding(&self) -> impl std::fmt::Display { if self.ty.is_rust_vals_array_const() { @@ -62,25 +63,6 @@ where } } - pub fn from_c( - pos: usize, - arg: &str, - target: &str, - constraint: Option, - ) -> Argument { - let (ty, var_name) = Self::type_and_name_from_c(arg); - - let ty = - T::from_c(ty, target).unwrap_or_else(|_| panic!("Failed to parse argument '{arg}'")); - - Argument { - pos, - name: String::from(var_name), - ty: ty, - constraint, - } - } - fn as_call_param_c(&self) -> String { self.ty.as_call_param_c(&self.name) } diff --git a/crates/intrinsic-test/src/common/intrinsic_helpers.rs b/crates/intrinsic-test/src/common/intrinsic_helpers.rs index b53047b2d3..4f663dd81c 100644 --- a/crates/intrinsic-test/src/common/intrinsic_helpers.rs +++ b/crates/intrinsic-test/src/common/intrinsic_helpers.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::fmt; use std::ops::Deref; use std::str::FromStr; @@ -121,7 +122,7 @@ pub struct IntrinsicType { /// A value of `None` can be assumed to be 1 though. pub vec_len: Option, - pub target: String, + pub metadata: HashMap, } impl IntrinsicType { @@ -153,6 +154,10 @@ impl IntrinsicType { self.ptr } + pub fn set_metadata(&mut self, key: String, value: String) { + self.metadata.insert(key, value); + } + pub fn c_scalar_type(&self) -> String { match self.kind() { TypeKind::Char(_) => String::from("char"), @@ -322,7 +327,7 @@ pub trait IntrinsicTypeDefinition: Deref { fn get_lane_function(&self) -> String; /// can be implemented in an `impl` block - fn from_c(_s: &str, _target: &str) -> Result + fn from_c(_s: &str) -> Result where Self: Sized; From 357aca7c80a0e096a6574dff0e4364d8122c7046 Mon Sep 17 00:00:00 2001 From: Madhav Madhusoodanan Date: Sat, 26 Jul 2025 17:26:45 +0530 Subject: [PATCH 5/5] fix: rebasing changes from master --- crates/intrinsic-test/src/arm/mod.rs | 2 +- crates/intrinsic-test/src/common/gen_rust.rs | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/crates/intrinsic-test/src/arm/mod.rs b/crates/intrinsic-test/src/arm/mod.rs index a598be6441..6e01d182d7 100644 --- a/crates/intrinsic-test/src/arm/mod.rs +++ b/crates/intrinsic-test/src/arm/mod.rs @@ -5,7 +5,7 @@ mod intrinsic; mod json_parser; mod types; -use std::fs; +use std::fs::{self, File}; use rayon::prelude::*; diff --git a/crates/intrinsic-test/src/common/gen_rust.rs b/crates/intrinsic-test/src/common/gen_rust.rs index 60bb577a80..cfcaf1086f 100644 --- a/crates/intrinsic-test/src/common/gen_rust.rs +++ b/crates/intrinsic-test/src/common/gen_rust.rs @@ -138,10 +138,8 @@ pub fn compile_rust_programs(toolchain: Option<&str>, target: &str, linker: Opti // Do not use the target directory of the workspace please. cargo_command.env("CARGO_TARGET_DIR", "target"); - if let Some(toolchain) = toolchain - && !toolchain.is_empty() - { - cargo_command.arg(toolchain); + if toolchain.is_some_and(|val| !val.is_empty()) { + cargo_command.arg(toolchain.unwrap()); } cargo_command.args(["build", "--target", target, "--release"]); @@ -251,12 +249,13 @@ pub fn generate_rust_test_loop( /// Generate the specializations (unique sequences of const-generic arguments) for this intrinsic. fn generate_rust_specializations<'a>( - constraints: &mut impl Iterator>, + constraints: &mut impl Iterator>, ) -> Vec> { let mut specializations = vec![vec![]]; for constraint in constraints { specializations = constraint + .into_iter() .flat_map(|right| { specializations.iter().map(move |left| { let mut left = left.clone(); @@ -288,7 +287,7 @@ pub fn create_rust_test_module( let specializations = generate_rust_specializations( &mut arguments .iter() - .filter_map(|i| i.constraint.as_ref().map(|v| v.to_range())), + .filter_map(|i| i.constraint.as_ref().map(|v| v.to_vector())), ); generate_rust_test_loop(w, intrinsic, indentation, &specializations, PASSES)?;