From 6be8c4c8888dcd415f25625b5bbd7aa8cdfcdaef Mon Sep 17 00:00:00 2001 From: Jacob Bramley Date: Tue, 28 Jan 2025 17:07:19 +0000 Subject: [PATCH] Update stdarch-gen-arm path generation. Fix both the instructions for how to regenerate each `generated.rs`, and the logic for inferring the correct output path from each input `.spec.yml`. --- .../stdarch-gen-arm/src/load_store_tests.rs | 6 +- crates/stdarch-gen-arm/src/main.rs | 117 +++++++++++------- 2 files changed, 77 insertions(+), 46 deletions(-) diff --git a/crates/stdarch-gen-arm/src/load_store_tests.rs b/crates/stdarch-gen-arm/src/load_store_tests.rs index d697a8d22d..83d0ac975c 100644 --- a/crates/stdarch-gen-arm/src/load_store_tests.rs +++ b/crates/stdarch-gen-arm/src/load_store_tests.rs @@ -91,11 +91,11 @@ pub fn generate_load_store_tests( format!( "// This code is automatically generated. DO NOT MODIFY. // -// Instead, modify `crates/stdarch-gen2/spec/sve` and run the following command to re-generate this -// file: +// Instead, modify `crates/stdarch-gen-arm/spec/sve` and run the following command to re-generate +// this file: // // ``` -// cargo run --bin=stdarch-gen2 -- crates/stdarch-gen2/spec +// cargo run --bin=stdarch-gen-arm -- crates/stdarch-gen-arm/spec // ``` {}", quote! { #preamble #(#tests)* #manual_tests } diff --git a/crates/stdarch-gen-arm/src/main.rs b/crates/stdarch-gen-arm/src/main.rs index 22bf6724b0..c78e5dc4e4 100644 --- a/crates/stdarch-gen-arm/src/main.rs +++ b/crates/stdarch-gen-arm/src/main.rs @@ -104,7 +104,10 @@ fn parse_args() -> Vec<(PathBuf, Option)> { let mut args_it = std::env::args().skip(1); assert!( 1 <= args_it.len() && args_it.len() <= 2, - "Usage: cargo run -p stdarch-gen2 -- INPUT_DIR [OUTPUT_DIR]" + "Usage: cargo run -p stdarch-gen-arm -- INPUT_DIR [OUTPUT_DIR]\n\ + where:\n\ + - INPUT_DIR contains a tree like: INPUT_DIR//.spec.yml\n\ + - OUTPUT_DIR is a directory like: crates/core_arch/src/" ); let in_path = Path::new(args_it.next().unwrap().as_str()).to_path_buf(); @@ -124,7 +127,7 @@ fn parse_args() -> Vec<(PathBuf, Option)> { std::env::current_exe() .map(|mut f| { f.pop(); - f.push("../../crates/core_arch/src/aarch64/"); + f.push("../../crates/core_arch/src/"); f.exists().then_some(f) }) .ok() @@ -147,10 +150,10 @@ fn generate_file( out, r#"// This code is automatically generated. DO NOT MODIFY. // -// Instead, modify `crates/stdarch-gen2/spec/` and run the following command to re-generate this file: +// Instead, modify `crates/stdarch-gen-arm/spec/` and run the following command to re-generate this file: // // ``` -// cargo run --bin=stdarch-gen2 -- crates/stdarch-gen2/spec +// cargo run --bin=stdarch-gen-arm -- crates/stdarch-gen-arm/spec // ``` #![allow(improper_ctypes)] @@ -183,17 +186,19 @@ pub fn format_code( output.write_all(proc.wait_with_output()?.stdout.as_slice()) } -/// Derive an output file name from an input file and an output directory. +/// Derive an output file path from an input file path and an output directory. /// -/// The name is formed by: +/// `in_filepath` is expected to have a structure like: +/// ...//.spec.yml /// -/// - ... taking in_filepath.file_name() (dropping all directory components), -/// - ... dropping a .yml or .yaml extension (if present), -/// - ... then dropping a .spec extension (if present). +/// The resulting output path will have a structure like: +/// ///generated.rs /// /// Panics if the resulting name is empty, or if file_name() is not UTF-8. fn make_output_filepath(in_filepath: &Path, out_dirpath: &Path) -> PathBuf { - make_filepath(in_filepath, out_dirpath, |name: &str| format!("{name}.rs")) + make_filepath(in_filepath, out_dirpath, |_name: &str| { + format!("generated.rs") + }) } fn make_tests_filepath(in_filepath: &Path, out_dirpath: &Path) -> PathBuf { @@ -207,22 +212,27 @@ fn make_filepath String>( out_dirpath: &Path, name_formatter: F, ) -> PathBuf { - let mut parts = in_filepath.iter(); - let name = parts - .next_back() - .and_then(|f| f.to_str()) - .expect("Inputs must have valid, UTF-8 file_name()"); - let dir = parts.next_back().unwrap(); + let mut parts = in_filepath.components().rev().map(|f| { + f.as_os_str() + .to_str() + .expect("Inputs must have valid, UTF-8 file_name()") + }); + let yml = parts.next().expect("Not enough input path elements."); + let feature = parts.next().expect("Not enough input path elements."); - let name = name - .trim_end_matches(".yml") - .trim_end_matches(".yaml") - .trim_end_matches(".spec"); - assert!(!name.is_empty()); + let arch = yml + .strip_suffix(".yml") + .expect("Expected .yml file input.") + .strip_suffix(".spec") + .expect("Expected .spec.yml file input."); + if arch.is_empty() { + panic!("Extended ARCH.spec.yml file input."); + } let mut output = out_dirpath.to_path_buf(); - output.push(dir); - output.push(name_formatter(name)); + output.push(arch); + output.push(feature); + output.push(name_formatter(arch)); output } @@ -233,47 +243,68 @@ mod tests { #[test] fn infer_output_file() { macro_rules! t { - ($src:expr, $outdir:expr, $dst:expr) => { + ($src:expr, $outdir:expr, $dst:expr, $ldst:expr) => { let src: PathBuf = $src.iter().collect(); let outdir: PathBuf = $outdir.iter().collect(); let dst: PathBuf = $dst.iter().collect(); + let ldst: PathBuf = $ldst.iter().collect(); assert_eq!(make_output_filepath(&src, &outdir), dst); + assert_eq!(make_tests_filepath(&src, &outdir), ldst); }; } // Documented usage. - t!(["x", "NAME.spec.yml"], [""], ["x", "NAME.rs"]); t!( - ["x", "NAME.spec.yml"], - ["a", "b"], - ["a", "b", "x", "NAME.rs"] + ["FEAT", "ARCH.spec.yml"], + [""], + ["ARCH", "FEAT", "generated.rs"], + ["ARCH", "FEAT", "ld_st_tests_ARCH.rs"] ); t!( - ["x", "y", "NAME.spec.yml"], + ["x", "y", "FEAT", "ARCH.spec.yml"], ["out"], - ["out", "y", "NAME.rs"] + ["out", "ARCH", "FEAT", "generated.rs"], + ["out", "ARCH", "FEAT", "ld_st_tests_ARCH.rs"] ); - t!(["x", "NAME.spec.yaml"], ["out"], ["out", "x", "NAME.rs"]); - t!(["x", "NAME.spec"], ["out"], ["out", "x", "NAME.rs"]); - t!(["x", "NAME.yml"], ["out"], ["out", "x", "NAME.rs"]); - t!(["x", "NAME.yaml"], ["out"], ["out", "x", "NAME.rs"]); - // Unrecognised extensions get treated as part of the stem. t!( - ["x", "NAME.spac.yml"], - ["out"], - ["out", "x", "NAME.spac.rs"] + ["p", "q", "FEAT", "ARCH.spec.yml"], + ["a", "b"], + ["a", "b", "ARCH", "FEAT", "generated.rs"], + ["a", "b", "ARCH", "FEAT", "ld_st_tests_ARCH.rs"] ); - t!(["x", "NAME.txt"], ["out"], ["out", "x", "NAME.txt.rs"]); - // Always take the top-level directory from the input path + // Extra extensions get treated as part of the stem. t!( - ["x", "y", "z", "NAME.spec.yml"], + ["FEAT", "ARCH.variant.spec.yml"], ["out"], - ["out", "z", "NAME.rs"] + ["out", "ARCH.variant", "FEAT", "generated.rs"], + ["out", "ARCH.variant", "FEAT", "ld_st_tests_ARCH.variant.rs"] ); } #[test] #[should_panic] fn infer_output_file_no_stem() { - make_output_filepath(Path::new(".spec.yml"), Path::new("")); + let src = PathBuf::from("FEAT/.spec.yml"); + make_output_filepath(&src, Path::new("")); + } + + #[test] + #[should_panic] + fn infer_output_file_no_feat() { + let src = PathBuf::from("ARCH.spec.yml"); + make_output_filepath(&src, Path::new("")); + } + + #[test] + #[should_panic] + fn infer_output_file_ldst_no_stem() { + let src = PathBuf::from("FEAT/.spec.yml"); + make_tests_filepath(&src, Path::new("")); + } + + #[test] + #[should_panic] + fn infer_output_file_ldst_no_feat() { + let src = PathBuf::from("ARCH.spec.yml"); + make_tests_filepath(&src, Path::new("")); } }