diff --git a/crates/assert-instr-macro/Cargo.toml b/crates/assert-instr-macro/Cargo.toml index 4ad654e695..881c8109c1 100644 --- a/crates/assert-instr-macro/Cargo.toml +++ b/crates/assert-instr-macro/Cargo.toml @@ -11,4 +11,4 @@ test = false [dependencies] proc-macro2 = "1.0" quote = "1.0" -syn = { version = "1.0", features = ["full"] } +syn = { version = "2.0", features = ["full"] } diff --git a/crates/assert-instr-macro/src/lib.rs b/crates/assert-instr-macro/src/lib.rs index dfda3b48bf..c9de43943f 100644 --- a/crates/assert-instr-macro/src/lib.rs +++ b/crates/assert-instr-macro/src/lib.rs @@ -38,7 +38,7 @@ pub fn assert_instr( let maybe_allow_deprecated = if func .attrs .iter() - .any(|attr| attr.path.is_ident("deprecated")) + .any(|attr| attr.path().is_ident("deprecated")) { quote! { #[allow(deprecated)] } } else { @@ -117,7 +117,7 @@ pub fn assert_instr( .attrs .iter() .filter(|attr| { - attr.path + attr.path() .segments .first() .expect("attr.path.segments.first() failed") diff --git a/crates/intrinsic-test/Cargo.toml b/crates/intrinsic-test/Cargo.toml index d977dd659b..c7a18f77f5 100644 --- a/crates/intrinsic-test/Cargo.toml +++ b/crates/intrinsic-test/Cargo.toml @@ -12,10 +12,10 @@ lazy_static = "1.4.0" serde = { version = "1", features = ["derive"] } serde_json = "1.0" csv = "1.1" -clap = "2.33.3" +clap = { version = "4.4", features = ["derive"] } regex = "1.4.2" log = "0.4.11" -pretty_env_logger = "0.4.0" +pretty_env_logger = "0.5.0" rayon = "1.5.0" diff = "0.1.12" -itertools = "0.10.1" +itertools = "0.11.0" diff --git a/crates/intrinsic-test/README.md b/crates/intrinsic-test/README.md index 8a8ddab404..2b3f0c75a2 100644 --- a/crates/intrinsic-test/README.md +++ b/crates/intrinsic-test/README.md @@ -4,15 +4,17 @@ each produces the same result from random inputs. # Usage ``` USAGE: - intrinsic-test [OPTIONS] + intrinsic-test [FLAGS] [OPTIONS] FLAGS: + --a32 Run tests for A32 instrinsics instead of A64 -h, --help Prints help information -V, --version Prints version information OPTIONS: --cppcompiler The C++ compiler to use for compiling the c++ code [default: clang++] --runner Run the C programs under emulation with this command + --skip Filename for a list of intrinsics to skip (one per line) --toolchain The rust toolchain to use for building the rust code ARGS: diff --git a/crates/intrinsic-test/src/json_parser.rs b/crates/intrinsic-test/src/json_parser.rs index bc6fa4a9ed..8b3c7869c6 100644 --- a/crates/intrinsic-test/src/json_parser.rs +++ b/crates/intrinsic-test/src/json_parser.rs @@ -1,4 +1,5 @@ use std::collections::HashMap; +use std::path::Path; use serde::Deserialize; @@ -41,7 +42,7 @@ struct JsonIntrinsic { architectures: Vec, } -pub fn get_neon_intrinsics(filename: &str) -> Result, Box> { +pub fn get_neon_intrinsics(filename: &Path) -> Result, Box> { let file = std::fs::File::open(filename)?; let reader = std::io::BufReader::new(file); let json: Vec = serde_json::from_reader(reader).expect("Couldn't parse JSON"); diff --git a/crates/intrinsic-test/src/main.rs b/crates/intrinsic-test/src/main.rs index 76d2da3abf..15bc021c75 100644 --- a/crates/intrinsic-test/src/main.rs +++ b/crates/intrinsic-test/src/main.rs @@ -4,9 +4,9 @@ extern crate log; use std::fs::File; use std::io::Write; +use std::path::PathBuf; use std::process::Command; -use clap::{App, Arg}; use intrinsic::Intrinsic; use itertools::Itertools; use rayon::prelude::*; @@ -320,58 +320,47 @@ path = "{intrinsic}/main.rs""#, } } +/// Intrinsic test tool +#[derive(clap::Parser)] +#[command( + name = "Intrinsic test tool", + about = "Generates Rust and C programs for intrinsics and compares the output" +)] +struct Cli { + /// The input file containing the intrinsics + input: PathBuf, + + /// The rust toolchain to use for building the rust code + #[arg(long)] + toolchain: Option, + + /// The C++ compiler to use for compiling the c++ code + #[arg(long, default_value_t = String::from("clang++"))] + cppcompiler: String, + + /// Run the C programs under emulation with this command + #[arg(long)] + runner: Option, + + /// Filename for a list of intrinsics to skip (one per line) + #[arg(long)] + skip: Option, + + /// Run tests for A32 instrinsics instead of A64 + #[arg(long)] + a32: bool, +} + fn main() { pretty_env_logger::init(); - let matches = App::new("Intrinsic test tool") - .about("Generates Rust and C programs for intrinsics and compares the output") - .arg( - Arg::with_name("INPUT") - .help("The input file containing the intrinsics") - .required(true) - .index(1), - ) - .arg( - Arg::with_name("TOOLCHAIN") - .takes_value(true) - .long("toolchain") - .help("The rust toolchain to use for building the rust code"), - ) - .arg( - Arg::with_name("CPPCOMPILER") - .takes_value(true) - .default_value("clang++") - .long("cppcompiler") - .help("The C++ compiler to use for compiling the c++ code"), - ) - .arg( - Arg::with_name("RUNNER") - .takes_value(true) - .long("runner") - .help("Run the C programs under emulation with this command"), - ) - .arg( - Arg::with_name("SKIP") - .takes_value(true) - .long("skip") - .help("Filename for a list of intrinsics to skip (one per line)"), - ) - .arg( - Arg::with_name("A32") - .takes_value(false) - .long("a32") - .help("Run tests for A32 instrinsics instead of A64"), - ) - .get_matches(); - - let filename = matches.value_of("INPUT").unwrap(); - let toolchain = matches - .value_of("TOOLCHAIN") - .map_or("".into(), |t| format!("+{t}")); + let args: Cli = clap::Parser::parse(); - let cpp_compiler = matches.value_of("CPPCOMPILER").unwrap(); - let c_runner = matches.value_of("RUNNER").unwrap_or(""); - let skip = if let Some(filename) = matches.value_of("SKIP") { + let filename = args.input; + let toolchain = args.toolchain.map_or_else(String::new, |t| format!("+{t}")); + let cpp_compiler = args.cppcompiler; + let c_runner = args.runner.unwrap_or_else(String::new); + let skip = if let Some(filename) = args.skip { let data = std::fs::read_to_string(&filename).expect("Failed to open file"); data.lines() .map(str::trim) @@ -381,8 +370,8 @@ fn main() { } else { Default::default() }; - let a32 = matches.is_present("A32"); - let mut intrinsics = get_neon_intrinsics(filename).expect("Error parsing input file"); + let a32 = args.a32; + let mut intrinsics = get_neon_intrinsics(&filename).expect("Error parsing input file"); intrinsics.sort_by(|a, b| a.name.cmp(&b.name)); @@ -409,7 +398,7 @@ fn main() { let notices = build_notices("// "); - if !build_c(¬ices, &intrinsics, cpp_compiler, a32) { + if !build_c(¬ices, &intrinsics, &cpp_compiler, a32) { std::process::exit(2); } diff --git a/crates/stdarch-test/Cargo.toml b/crates/stdarch-test/Cargo.toml index 3a2130d4e2..3682fcd7ed 100644 --- a/crates/stdarch-test/Cargo.toml +++ b/crates/stdarch-test/Cargo.toml @@ -20,7 +20,7 @@ cc = "1.0" # time, and we want to make updates to this explicit rather than automatically # picking up updates which might break CI with new instruction names. [target.'cfg(target_arch = "wasm32")'.dependencies] -wasmprinter = "=0.2.53" +wasmprinter = "=0.2.67" [features] default = [] diff --git a/crates/stdarch-verify/Cargo.toml b/crates/stdarch-verify/Cargo.toml index 10ae90074d..515f05138a 100644 --- a/crates/stdarch-verify/Cargo.toml +++ b/crates/stdarch-verify/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] proc-macro2 = "1.0" quote = "1.0" -syn = { version = "1.0", features = ["full"] } +syn = { version = "2.0", features = ["full"] } [lib] proc-macro = true @@ -15,5 +15,5 @@ test = false [dev-dependencies] serde = { version = "1.0", features = ['derive'] } -serde-xml-rs = "0.3" +serde-xml-rs = "0.6" serde_json = "1.0.96" diff --git a/crates/stdarch-verify/src/lib.rs b/crates/stdarch-verify/src/lib.rs index a9bf89f707..3f9eb3bf9b 100644 --- a/crates/stdarch-verify/src/lib.rs +++ b/crates/stdarch-verify/src/lib.rs @@ -7,6 +7,7 @@ extern crate syn; use proc_macro::TokenStream; use std::{fs::File, io::Read, path::Path}; use syn::ext::IdentExt; +use syn::parse::Parser as _; #[proc_macro] pub fn x86_functions(input: TokenStream) -> TokenStream { @@ -416,7 +417,7 @@ fn walk(root: &Path, files: &mut Vec<(syn::File, String)>) { fn find_instrs(attrs: &[syn::Attribute]) -> Vec { struct AssertInstr { - instr: String, + instr: Option, } // A small custom parser to parse out the instruction in `assert_instr`. @@ -424,15 +425,21 @@ fn find_instrs(attrs: &[syn::Attribute]) -> Vec { // TODO: should probably just reuse `Invoc` from the `assert-instr-macro` // crate. impl syn::parse::Parse for AssertInstr { - fn parse(content: syn::parse::ParseStream<'_>) -> syn::Result { - let input; - parenthesized!(input in content); - let _ = input.parse::()?; - let _ = input.parse::()?; - let ident = input.parse::()?; - if ident != "assert_instr" { - return Err(input.error("expected `assert_instr`")); + fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { + let _ = input.parse::().unwrap(); + let _ = input.parse::().unwrap(); + + match input.parse::() { + Ok(ident) if ident == "assert_instr" => {} + _ => { + while !input.is_empty() { + // consume everything + drop(input.parse::()); + } + return Ok(Self { instr: None }); + } } + let instrs; parenthesized!(instrs in input); @@ -452,18 +459,24 @@ fn find_instrs(attrs: &[syn::Attribute]) -> Vec { return Err(input.error("failed to parse instruction")); } } - Ok(Self { instr }) + Ok(Self { instr: Some(instr) }) } } attrs .iter() - .filter(|a| a.path.is_ident("cfg_attr")) .filter_map(|a| { - syn::parse2::(a.tokens.clone()) - .ok() - .map(|a| a.instr) + if let syn::Meta::List(ref l) = a.meta { + if l.path.is_ident("cfg_attr") { + Some(l) + } else { + None + } + } else { + None + } }) + .filter_map(|l| syn::parse2::(l.tokens.clone()).unwrap().instr) .collect() } @@ -471,19 +484,26 @@ fn find_target_feature(attrs: &[syn::Attribute]) -> Option { attrs .iter() .flat_map(|a| { - if let Ok(syn::Meta::List(i)) = a.parse_meta() { - if i.path.is_ident("target_feature") { - return i.nested; + if let syn::Meta::List(ref l) = a.meta { + if l.path.is_ident("target_feature") { + if let Ok(l) = + syn::punctuated::Punctuated::::parse_terminated + .parse2(l.tokens.clone()) + { + return l; + } } } syn::punctuated::Punctuated::new() }) - .filter_map(|nested| match nested { - syn::NestedMeta::Meta(m) => Some(m), - syn::NestedMeta::Lit(_) => None, - }) .find_map(|m| match m { - syn::Meta::NameValue(ref i) if i.path.is_ident("enable") => Some(i.clone().lit), + syn::Meta::NameValue(i) if i.path.is_ident("enable") => { + if let syn::Expr::Lit(lit) = i.value { + Some(lit.lit) + } else { + None + } + } _ => None, }) } @@ -491,9 +511,16 @@ fn find_target_feature(attrs: &[syn::Attribute]) -> Option { fn find_required_const(name: &str, attrs: &[syn::Attribute]) -> Vec { attrs .iter() - .flat_map(|a| { - if a.path.segments[0].ident == name { - syn::parse::(a.tokens.clone().into()) + .filter_map(|a| { + if let syn::Meta::List(ref l) = a.meta { + Some(l) + } else { + None + } + }) + .flat_map(|l| { + if l.path.segments[0].ident == name { + syn::parse2::(l.tokens.clone()) .unwrap() .args } else { @@ -509,10 +536,7 @@ struct RustcArgsRequiredConst { impl syn::parse::Parse for RustcArgsRequiredConst { fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result { - let content; - parenthesized!(content in input); - let list = - syn::punctuated::Punctuated::::parse_terminated(&content)?; + let list = syn::punctuated::Punctuated::::parse_terminated(&input)?; Ok(Self { args: list .into_iter() diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 38f497fa61..d9034dd803 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -13,8 +13,8 @@ default-run = "hex" [dependencies] core_arch = { path = "../crates/core_arch" } std_detect = { path = "../crates/std_detect" } -quickcheck = "0.9" -rand = "0.7" +quickcheck = "1.0" +rand = "0.8" [[bin]] name = "hex"