diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index cd82df386f5ce..73d4adf8e3cf2 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -140,7 +140,6 @@ fn emit_module( bytecode: None, assembly: None, llvm_ir: None, - links_from_incr_cache: Vec::new(), }) } diff --git a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml index 2f5cc409e363d..f37123c124c74 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml @@ -52,7 +52,9 @@ jobs: - name: Install packages # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. - run: sudo apt-get install ninja-build ripgrep llvm-14-tools llvm + run: | + sudo apt-get update + sudo apt-get install ninja-build ripgrep llvm-14-tools llvm - name: Install the libraries needed to build librsvg if: ${{ contains(matrix.commands, '--projects') }} diff --git a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml index 17d6449c85e08..34499c6e7b522 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml @@ -96,14 +96,16 @@ jobs: if: ${{ !matrix.cargo_runner }} run: | # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. - ./y.sh test --release --stdarch-tests -- --skip test_tile_ --skip test__tile + # FIXME: remove --skip test_mm_srav_epi64 when it's fixed upstream. + ./y.sh test --release --stdarch-tests -- --skip test_tile_ --skip test__tile --skip test_mm_srav_epi64 - name: Run stdarch tests if: ${{ matrix.cargo_runner }} run: | # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro. # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. - STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ --skip test__tile + # FIXME: remove --skip test_mm_srav_epi64 when it's fixed upstream. + STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ --skip test__tile --skip test_mm_srav_epi64 # Summary job for the merge queue. # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md index 9a7c624c9bc22..14c0e3ad0f21c 100644 --- a/compiler/rustc_codegen_gcc/Readme.md +++ b/compiler/rustc_codegen_gcc/Readme.md @@ -154,7 +154,7 @@ If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y. You can do the same manually (although we don't recommend it): ```bash -$ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs +$ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain.toml | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs ``` ## Environment variables diff --git a/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs b/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs index a85886d87f365..9fc06dc8dbc04 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/abi_test.rs @@ -34,7 +34,7 @@ pub fn run() -> Result<(), String> { .map_err(|err| format!("Git clone failed with message: {err:?}!"))?; // Configure abi-cafe to use the exact same rustc version we use - this is crucial. // Otherwise, the concept of ABI compatibility becomes meanignless. - std::fs::copy("rust-toolchain", "clones/abi-cafe/rust-toolchain") + std::fs::copy("rust-toolchain.toml", "clones/abi-cafe/rust-toolchain.toml") .expect("Could not copy toolchain configs!"); // Get the backend path. // We will use the *debug* build of the backend - it has more checks enabled. diff --git a/compiler/rustc_codegen_gcc/build_system/src/utils.rs b/compiler/rustc_codegen_gcc/build_system/src/utils.rs index 4c67156a85fb2..dda44e4d16d41 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/utils.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/utils.rs @@ -242,9 +242,9 @@ fn rustc_version_info_inner( } pub fn get_toolchain() -> Result { - let content = match fs::read_to_string("rust-toolchain") { + let content = match fs::read_to_string("rust-toolchain.toml") { Ok(content) => content, - Err(_) => return Err("No `rust-toolchain` file found".to_string()), + Err(_) => return Err("No `rust-toolchain.toml` file found".to_string()), }; match content .split('\n') @@ -259,7 +259,7 @@ pub fn get_toolchain() -> Result { .next() { Some(toolchain) => Ok(toolchain.to_string()), - None => Err("Couldn't find `channel` in `rust-toolchain` file".to_string()), + None => Err("Couldn't find `channel` in `rust-toolchain.toml` file".to_string()), } } diff --git a/compiler/rustc_codegen_gcc/doc/tips.md b/compiler/rustc_codegen_gcc/doc/tips.md index dc40ee4d39952..28964f66403bf 100644 --- a/compiler/rustc_codegen_gcc/doc/tips.md +++ b/compiler/rustc_codegen_gcc/doc/tips.md @@ -41,7 +41,7 @@ COLLECT_NO_DEMANGLE=1 ### How to use a custom-build rustc * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). - * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`. + * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain.toml`. ### How to use a custom sysroot source path diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain.toml similarity index 70% rename from compiler/rustc_codegen_gcc/rust-toolchain rename to compiler/rustc_codegen_gcc/rust-toolchain.toml index 0c81f7c7c7398..a7774784e3afa 100644 --- a/compiler/rustc_codegen_gcc/rust-toolchain +++ b/compiler/rustc_codegen_gcc/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-09-18" +channel = "nightly-2026-09-24" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index cb12c103834af..d52e34d30fb7d 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -463,23 +463,29 @@ fn thin_lto( info!("thin LTO data created"); - let (key_map_path, prev_key_map, curr_key_map) = if let Some(ref incr_comp_session_dir) = - cgcx.incr_comp_session_dir + let new_key_map_path = cgcx + .new_incr_comp_session_dir + .as_ref() + .map(|dir| dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME)); + + let prev_key_map = if let Some(ref old_incr_comp_session_dir) = + cgcx.old_incr_comp_session_dir { - let path = incr_comp_session_dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME); + let old_path = old_incr_comp_session_dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME); + // If the previous file was deleted, or we get an IO error // reading the file, then we'll just use `None` as the // prev_key_map, which will force the code to be recompiled. - let prev = - if path.exists() { ThinLTOKeysMap::load_from_file(&path).ok() } else { None }; - let curr = ThinLTOKeysMap::from_thin_lto_modules(&data, &thin_modules, &module_names); - (Some(path), prev, curr) + if old_path.exists() { ThinLTOKeysMap::load_from_file(&old_path).ok() } else { None } + } else { + assert!(green_modules.is_empty()); + None + }; + let curr_key_map = if cgcx.new_incr_comp_session_dir.is_some() { + ThinLTOKeysMap::from_thin_lto_modules(&data, &thin_modules, &module_names) } else { - // If we don't compile incrementally, we don't need to load the - // import data from LLVM. assert!(green_modules.is_empty()); - let curr = ThinLTOKeysMap::default(); - (None, None, curr) + ThinLTOKeysMap::default() }; info!("thin LTO cache key map loaded"); info!("prev_key_map: {:#?}", prev_key_map); @@ -500,7 +506,8 @@ fn thin_lto( if let (Some(prev_key_map), true) = (prev_key_map.as_ref(), green_modules.contains_key(module_name)) { - assert!(cgcx.incr_comp_session_dir.is_some()); + assert!(cgcx.old_incr_comp_session_dir.is_some()); + assert!(cgcx.new_incr_comp_session_dir.is_some()); // If a module exists in both the current and the previous session, // and has the same LTO cache key in both sessions, then we can re-use it @@ -508,7 +515,6 @@ fn thin_lto( let work_product = green_modules[module_name].clone(); copy_jobs.push(work_product); info!(" - {}: re-used", module_name); - assert!(cgcx.incr_comp_session_dir.is_some()); continue; } } @@ -518,8 +524,8 @@ fn thin_lto( } // Save the current ThinLTO import information for the next compilation - // session, overwriting the previous serialized data (if any). - if let Some(path) = key_map_path + // session. + if let Some(path) = new_key_map_path && let Err(err) = curr_key_map.save_to_file(&path) { write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err }); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index f16eb78b36e35..147e4c43c7103 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -15,7 +15,9 @@ use rustc_errors::{ Level, MultiSpan, Style, Sublevel, Suggestions, catch_fatal_errors, }; use rustc_fs_util::link_or_copy; -use rustc_incremental::{copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir_sess}; +use rustc_incremental::{ + copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir_sess, in_old_incr_comp_dir_sess, +}; use rustc_macros::{Decodable, Encodable}; use rustc_metadata::fs::copy_to_stdout; use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; @@ -351,9 +353,12 @@ pub struct CodegenContext { /// Directory into which should the LLVM optimization remarks be written. /// If `None`, they will be written to stderr. pub remark_dir: Option, + /// The previous incremental compilation session directory, or None if we + /// are not compiling incrementally or there is no previous session. + pub old_incr_comp_session_dir: Option, /// The incremental compilation session directory, or None if we are not /// compiling incrementally - pub incr_comp_session_dir: Option, + pub new_incr_comp_session_dir: Option, /// `Some(limit)` if the codegen should be run in parallel. /// /// Depends on [`WriteBackendMethods::supports_parallel()`] and `--jobs-backend`. @@ -497,7 +502,6 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( incr_comp_session.unwrap(), &module.name, files.as_slice(), - &module.links_from_incr_cache, ); work_products.insert(id, product); } @@ -839,7 +843,7 @@ fn execute_optimize_work_item( // save our module to disk first. let bitcode = if cgcx.module_config.emit_pre_lto_bc { let filename = pre_lto_bitcode_filename(&module.name); - cgcx.incr_comp_session_dir.as_ref().map(|path| path.join(&filename)) + cgcx.new_incr_comp_session_dir.as_ref().map(|path| path.join(&filename)) } else { None }; @@ -886,11 +890,9 @@ fn execute_copy_from_cache_work_item( let dcx = DiagCtxt::new(Box::new(shared_emitter)); let dcx = dcx.handle(); - let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); - - let mut links_from_incr_cache = Vec::new(); + let incr_comp_session_dir = cgcx.old_incr_comp_session_dir.as_ref().unwrap(); - let mut load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { + let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { let source_file_in_incr_comp_dir = incr_comp_session_dir.join(saved_path); debug!( "copying preexisting module `{}` from {:?} to {}", @@ -899,10 +901,7 @@ fn execute_copy_from_cache_work_item( output_path.display() ); match link_or_copy(&source_file_in_incr_comp_dir, &output_path) { - Ok(_) => { - links_from_incr_cache.push(source_file_in_incr_comp_dir); - Some(output_path) - } + Ok(_) => Some(output_path), Err(error) => { dcx.emit_err(diagnostics::CopyPathBuf { source_file: source_file_in_incr_comp_dir, @@ -925,7 +924,7 @@ fn execute_copy_from_cache_work_item( load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file) }); - let mut load_from_incr_cache = |perform, output_type: OutputType| { + let load_from_incr_cache = |perform, output_type: OutputType| { if perform { let saved_file = module.source.saved_files.get(output_type.extension())?; let output_path = cgcx.output_filenames.temp_path_for_cgu(output_type, &module.name); @@ -953,7 +952,6 @@ fn execute_copy_from_cache_work_item( } CompiledModule { - links_from_incr_cache, kind: ModuleKind::Regular, name: module.name, object, @@ -1293,10 +1291,15 @@ fn start_executing_work( time_trace: sess.opts.unstable_opts.llvm_time_trace, remark: sess.opts.cg.remark.clone(), remark_dir, - incr_comp_session_dir: tcx + old_incr_comp_session_dir: tcx + .incr_comp_session + .as_ref() + .and_then(|incr_comp_session| incr_comp_session.old_session_directory.as_deref()) + .map(ToOwned::to_owned), + new_incr_comp_session_dir: tcx .incr_comp_session .as_ref() - .map(|incr_comp_session| (&*incr_comp_session.session_directory).to_owned()), + .map(|incr_comp_session| (&*incr_comp_session.new_session_directory).to_owned()), output_filenames: Arc::clone(tcx.output_filenames(())), module_config: regular_config, opt_level, @@ -2260,7 +2263,22 @@ pub(crate) fn submit_pre_lto_module_to_llvm( module: CachedModuleCodegen, ) { let filename = pre_lto_bitcode_filename(&module.name); + let old_bitcode_path = + in_old_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename).unwrap(); let bitcode_path = in_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename); + + match link_or_copy(&old_bitcode_path, &bitcode_path) { + Ok(_) => {} + Err(error) => { + tcx.sess.dcx().emit_err(diagnostics::CopyPathBuf { + source_file: old_bitcode_path, + output_path: bitcode_path, + error, + }); + return; + } + } + // Schedule the module to be loaded drop( coordinator diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index e054394ccade0..8743d703940ec 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -878,6 +878,10 @@ pub fn codegen_crate< source: cgu.previous_work_product(tcx), }, ); + // This will unwind if there are errors, which triggers our `AbortCodegenOnDrop` + // guard. Unfortunately, just skipping the `submit_pre_lto_module_to_llvm` makes + // compilation hang on post-monomorphization errors. + tcx.dcx().abort_if_errors(); } CguReuse::PostLto => { submit_post_lto_module_to_llvm( diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 7a29ca383b24b..4237898c52a6d 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -114,7 +114,6 @@ impl ModuleCodegen { bytecode, assembly, llvm_ir, - links_from_incr_cache: Vec::new(), } } } @@ -129,7 +128,6 @@ pub struct CompiledModule { pub bytecode: Option, pub assembly: Option, // --emit=asm pub llvm_ir: Option, // --emit=llvm-ir, llvm-bc is in bytecode - pub links_from_incr_cache: Vec, } impl CompiledModule { diff --git a/compiler/rustc_incremental/src/diagnostics.rs b/compiler/rustc_incremental/src/diagnostics.rs index 6e291b7ea3abb..b9ac4662dcbdc 100644 --- a/compiler/rustc_incremental/src/diagnostics.rs +++ b/compiler/rustc_incremental/src/diagnostics.rs @@ -169,21 +169,6 @@ pub(crate) struct DeleteLock<'a> { pub err: std::io::Error, } -#[derive(Diagnostic)] -#[diag( - "hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`" -)] -pub(crate) struct HardLinkFailed<'a> { - pub path: &'a Path, -} - -#[derive(Diagnostic)] -#[diag("failed to delete partly initialized session dir `{$path}`: {$err}")] -pub(crate) struct DeletePartial<'a> { - pub path: &'a Path, - pub err: std::io::Error, -} - #[derive(Diagnostic)] #[diag("did not finalize incremental compilation session directory `{$path}`: {$err}")] #[help("the next build will not be able to reuse work from this compilation")] @@ -266,13 +251,6 @@ pub(crate) struct CopyWorkProductToCache<'a> { pub err: std::io::Error, } -#[derive(Diagnostic)] -#[diag("file-system error deleting outdated file `{$path}`: {$err}")] -pub(crate) struct DeleteWorkProduct<'a> { - pub path: &'a Path, - pub err: std::io::Error, -} - #[derive(Diagnostic)] #[diag( "corrupt incremental compilation artifact found at `{$path}`. This file will automatically be ignored and deleted. If you see this message repeatedly or can provoke it without manually manipulating the compiler's artifacts, please file an issue. The incremental compilation system relies on hardlinks and filesystem locks behaving correctly, and may not deal well with OS crashes, so whatever information you can provide about your filesystem or other state may be very relevant" diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 83646cb086d8d..b5470d224ffbd 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -3,6 +3,7 @@ // tidy-alphabetical-start #![deny(missing_docs)] #![feature(file_buffered)] +#![feature(try_blocks)] // tidy-alphabetical-end mod assert_dep_graph; @@ -11,7 +12,7 @@ mod persist; pub use persist::{ copy_cgu_workproduct_to_incr_comp_cache_dir, finalize_session_directory, in_incr_comp_dir_sess, - load_query_result_cache, save_work_product_index, setup_dep_graph, + in_old_incr_comp_dir_sess, load_query_result_cache, save_work_product_index, setup_dep_graph, }; use rustc_middle::util::Providers; diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 374e0b0dd6d1a..3f896584eaef2 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -1,14 +1,14 @@ //! This module manages how the incremental compilation cache is represented in //! the file system. //! -//! Incremental compilation caches are managed according to a copy-on-write -//! strategy: Once a complete, consistent cache version is finalized, it is -//! never modified. Instead, when a subsequent compilation session is started, -//! the compiler will allocate a new version of the cache that starts out as -//! a copy of the previous version. Then only this new copy is modified and it -//! will not be visible to other processes until it is finalized. This ensures -//! that multiple compiler processes can be executed concurrently for the same -//! crate without interfering with each other or blocking each other. +//! Incremental compilation caches are managed according to a rebuild from +//! scratch strategy: Once a complete, consistent cache version is finalized, it +//! is never modified. Instead, when a subsequent compilation session is started, +//! the compiler will allocate a new version of the cache that starts out empty. +//! Then only this new directory is written to and it will not be visible to +//! other processes until it is finalized. This ensures that multiple compiler +//! processes can be executed concurrently for the same crate without +//! interfering with each other or blocking each other. //! //! More concretely this is implemented via the following protocol: //! @@ -22,12 +22,12 @@ //! considered finalized if the "-working" suffix in the directory name has //! been replaced by the SVH of the crate. //! 3. Once the compiler has found a valid, finalized session directory, it will -//! hard-link/copy its contents into the new "-working" directory. If all -//! goes well, it will have its own, private copy of the source directory and -//! subsequently not have to worry about synchronizing with other compiler -//! processes. +//! obtain a shared lock on the directory. If this succeeds, it will have +//! read-only access to the old session directory without having to worry +//! about synchronizing with other compiler processes. //! 4. Now the compiler can do its normal compilation process, which involves -//! reading and updating its private session directory. +//! writing to its private session directory. Possibly by hardlinking +//! existing files from the old session directory if they haven't changed. //! 5. When compilation finishes without errors, the private session directory //! will be in a state where it can be used as input for other compilation //! sessions. That is, it will contain a dependency graph and cache artifacts @@ -71,23 +71,15 @@ //! //! Another case that has to be considered is what happens if one process //! deletes a finalized session directory that another process is currently -//! trying to copy from. This case is also handled via the lock file. Before -//! a process starts copying a finalized session directory, it will acquire a -//! shared lock on the directory's lock file. Any garbage collecting process, -//! on the other hand, will acquire an exclusive lock on the lock file. -//! Thus, if a directory is being collected, any reader process will fail -//! acquiring the shared lock and will leave the directory alone. Conversely, -//! if a collecting process can't acquire the exclusive lock because the -//! directory is currently being read from, it will leave collecting that -//! directory to another process at a later point in time. -//! The exact same scheme is also used when reading the metadata hashes file -//! from an extern crate. When a crate is compiled, the hash values of its -//! metadata are stored in a file in its session directory. When the -//! compilation session of another crate imports the first crate's metadata, -//! it also has to read in the accompanying metadata hashes. It thus will access -//! the finalized session directory of all crates it links to and while doing -//! so, it will also place a read lock on that the respective session directory -//! so that it won't be deleted while the metadata hashes are loaded. +//! reading from. This case is also handled via the lock file. Before a process +//! starts reading from a finalized session directory, it will acquire a shared +//! lock on the directory's lock file. Any garbage collecting process, on the +//! other hand, will acquire an exclusive lock on the lock file. Thus, if a +//! directory is being collected, any reader process will fail acquiring the +//! shared lock and will leave the directory alone. Conversely, if a collecting +//! process can't acquire the exclusive lock because the directory is currently +//! being read from, it will leave collecting that directory to another process +//! at a later point in time. //! //! ## Preconditions //! @@ -110,11 +102,11 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; use rand::{RngCore, rng}; use rustc_data_structures::base_n::{BaseNString, CASE_INSENSITIVE, ToBaseN}; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::svh::Svh; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_data_structures::{base_n, flock}; -use rustc_fs_util::{LinkOrCopy, link_or_copy, try_canonicalize}; +use rustc_fs_util::try_canonicalize; use rustc_middle::dep_graph::WorkProduct; use rustc_session::config::OutputType; use rustc_session::{IncrCompSession, Session, StableCrateId}; @@ -138,6 +130,11 @@ const QUERY_CACHE_FILENAME: &str = "query-cache.bin"; // case-sensitive (as opposed to base64, for example). const INT_ENCODE_BASE: usize = base_n::CASE_INSENSITIVE; +/// Returns the path to a previous session's dependency graph. +pub(crate) fn old_dep_graph_path(incr_comp_session: &IncrCompSession) -> Option { + in_old_incr_comp_dir_sess(incr_comp_session, DEP_GRAPH_FILENAME) +} + /// Returns the path to a session's dependency graph. pub(crate) fn dep_graph_path(incr_comp_session: &IncrCompSession) -> PathBuf { in_incr_comp_dir_sess(incr_comp_session, DEP_GRAPH_FILENAME) @@ -151,10 +148,19 @@ pub(crate) fn staging_dep_graph_path(incr_comp_session: &IncrCompSession) -> Pat in_incr_comp_dir_sess(incr_comp_session, STAGING_DEP_GRAPH_FILENAME) } +pub(crate) fn old_work_products_path(incr_comp_session: &IncrCompSession) -> Option { + in_old_incr_comp_dir_sess(incr_comp_session, WORK_PRODUCTS_FILENAME) +} + pub(crate) fn work_products_path(incr_comp_session: &IncrCompSession) -> PathBuf { in_incr_comp_dir_sess(incr_comp_session, WORK_PRODUCTS_FILENAME) } +/// Returns the path to a previous session's query cache. +pub(crate) fn old_query_cache_path(incr_comp_session: &IncrCompSession) -> Option { + in_old_incr_comp_dir_sess(incr_comp_session, QUERY_CACHE_FILENAME) +} + /// Returns the path to a session's query cache. pub(crate) fn query_cache_path(incr_comp_session: &IncrCompSession) -> PathBuf { in_incr_comp_dir_sess(incr_comp_session, QUERY_CACHE_FILENAME) @@ -182,10 +188,19 @@ fn lock_file_path(session_dir: &Path) -> PathBuf { crate_dir.join(&directory_name[0..dash_indices[2]]).with_extension(&LOCK_FILE_EXT[1..]) } +/// Returns the path for a given filename within the incremental compilation directory +/// in the previous session. +pub fn in_old_incr_comp_dir_sess( + incr_comp_session: &IncrCompSession, + file_name: &str, +) -> Option { + incr_comp_session.old_session_directory.as_ref().map(|dir| dir.join(file_name)) +} + /// Returns the path for a given filename within the incremental compilation directory /// in the current session. pub fn in_incr_comp_dir_sess(incr_comp_session: &IncrCompSession, file_name: &str) -> PathBuf { - incr_comp_session.session_directory.join(file_name) + incr_comp_session.new_session_directory.join(file_name) } /// Allocates the private session directory. @@ -230,62 +245,30 @@ pub(crate) fn prepare_session_directory( } }; - let mut source_directories_already_tried = FxHashSet::default(); - - loop { - // Generate a session directory of the form: - // - // {incr-comp-dir}/{crate-name-and-disambiguator}/s-{timestamp}-{random}-working - let session_directory = generate_session_dir_path(&crate_dir); - debug!("session-dir: {}", session_directory.display()); - - // Lock the new session directory. If this fails, return an - // error without retrying - let (session_directory, lock_file_path) = - lock_and_create_directory(sess, &session_directory); - - // Find a suitable source directory to copy from. Ignore those that we - // have already tried before. - let source_directory = find_source_directory(&crate_dir, &source_directories_already_tried); - - let Some(source_directory) = source_directory else { - // There's nowhere to copy from, we're done - debug!( - "no source directory found. Continuing with empty session \ - directory." - ); - - return IncrCompSession { session_directory }; - }; - - debug!("attempting to copy data from source: {}", source_directory.display()); - - // Try copying over all files from the source directory - if let Ok(allows_links) = copy_files(sess, &session_directory, &source_directory) { - debug!("successfully copied data from: {}", source_directory.display()); + // Generate a session directory of the form: + // + // {incr-comp-dir}/{crate-name-and-disambiguator}/s-{timestamp}-{random}-working + let new_session_dir = generate_session_dir_path(&crate_dir); + debug!("session-dir: {}", new_session_dir.display()); - if !allows_links { - sess.dcx().emit_warn(diagnostics::HardLinkFailed { path: &session_directory }); - } - - return IncrCompSession { session_directory }; - } else { - debug!("copying failed - trying next directory"); + // Lock the new session directory. If this fails, return an + // error without retrying + let new_session_directory = lock_directory(sess, &new_session_dir, true /* new_session */) + .expect("should emit fatal error on lock fail"); - // Something went wrong while trying to copy/link files from the - // source directory. Try again with a different one. - source_directories_already_tried.insert(source_directory); + // Find a suitable source directory to copy from. Ignore those that we + // have already tried before. + let old_source_directory = find_source_directory(sess, &crate_dir); - // Try to remove the session directory we just allocated. We don't - // know if there's any garbage in it from the failed copy action. - if let Err(err) = std_fs::remove_dir_all(&*session_directory) { - sess.dcx().emit_warn(diagnostics::DeletePartial { path: &session_directory, err }); - } + let old_session_directory = if let Some(old_source_directory) = old_source_directory { + debug!("attempting to use: {}", old_source_directory.display()); + Some(old_source_directory) + } else { + debug!("no source directory found. Continuing with empty session directory."); + None + }; - delete_session_dir_lock_file(sess, &lock_file_path); - drop(session_directory); - } - } + IncrCompSession { old_session_directory, new_session_directory } } /// This function finalizes and thus 'publishes' the session directory by @@ -301,13 +284,13 @@ pub fn finalize_session_directory( if sess.opts.incremental.is_none() { return; } - let incr_comp_session = incr_comp_session.unwrap(); + let mut incr_comp_session = incr_comp_session.unwrap(); // The svh is always produced when incr. comp. is enabled. let svh = svh.unwrap(); let _timer = sess.timer("incr_comp_finalize_session_directory"); - let incr_comp_session_dir = &*incr_comp_session.session_directory; + let incr_comp_session_dir = &*incr_comp_session.new_session_directory; debug!("finalize_session_directory() - session directory: {}", incr_comp_session_dir.display()); @@ -367,77 +350,28 @@ pub fn finalize_session_directory( } } - let _ = garbage_collect_session_directories( - sess, - &incr_comp_session, - false, // keep_most_recent - ); -} + // Unlock the old session directory now that we will no longer read from it. + incr_comp_session.old_session_directory = None; -pub(crate) fn delete_all_session_dir_contents( - incr_comp_session: &IncrCompSession, -) -> io::Result<()> { - let sess_dir_iterator = incr_comp_session.session_directory.read_dir()?; - for entry in sess_dir_iterator { - let entry = entry?; - safe_remove_file(&entry.path())? - } - Ok(()) + let _ = garbage_collect_session_directories(sess, &incr_comp_session); } -fn copy_files(sess: &Session, target_dir: &Path, source_dir: &Path) -> Result { - // We acquire a shared lock on the lock file of the directory, so that - // nobody deletes it out from under us while we are reading from it. - let lock_file_path = lock_file_path(source_dir); - - // not exclusive - let Ok(_lock) = flock::Lock::try_lock( - &lock_file_path, - false, // don't create - false, - ) else { - // Could not acquire the lock, don't try to copy from here - return Err(()); - }; - - let Ok(source_dir_iterator) = source_dir.read_dir() else { - return Err(()); - }; - - let mut files_linked = 0; - let mut files_copied = 0; - - for entry in source_dir_iterator { - match entry { - Ok(entry) => { - let file_name = entry.file_name(); - - let target_file_path = target_dir.join(file_name); - let source_path = entry.path(); - - debug!("copying into session dir: {}", source_path.display()); - match link_or_copy(source_path, target_file_path) { - Ok(LinkOrCopy::Link) => files_linked += 1, - Ok(LinkOrCopy::Copy) => files_copied += 1, - Err(_) => return Err(()), - } +pub(crate) fn invalidate_old_session_dir(sess: &Session, incr_comp_session: &mut IncrCompSession) { + if let Some(old_incr_comp_session_dir) = incr_comp_session.old_session_directory.take() { + let res = try { + let sess_dir_iterator = old_incr_comp_session_dir.read_dir()?; + for entry in sess_dir_iterator { + let entry = entry?; + safe_remove_file(&entry.path())? } - Err(_) => return Err(()), + }; + if let Err(err) = res { + sess.dcx().emit_err(diagnostics::DeleteIncompatible { + path: (*old_incr_comp_session_dir).to_owned(), + err, + }); } } - - if sess.opts.unstable_opts.incremental_info { - eprintln!( - "[incremental] session directory: \ - {files_linked} files hard-linked" - ); - eprintln!( - "[incremental] session directory: \ - {files_copied} files copied" - ); - } - - Ok(files_linked > 0 || files_copied == 0) } /// Generates unique directory path of the form: @@ -470,33 +404,44 @@ fn create_dir(sess: &Session, path: &Path, dir_tag: &str) { } } -/// Allocate the lock-file, lock it and create the session directory. -fn lock_and_create_directory(sess: &Session, session_dir: &Path) -> (flock::LockedDir, PathBuf) { +/// Allocate the lock-file, lock it and create the session directory if requested. +fn lock_directory( + sess: &Session, + session_dir: &Path, + new_session: bool, +) -> Option { let lock_file_path = lock_file_path(session_dir); debug!("lock_directory() - lock_file: {}", lock_file_path.display()); match flock::LockedDir::try_lock( session_dir.to_owned(), &lock_file_path, - true, // create the lock file - true, + new_session, // create + new_session, // exclusive ) { - // the lock should be exclusive Ok(lock) => { // Now that we have the lock, we can actually create the session // directory - create_dir(sess, &session_dir, "session"); + if new_session { + create_dir(sess, &session_dir, "session"); + } - (lock, lock_file_path) + Some(lock) } Err(lock_err) => { let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err); - sess.dcx().emit_fatal(diagnostics::CreateLock { + let diag = diagnostics::CreateLock { lock_err, session_dir, is_unsupported_lock, is_cargo: rustc_session::utils::was_invoked_from_cargo(), - }); + }; + if new_session { + sess.dcx().emit_fatal(diag); + } else { + sess.dcx().emit_warn(diag); + None + } } } } @@ -507,24 +452,18 @@ fn delete_session_dir_lock_file(sess: &Session, lock_file_path: &Path) { } } -/// Finds the most recent published session directory that is not in the -/// ignore-list. -fn find_source_directory( - crate_dir: &Path, - source_directories_already_tried: &FxHashSet, -) -> Option { +/// Finds the most recent published session directory. +fn find_source_directory(sess: &Session, crate_dir: &Path) -> Option { let iter = crate_dir .read_dir() .unwrap() // FIXME .filter_map(|e| e.ok().map(|e| e.path())); - find_source_directory_in_iter(iter, source_directories_already_tried) + find_source_directory_in_iter(iter) + .and_then(|session_dir| lock_directory(sess, &session_dir, false /* new_session */)) } -fn find_source_directory_in_iter( - iter: I, - source_directories_already_tried: &FxHashSet, -) -> Option +fn find_source_directory_in_iter(iter: I) -> Option where I: Iterator, { @@ -538,10 +477,7 @@ where continue; }; - if source_directories_already_tried.contains(&session_dir) - || !is_session_directory(&directory_name) - || !is_finalized(&directory_name) - { + if !is_session_directory(&directory_name) || !is_finalized(&directory_name) { debug!("find_source_directory_in_iter - ignoring"); continue; } @@ -619,11 +555,10 @@ fn is_old_enough_to_be_collected(timestamp: SystemTime) -> bool { pub(crate) fn garbage_collect_session_directories( sess: &Session, incr_comp_session: &IncrCompSession, - keep_most_recent: bool, ) -> io::Result<()> { debug!("garbage_collect_session_directories() - begin"); - let session_directory = &*incr_comp_session.session_directory; + let session_directory = &*incr_comp_session.new_session_directory; debug!( "garbage_collect_session_directories() - session directory: {}", @@ -760,10 +695,7 @@ pub(crate) fn garbage_collect_session_directories( ); // Note that we are holding on to the lock - return Some(( - (timestamp, crate_directory.join(directory_name)), - Some(lock), - )); + return Some((crate_directory.join(directory_name), lock)); } Err(_) => { debug!( @@ -818,25 +750,22 @@ pub(crate) fn garbage_collect_session_directories( } None }); - let deletion_candidates = deletion_candidates.into(); // Delete all but the most recent of the candidates - all_except_maybe_most_recent(deletion_candidates, keep_most_recent).into_items().all( - |(path, lock)| { - debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); + deletion_candidates.all(|(path, lock)| { + debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); - if let Err(err) = std_fs::remove_dir_all(&path) { - sess.dcx().emit_warn(diagnostics::FinalizedGcFailed { path: &path, err }); - } else { - delete_session_dir_lock_file(sess, &lock_file_path(&path)); - } + if let Err(err) = std_fs::remove_dir_all(&path) { + sess.dcx().emit_warn(diagnostics::FinalizedGcFailed { path: &path, err }); + } else { + delete_session_dir_lock_file(sess, &lock_file_path(&path)); + } - // Let's make it explicit that the file lock is released at this point, - // or rather, that we held on to it until here - drop(lock); - true - }, - ); + // Let's make it explicit that the file lock is released at this point, + // or rather, that we held on to it until here + drop(lock); + true + }); Ok(()) } @@ -851,21 +780,6 @@ fn delete_old(sess: &Session, path: &Path) { } } -fn all_except_maybe_most_recent( - deletion_candidates: UnordMap<(SystemTime, PathBuf), Option>, - keep_most_recent: bool, -) -> UnordMap> { - let most_recent = keep_most_recent - .then(|| deletion_candidates.items().map(|(&(timestamp, _), _)| timestamp).max()) - .flatten(); - - deletion_candidates - .into_items() - .filter(|&((timestamp, _), _)| Some(timestamp) != most_recent) - .map(|((_, path), lock)| (path, lock)) - .collect() -} - fn safe_remove_file(p: &Path) -> io::Result<()> { match std_fs::remove_file(p) { Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(()), diff --git a/compiler/rustc_incremental/src/persist/fs/tests.rs b/compiler/rustc_incremental/src/persist/fs/tests.rs index 75b573dd4944a..112afd8c7bd1d 100644 --- a/compiler/rustc_incremental/src/persist/fs/tests.rs +++ b/compiler/rustc_incremental/src/persist/fs/tests.rs @@ -1,25 +1,5 @@ use super::*; -#[test] -fn test_all_except_most_recent() { - let input: UnordMap<_, Option> = UnordMap::from_iter([ - ((UNIX_EPOCH + Duration::new(4, 0), PathBuf::from("4")), None), - ((UNIX_EPOCH + Duration::new(1, 0), PathBuf::from("1")), None), - ((UNIX_EPOCH + Duration::new(5, 0), PathBuf::from("5")), None), - ((UNIX_EPOCH + Duration::new(3, 0), PathBuf::from("3")), None), - ((UNIX_EPOCH + Duration::new(2, 0), PathBuf::from("2")), None), - ]); - assert_eq!( - all_except_maybe_most_recent(input, true) - .into_items() - .map(|(path, _)| path) - .into_sorted_stable_ord(), - vec![PathBuf::from("1"), PathBuf::from("2"), PathBuf::from("3"), PathBuf::from("4")] - ); - - assert!(all_except_maybe_most_recent(UnordMap::default(), true).is_empty()); -} - #[test] fn test_timestamp_serialization() { for i in 0..1_000u64 { @@ -31,8 +11,6 @@ fn test_timestamp_serialization() { #[test] fn test_find_source_directory_in_iter() { - let already_visited = FxHashSet::default(); - // Find newest assert_eq!( find_source_directory_in_iter( @@ -42,7 +20,6 @@ fn test_find_source_directory_in_iter() { PathBuf::from("crate-dir/s-1234-0000-svh") ] .into_iter(), - &already_visited ), Some(PathBuf::from("crate-dir/s-3234-0000-svh")) ); @@ -56,13 +33,12 @@ fn test_find_source_directory_in_iter() { PathBuf::from("crate-dir/s-1234-0000-svh") ] .into_iter(), - &already_visited ), Some(PathBuf::from("crate-dir/s-2234-0000-svh")) ); // Handle empty - assert_eq!(find_source_directory_in_iter([].into_iter(), &already_visited), None); + assert_eq!(find_source_directory_in_iter([].into_iter()), None); // Handle only working assert_eq!( @@ -73,7 +49,6 @@ fn test_find_source_directory_in_iter() { PathBuf::from("crate-dir/s-1234-0000-working") ] .into_iter(), - &already_visited ), None ); diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index fb83149e65b22..76e0bf92c6f0f 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -16,8 +16,8 @@ use rustc_span::Symbol; use tracing::{debug, warn}; use super::data::*; +use super::file_format; use super::fs::*; -use super::{file_format, work_product}; use crate::diagnostics; use crate::persist::file_format::{OpenFile, OpenFileError}; @@ -32,15 +32,6 @@ enum LoadResult { IoError { path: PathBuf, err: io::Error }, } -fn delete_dirty_work_product( - sess: &Session, - incr_comp_session: &IncrCompSession, - swp: SerializedWorkProduct, -) { - debug!("delete_dirty_work_product({:?})", swp); - work_product::delete_workproduct_files(sess, incr_comp_session, &swp.work_product); -} - fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadResult { assert!(sess.opts.incremental.is_some()); @@ -48,12 +39,16 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`. // Fortunately, we just checked that this isn't the case. - let path = dep_graph_path(incr_comp_session); + let Some(path) = old_dep_graph_path(incr_comp_session) else { + return LoadResult::DataOutOfDate; + }; let expected_hash = sess.opts.dep_tracking_hash(false); let mut prev_work_products = UnordMap::default(); - let work_products_path = work_products_path(incr_comp_session); + let Some(work_products_path) = old_work_products_path(incr_comp_session) else { + return LoadResult::DataOutOfDate; + }; if let Ok(OpenFile { mmap, start_pos }) = file_format::open_incremental_file(sess, &work_products_path) @@ -68,7 +63,7 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe for swp in work_products { let all_files_exist = swp.work_product.saved_files.items().all(|(_, path)| { - let exists = in_incr_comp_dir_sess(incr_comp_session, path).exists(); + let exists = in_old_incr_comp_dir_sess(incr_comp_session, path).unwrap().exists(); if !exists && sess.opts.unstable_opts.incremental_info { eprintln!("incremental: could not find file for work product: {path}",); } @@ -80,7 +75,7 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe prev_work_products.insert(swp.id, swp.work_product); } else { debug!("reconcile_work_products: some file for {:?} does not exist", swp); - delete_dirty_work_product(sess, incr_comp_session, swp); + return LoadResult::DataOutOfDate; } } } @@ -134,7 +129,9 @@ pub fn load_query_result_cache( let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache"); - let path = query_cache_path(incr_comp_session); + let Some(path) = old_query_cache_path(incr_comp_session) else { + return Some(OnDiskCache::new_empty()); + }; match file_format::open_incremental_file(sess, &path) { Ok(OpenFile { mmap, start_pos }) => { let cache = OnDiskCache::new(sess, mmap, start_pos).unwrap_or_else(|()| { @@ -190,16 +187,12 @@ pub fn setup_dep_graph( } // `load_dep_graph` can only be called after `prepare_session_directory`. - let incr_comp_session = prepare_session_directory(sess, crate_name, stable_crate_id); + let mut incr_comp_session = prepare_session_directory(sess, crate_name, stable_crate_id); // Try to load the previous session's dep graph and work products. let load_result = load_dep_graph(sess, &incr_comp_session); sess.time("incr_comp_garbage_collect_session_directories", || { - if let Err(e) = garbage_collect_session_directories( - sess, - &incr_comp_session, - true, // keep_most_recent - ) { + if let Err(e) = garbage_collect_session_directories(sess, &incr_comp_session) { warn!( "Error while trying to garbage collect incremental compilation \ cache directory: {e}", @@ -213,15 +206,11 @@ pub fn setup_dep_graph( let (prev_graph, prev_work_products) = match load_result { LoadResult::IoError { path, err } => { sess.dcx().emit_warn(diagnostics::LoadDepGraph { path, err }); + invalidate_old_session_dir(sess, &mut incr_comp_session); Default::default() } LoadResult::DataOutOfDate => { - if let Err(err) = delete_all_session_dir_contents(&incr_comp_session) { - sess.dcx().emit_err(diagnostics::DeleteIncompatible { - path: dep_graph_path(&incr_comp_session), - err, - }); - } + invalidate_old_session_dir(sess, &mut incr_comp_session); Default::default() } LoadResult::Ok { prev_graph, prev_work_products } => (prev_graph, prev_work_products), diff --git a/compiler/rustc_incremental/src/persist/mod.rs b/compiler/rustc_incremental/src/persist/mod.rs index 7d486cc394b80..fb318357b26cb 100644 --- a/compiler/rustc_incremental/src/persist/mod.rs +++ b/compiler/rustc_incremental/src/persist/mod.rs @@ -10,7 +10,7 @@ mod load; mod save; mod work_product; -pub use fs::{finalize_session_directory, in_incr_comp_dir_sess}; +pub use fs::{finalize_session_directory, in_incr_comp_dir_sess, in_old_incr_comp_dir_sess}; pub use load::{load_query_result_cache, setup_dep_graph}; pub(crate) use save::save_dep_graph; pub use save::save_work_product_index; diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 12f674fe2a859..46f47d6c8623c 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -11,7 +11,7 @@ use tracing::debug; use super::data::*; use super::fs::*; -use super::{clean, file_format, work_product}; +use super::{clean, file_format}; use crate::assert_dep_graph::assert_dep_graph; use crate::diagnostics; @@ -112,23 +112,6 @@ pub fn save_work_product_index( e.finish() }); - // We also need to clean out old work-products, as not all of them are - // deleted during invalidation. Some object files don't change their - // content, they are just not needed anymore. - let previous_work_products = dep_graph.previous_work_products(); - for (id, wp) in previous_work_products.to_sorted_stable_ord() { - if !new_work_products.contains_key(id) { - work_product::delete_workproduct_files(sess, incr_comp_session.unwrap(), wp); - debug_assert!( - !wp.saved_files.items().all(|(_, path)| in_incr_comp_dir_sess( - incr_comp_session.unwrap(), - path - ) - .exists()) - ); - } - } - // Check that we did not delete one of the current work-products: debug_assert!({ new_work_products.items().all(|(_, wp)| { diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 7bb66fee4d1a3..0aaa9aa8e96c2 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -1,9 +1,8 @@ -//! Functions for saving and removing intermediate [work products]. +//! Function for saving intermediate [work products]. //! //! [work products]: WorkProduct -use std::fs as std_fs; -use std::path::{Path, PathBuf}; +use std::path::Path; use rustc_data_structures::unord::UnordMap; use rustc_fs_util::link_or_copy; @@ -23,7 +22,6 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( incr_comp_session: &IncrCompSession, cgu_name: &str, files: &[(&'static str, &Path)], - known_links: &[PathBuf], ) -> (WorkProductId, WorkProduct) { debug!(?cgu_name, ?files); assert!(sess.opts.incremental.is_some()); @@ -32,10 +30,6 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( for (ext, path) in files { let file_name = format!("{cgu_name}.{ext}"); let path_in_incr_dir = in_incr_comp_dir_sess(incr_comp_session, &file_name); - if known_links.contains(&path_in_incr_dir) { - let _ = saved_files.insert(ext.to_string(), file_name); - continue; - } match link_or_copy(path, &path_in_incr_dir) { Ok(_) => { let _ = saved_files.insert(ext.to_string(), file_name); @@ -55,17 +49,3 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( let work_product_id = WorkProductId::from_cgu_name(cgu_name); (work_product_id, work_product) } - -/// Removes files for a given work product. -pub(crate) fn delete_workproduct_files( - sess: &Session, - incr_comp_session: &IncrCompSession, - work_product: &WorkProduct, -) { - for (_, path) in work_product.saved_files.items().into_sorted_stable_ord() { - let path = in_incr_comp_dir_sess(incr_comp_session, path); - if let Err(err) = std_fs::remove_file(&path) { - sess.dcx().emit_warn(diagnostics::DeleteWorkProduct { path: &path, err }); - } - } -} diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 2f196c5e5d609..759297bc69592 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -101,7 +101,6 @@ impl Linker { incr_comp_session.as_ref().unwrap(), WorkProduct::METADATA_WORKPRODUCT_CGU_NAME, &[(OutputType::Metadata.extension(), path)], - &[], ); work_products.insert(id, product); } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 1031af39f272b..629efc498863b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2501,14 +2501,15 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { // If the metadata dep-node is green, try to reuse the saved work product. if tcx.dep_graph.is_fully_enabled() + && let incr_comp_session = tcx.incr_comp_session.unwrap() + && let Some(old_incr_comp_session_dir) = &incr_comp_session.old_session_directory && let work_product_id = WorkProductId::from_cgu_name(WorkProduct::METADATA_WORKPRODUCT_CGU_NAME) && let Some(work_product) = tcx.dep_graph.previous_work_product(&work_product_id) && tcx.dep_graph.try_mark_green(tcx, &dep_node).is_some() { let saved_path = &work_product.saved_files[OutputType::Metadata.extension()]; - let incr_comp_session_dir = &tcx.incr_comp_session.unwrap().session_directory; - let source_file_in_incr_dir = &incr_comp_session_dir.join(saved_path); + let source_file_in_incr_dir = &old_incr_comp_session_dir.join(saved_path); debug!("copying preexisting metadata from {source_file_in_incr_dir:?} to {path:?}"); match rustc_fs_util::link_or_copy(&source_file_in_incr_dir, path) { Ok(_) => {} diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index eb9f56d887684..43936770ff762 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -74,28 +74,41 @@ pub(crate) fn as_constant_inner<'tcx>( ExprKind::NamedConst { def_id, args, ref user_ty } => { let user_ty = user_ty.as_ref().and_then(push_cuta); - // Under generic_const_args, `def_id` might be a regular const declared in a trait, but - // is `impl`d as a directly represented const. We do not know whether it is here, so we - // must use type system normalization for all consts under generic_const_args. - // FIXME(generic_const_args): there's a lot to consider here! `Const::Ty` uses valtrees - // and `Const::Unevaluated` does not, we should revisit this before stabilization. - let def_kind = tcx.def_kind(def_id); - if tcx.features().generic_const_args() - || matches!(def_kind, DefKind::Const | DefKind::AssocConst) - && tcx.is_direct_const(def_id) - { - let kind = match def_kind { - DefKind::AssocConst => { - if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(def_id)) - { - ty::AliasConstKind::InherentImpl { def_id } - } else { - ty::AliasConstKind::Projection { def_id } - } + let get_kind = |def_id, def_kind| match def_kind { + DefKind::AssocConst => { + if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(def_id)) { + ty::AliasConstKind::InherentImpl { def_id } + } else { + ty::AliasConstKind::Projection { def_id } } - DefKind::Const => ty::AliasConstKind::Free { def_id }, - _ => unreachable!(), + } + DefKind::Const => ty::AliasConstKind::Free { def_id }, + kind => bug!("unexpected DefKind in THIR ExprKind::NamedConst: {kind:?}"), + }; + + let could_be_direct_const = |def_id| { + let def_kind = tcx.def_kind(def_id); + let (DefKind::Const | DefKind::AssocConst) = def_kind else { + return None; }; + if tcx.is_direct_const(def_id) { + return Some(get_kind(def_id, def_kind)); + } + // Under generic_const_args, `def_id` might be a regular const declared in a trait, + // but is `impl`d as a directly represented const. We do not know whether it is + // here, so we must use type system normalization for all const projections. + // FIXME(generic_const_args): there's a lot to consider here! `Const::Ty` uses + // valtrees and `Const::Unevaluated` does not, we should revisit this before + // stabilization. + if tcx.features().generic_const_args() + && let kind @ ty::AliasConstKind::Projection { .. } = get_kind(def_id, def_kind) + { + return Some(kind); + } + None + }; + + if let Some(kind) = could_be_direct_const(def_id) { let alias = ty::AliasConst::new(tcx, kind, args); let ct = ty::Const::new_alias(tcx, ty::IsRigid::No, alias); let const_ = Const::Ty(ty, ct); diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 928518c88fec6..0630a65e56cb4 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -3,7 +3,7 @@ use std::ops::{Deref, DerefMut}; use ast::token::IdentKind; use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind}; -use rustc_ast::util::parser::AssocOp; +use rustc_ast::util::parser::{AssocOp, ExprPrecedence}; use rustc_ast::{ self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block, BlockCheckMode, Expr, ExprKind, GenericArg, GenericArgs, Generics, Item, ItemKind, @@ -1719,26 +1719,35 @@ impl<'a> Parser<'a> { &mut self, await_sp: Span, ) -> PResult<'a, Box> { - let (hi, expr, is_question) = if self.token == token::Bang { + let (hi, expr_span, is_question) = if self.token == token::Bang { // Handle `await!()`. self.recover_await_macro()? } else { self.recover_await_prefix(await_sp)? }; - let (sp, guar) = self.error_on_incorrect_await(await_sp, hi, &expr, is_question); + let (sp, guar) = self.error_on_incorrect_await(await_sp, hi, expr_span, is_question); let expr = self.mk_expr_err(await_sp.to(sp), guar); self.maybe_recover_from_bad_qpath(expr) } - fn recover_await_macro(&mut self) -> PResult<'a, (Span, Box, bool)> { + fn recover_await_macro(&mut self) -> PResult<'a, (Span, Span, bool)> { self.expect(exp!(Bang))?; self.expect(exp!(OpenParen))?; + let open = self.prev_token.span; let expr = self.parse_expr()?; self.expect(exp!(CloseParen))?; - Ok((self.prev_token.span, expr, false)) + let close = self.prev_token.span; + // Keep parentheses when needed for `.await`, e.g. `(&mut future).await`. + // Use the delimiters to preserve any comments around the operand. + let expr_span = if expr.precedence() < ExprPrecedence::Unambiguous { + open.to(close) + } else { + open.shrink_to_hi().to(close.shrink_to_lo()) + }; + Ok((close, expr_span, false)) } - fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, Box, bool)> { + fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, Span, bool)> { let is_question = self.eat(exp!(Question)); // Handle `await? `. let expr = if self.token == token::OpenBrace { // Handle `await { }`. @@ -1752,22 +1761,22 @@ impl<'a> Parser<'a> { err.span_label(await_sp, format!("while parsing this incorrect await expression")); err })?; - Ok((expr.span, expr, is_question)) + Ok((expr.span, expr.span, is_question)) } fn error_on_incorrect_await( &self, lo: Span, hi: Span, - expr: &Expr, + expr_span: Span, is_question: bool, ) -> (Span, ErrorGuaranteed) { let span = lo.to(hi); let guar = self.dcx().emit_err(IncorrectAwait { span, suggestion: AwaitSuggestion { - removal: lo.until(expr.span), - dot_await: expr.span.shrink_to_hi(), + removal: lo.until(expr_span), + dot_await: expr_span.shrink_to_hi().to(hi.shrink_to_hi()), question_mark: if is_question { "?" } else { "" }, }, }); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 65c0229184db6..3b60a13b8e6f2 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1840,10 +1840,11 @@ fn validate_commandline_args_with_session_available(sess: &Session) { /// Holds data on the current incremental compilation session, if there is one. pub struct IncrCompSession { - /// The directory containing all cached data. Cached data from a previous - /// session can be read out of it and new data for the current session will - /// be written into it. - pub session_directory: flock::LockedDir, + /// The directory from which cached data of a previous session can be read. + pub old_session_directory: Option, + /// The directory to which cached data for the current session can be + /// written to. + pub new_session_directory: flock::LockedDir, } /// A wrapper around an [`DiagCtxt`] that is used for early error emissions. diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 32237e9f60ca3..7dccf278ac9b1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3795,9 +3795,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if typeck_results.hir_owner.to_def_id() != typeck_root { return false; } + + // Error reporting can run before closure capture analysis has inferred the + // tuple of upvar types. avoid accessing upvar types until they are available. + let upvar_tys = match upvar_args.tupled_upvars_ty().kind() { + ty::Tuple(args) => args, + ty::Error(_) => ty::List::empty(), + ty::Infer(_) => return false, + ty => unreachable!("unexpected upvar types tuple: {ty:?}"), + }; + let captures: Vec<_> = typeck_results.closure_min_captures_flattened(closure_def_id).collect(); - let upvar_tys = upvar_args.upvar_tys(); if captures.len() != upvar_tys.len() { return false; } diff --git a/library/stdarch/.github/workflows/main.yml b/library/stdarch/.github/workflows/main.yml index 5c2e2ae4a8e21..d7539fe2e8ebd 100644 --- a/library/stdarch/.github/workflows/main.yml +++ b/library/stdarch/.github/workflows/main.yml @@ -8,208 +8,208 @@ jobs: name: Check Style runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: rustup update nightly --no-self-update && rustup default nightly - - run: ci/style.sh + - uses: actions/checkout@v6 + - name: Install Rust + run: rustup update nightly --no-self-update && rustup default nightly + - run: ci/style.sh docs: name: Build Documentation - needs: [style] + needs: [ style ] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: rustup update nightly --no-self-update && rustup default nightly - - run: ci/dox.sh - env: - CI: 1 + - uses: actions/checkout@v6 + - name: Install Rust + run: rustup update nightly --no-self-update && rustup default nightly + - run: ci/dox.sh + env: + CI: 1 verify: name: Automatic intrinsic verification - needs: [style] + needs: [ style ] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: rustup update nightly --no-self-update && rustup default nightly - - run: cargo test --manifest-path crates/stdarch-verify/Cargo.toml + - uses: actions/checkout@v6 + - name: Install Rust + run: rustup update nightly --no-self-update && rustup default nightly + - run: cargo test --manifest-path crates/stdarch-verify/Cargo.toml test: - needs: [style] + needs: [ style ] name: Test runs-on: ${{ matrix.target.os }} strategy: matrix: profile: - - dev - - release + - dev + - release target: - # Dockers that are run through docker on linux - - tuple: i686-unknown-linux-gnu - os: ubuntu-latest - - tuple: x86_64-unknown-linux-gnu - os: ubuntu-latest - - tuple: arm-unknown-linux-gnueabihf - os: ubuntu-latest - - tuple: armv7-unknown-linux-gnueabihf - os: ubuntu-latest - - tuple: aarch64-unknown-linux-gnu - os: ubuntu-latest - - tuple: aarch64_be-unknown-linux-gnu - os: ubuntu-latest - - tuple: riscv32gc-unknown-linux-gnu - os: ubuntu-latest - - tuple: riscv64gc-unknown-linux-gnu - os: ubuntu-latest - - tuple: powerpc-unknown-linux-gnu - os: ubuntu-latest - - tuple: powerpc64-unknown-linux-gnu - os: ubuntu-latest - - tuple: powerpc64le-unknown-linux-gnu - os: ubuntu-latest - # MIPS targets disabled since they are dropped to tier 3. - # See https://github.com/rust-lang/compiler-team/issues/648 - #- tuple: mips-unknown-linux-gnu - # os: ubuntu-latest - #- tuple: mips64-unknown-linux-gnuabi64 - # os: ubuntu-latest - #- tuple: mips64el-unknown-linux-gnuabi64 - # os: ubuntu-latest - #- tuple: mipsel-unknown-linux-musl - # os: ubuntu-latest - - tuple: s390x-unknown-linux-gnu - os: ubuntu-latest - - tuple: i586-unknown-linux-gnu - os: ubuntu-latest - - tuple: nvptx64-nvidia-cuda - os: ubuntu-latest - - tuple: amdgcn-amd-amdhsa - os: ubuntu-latest - - tuple: thumbv6m-none-eabi - os: ubuntu-latest - - tuple: thumbv7m-none-eabi - os: ubuntu-latest - - tuple: thumbv7em-none-eabi - os: ubuntu-latest - - tuple: thumbv7em-none-eabihf - os: ubuntu-latest - - tuple: loongarch64-unknown-linux-gnu - os: ubuntu-latest - # hexagon doesn't build at the moment due to a libc issue. - # - tuple: hexagon-unknown-linux-musl - # os: ubuntu-latest - - tuple: wasm32-wasip1 - os: ubuntu-latest - - # macOS targets - - tuple: x86_64-apple-darwin - os: macos-15-intel - - tuple: x86_64-apple-ios-macabi - os: macos-15-intel - - tuple: aarch64-apple-darwin - os: macos-15 - - tuple: aarch64-apple-ios-macabi - os: macos-15 - # FIXME: gh-actions build environment doesn't have linker support - # - tuple: i686-apple-darwin - # os: macos-13 - - # Windows targets - - tuple: x86_64-pc-windows-msvc - os: windows-2025 - - tuple: i686-pc-windows-msvc - os: windows-2025 - - tuple: aarch64-pc-windows-msvc - os: windows-11-arm - - tuple: arm64ec-pc-windows-msvc - os: windows-11-arm - - tuple: x86_64-pc-windows-gnu - os: windows-2025 - # - tuple: i686-pc-windows-gnu - # os: windows-latest - - # Add additional variables to the matrix variations generated above using `include`: - include: - # `TEST_EVERYTHING` setups - there should be at least 1 for each architecture - - target: - tuple: aarch64-unknown-linux-gnu + # Dockers that are run through docker on linux + - tuple: i686-unknown-linux-gnu + os: ubuntu-latest + - tuple: x86_64-unknown-linux-gnu + os: ubuntu-latest + - tuple: arm-unknown-linux-gnueabihf os: ubuntu-latest - test_everything: true - - target: - tuple: aarch64_be-unknown-linux-gnu + - tuple: armv7-unknown-linux-gnueabihf os: ubuntu-latest - test_everything: true - build_std: true - - target: - tuple: armv7-unknown-linux-gnueabihf + - tuple: aarch64-unknown-linux-gnu os: ubuntu-latest - test_everything: true - - target: - tuple: loongarch64-unknown-linux-gnu + - tuple: aarch64_be-unknown-linux-gnu os: ubuntu-latest - test_everything: true - - target: - tuple: powerpc-unknown-linux-gnu + - tuple: riscv32gc-unknown-linux-gnu os: ubuntu-latest - disable_assert_instr: true - test_everything: true - - target: - tuple: powerpc64-unknown-linux-gnu + - tuple: riscv64gc-unknown-linux-gnu os: ubuntu-latest - disable_assert_instr: true - test_everything: true - - target: - tuple: powerpc64le-unknown-linux-gnu + - tuple: powerpc-unknown-linux-gnu os: ubuntu-latest - test_everything: true - - target: - tuple: riscv32gc-unknown-linux-gnu + - tuple: powerpc64-unknown-linux-gnu os: ubuntu-latest - test_everything: true - build_std: true - - target: - tuple: riscv64gc-unknown-linux-gnu + - tuple: powerpc64le-unknown-linux-gnu os: ubuntu-latest - test_everything: true - - target: - tuple: s390x-unknown-linux-gnu + # MIPS targets disabled since they are dropped to tier 3. + # See https://github.com/rust-lang/compiler-team/issues/648 + #- tuple: mips-unknown-linux-gnu + # os: ubuntu-latest + #- tuple: mips64-unknown-linux-gnuabi64 + # os: ubuntu-latest + #- tuple: mips64el-unknown-linux-gnuabi64 + # os: ubuntu-latest + #- tuple: mipsel-unknown-linux-musl + # os: ubuntu-latest + - tuple: s390x-unknown-linux-gnu os: ubuntu-latest - test_everything: true - - target: - tuple: x86_64-unknown-linux-gnu + - tuple: i586-unknown-linux-gnu os: ubuntu-latest - test_everything: true - # MIPS targets disabled since they are dropped to tier 3. - # See https://github.com/rust-lang/compiler-team/issues/648 - #- target: - # tuple: mips-unknown-linux-gnu - # os: ubuntu-latest - # norun: true - #- target: - # tuple: mips64-unknown-linux-gnuabi64 - # os: ubuntu-latest - # norun: true - #- target: - # tuple: mips64el-unknown-linux-gnuabi64 - # os: ubuntu-latest - # norun: true - #- target: - # tuple: mipsel-unknown-linux-musl - # os: ubuntu-latest - # norun: true - - target: - tuple: aarch64-apple-darwin + - tuple: nvptx64-nvidia-cuda + os: ubuntu-latest + - tuple: amdgcn-amd-amdhsa + os: ubuntu-latest + - tuple: thumbv6m-none-eabi + os: ubuntu-latest + - tuple: thumbv7m-none-eabi + os: ubuntu-latest + - tuple: thumbv7em-none-eabi + os: ubuntu-latest + - tuple: thumbv7em-none-eabihf + os: ubuntu-latest + - tuple: loongarch64-unknown-linux-gnu + os: ubuntu-latest + # hexagon doesn't build at the moment due to a libc issue. + # - tuple: hexagon-unknown-linux-musl + # os: ubuntu-latest + - tuple: wasm32-wasip1 + os: ubuntu-latest + + # macOS targets + - tuple: x86_64-apple-darwin + os: macos-15-intel + - tuple: x86_64-apple-ios-macabi + os: macos-15-intel + - tuple: aarch64-apple-darwin os: macos-15 - norun: true # https://github.com/rust-lang/stdarch/issues/1206 - - target: - tuple: aarch64-apple-ios-macabi + - tuple: aarch64-apple-ios-macabi os: macos-15 - norun: true # https://github.com/rust-lang/stdarch/issues/1206 - - target: - tuple: amdgcn-amd-amdhsa - os: ubuntu-latest - norun: true + # FIXME: gh-actions build environment doesn't have linker support + # - tuple: i686-apple-darwin + # os: macos-13 + + # Windows targets + - tuple: x86_64-pc-windows-msvc + os: windows-2025 + - tuple: i686-pc-windows-msvc + os: windows-2025 + - tuple: aarch64-pc-windows-msvc + os: windows-11-arm + - tuple: arm64ec-pc-windows-msvc + os: windows-11-arm + - tuple: x86_64-pc-windows-gnu + os: windows-2025 + # - tuple: i686-pc-windows-gnu + # os: windows-latest + + # Add additional variables to the matrix variations generated above using `include`: + include: + # `TEST_EVERYTHING` setups - there should be at least 1 for each architecture + - target: + tuple: aarch64-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + - target: + tuple: aarch64_be-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + build_std: true + - target: + tuple: armv7-unknown-linux-gnueabihf + os: ubuntu-latest + test_everything: true + - target: + tuple: loongarch64-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + - target: + tuple: powerpc-unknown-linux-gnu + os: ubuntu-latest + disable_assert_instr: true + test_everything: true + - target: + tuple: powerpc64-unknown-linux-gnu + os: ubuntu-latest + disable_assert_instr: true + test_everything: true + - target: + tuple: powerpc64le-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + - target: + tuple: riscv32gc-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + build_std: true + - target: + tuple: riscv64gc-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + - target: + tuple: s390x-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + - target: + tuple: x86_64-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + # MIPS targets disabled since they are dropped to tier 3. + # See https://github.com/rust-lang/compiler-team/issues/648 + #- target: + # tuple: mips-unknown-linux-gnu + # os: ubuntu-latest + # norun: true + #- target: + # tuple: mips64-unknown-linux-gnuabi64 + # os: ubuntu-latest + # norun: true + #- target: + # tuple: mips64el-unknown-linux-gnuabi64 + # os: ubuntu-latest + # norun: true + #- target: + # tuple: mipsel-unknown-linux-musl + # os: ubuntu-latest + # norun: true + - target: + tuple: aarch64-apple-darwin + os: macos-15 + norun: true # https://github.com/rust-lang/stdarch/issues/1206 + - target: + tuple: aarch64-apple-ios-macabi + os: macos-15 + norun: true # https://github.com/rust-lang/stdarch/issues/1206 + - target: + tuple: amdgcn-amd-amdhsa + os: ubuntu-latest + norun: true # hexagon doesn't build at the moment due to a libc issue. # - target: # tuple: hexagon-unknown-linux-musl @@ -218,59 +218,61 @@ jobs: # build_std: true steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: | - rustup update nightly --no-self-update - rustup default nightly - shell: bash + - uses: actions/checkout@v6 + - name: Install Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + shell: bash + + - run: rustup component add rustfmt - - run: rustup target add ${{ matrix.target.tuple }} - shell: bash - if: matrix.build_std == '' && matrix.target.tuple != 'amdgcn-amd-amdhsa' - - run: | - rustup component add rust-src - echo "CARGO_UNSTABLE_BUILD_STD=std" >> $GITHUB_ENV - shell: bash - if: matrix.build_std != '' - - run: | - rustup component add rust-src - echo "CARGO_UNSTABLE_BUILD_STD=core,alloc" >> $GITHUB_ENV - shell: bash - if: matrix.target.tuple == 'amdgcn-amd-amdhsa' + - run: rustup target add ${{ matrix.target.tuple }} + shell: bash + if: matrix.build_std == '' && matrix.target.tuple != 'amdgcn-amd-amdhsa' + - run: | + rustup component add rust-src + echo "CARGO_UNSTABLE_BUILD_STD=std" >> $GITHUB_ENV + shell: bash + if: matrix.build_std != '' + - run: | + rustup component add rust-src + echo "CARGO_UNSTABLE_BUILD_STD=core,alloc" >> $GITHUB_ENV + shell: bash + if: matrix.target.tuple == 'amdgcn-amd-amdhsa' - # Configure some env vars based on matrix configuration - - run: echo "PROFILE=${{matrix.profile}}" >> $GITHUB_ENV - shell: bash - - run: echo "NORUN=1" >> $GITHUB_ENV - shell: bash - if: matrix.norun != '' || startsWith(matrix.target.tuple, 'thumb') || matrix.target.tuple == 'nvptx64-nvidia-cuda' - - run: echo "STDARCH_TEST_EVERYTHING=1" >> $GITHUB_ENV - shell: bash - if: matrix.test_everything != '' - - run: echo "STDARCH_DISABLE_ASSERT_INSTR=1" >> $GITHUB_ENV - shell: bash - if: matrix.disable_assert_instr != '' - - run: echo "NOSTD=1" >> $GITHUB_ENV - shell: bash - if: startsWith(matrix.target.tuple, 'thumb') || matrix.target.tuple == 'nvptx64-nvidia-cuda' || matrix.target.tuple == 'amdgcn-amd-amdhsa' + # Configure some env vars based on matrix configuration + - run: echo "PROFILE=${{matrix.profile}}" >> $GITHUB_ENV + shell: bash + - run: echo "NORUN=1" >> $GITHUB_ENV + shell: bash + if: matrix.norun != '' || startsWith(matrix.target.tuple, 'thumb') || matrix.target.tuple == 'nvptx64-nvidia-cuda' + - run: echo "STDARCH_TEST_EVERYTHING=1" >> $GITHUB_ENV + shell: bash + if: matrix.test_everything != '' + - run: echo "STDARCH_DISABLE_ASSERT_INSTR=1" >> $GITHUB_ENV + shell: bash + if: matrix.disable_assert_instr != '' + - run: echo "NOSTD=1" >> $GITHUB_ENV + shell: bash + if: startsWith(matrix.target.tuple, 'thumb') || matrix.target.tuple == 'nvptx64-nvidia-cuda' || matrix.target.tuple == 'amdgcn-amd-amdhsa' - # Windows & OSX go straight to `run.sh` ... - - run: ./ci/run.sh - shell: bash - if: matrix.target.os != 'ubuntu-latest' || startsWith(matrix.target.tuple, 'thumb') - env: - TARGET: ${{ matrix.target.tuple }} + # Windows & OSX go straight to `run.sh` ... + - run: ./ci/run.sh + shell: bash + if: matrix.target.os != 'ubuntu-latest' || startsWith(matrix.target.tuple, 'thumb') + env: + TARGET: ${{ matrix.target.tuple }} - # ... while Linux goes to `run-docker.sh` - - run: ./ci/run-docker.sh ${{ matrix.target.tuple }} - shell: bash - if: matrix.target.os == 'ubuntu-latest' && !startsWith(matrix.target.tuple, 'thumb') - env: - TARGET: ${{ matrix.target.tuple }} + # ... while Linux goes to `run-docker.sh` + - run: ./ci/run-docker.sh ${{ matrix.target.tuple }} + shell: bash + if: matrix.target.os == 'ubuntu-latest' && !startsWith(matrix.target.tuple, 'thumb') + env: + TARGET: ${{ matrix.target.tuple }} intrinsic-test: - needs: [style] + needs: [ style ] name: Intrinsic Test runs-on: ubuntu-latest strategy: @@ -279,9 +281,10 @@ jobs: - aarch64-unknown-linux-gnu - aarch64_be-unknown-linux-gnu - armv7-unknown-linux-gnueabihf + - loongarch64-unknown-linux-gnu - x86_64-unknown-linux-gnu - profile: [dev, release] - cc: [clang, gcc] + profile: [ dev, release ] + cc: [ clang, gcc ] include: - target: aarch64_be-unknown-linux-gnu build_std: true @@ -295,74 +298,71 @@ jobs: - target: armv7-unknown-linux-gnueabihf cc: gcc steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: | - rustup update nightly --no-self-update - rustup default nightly - - run: rustup target add ${{ matrix.target }} - if: ${{ (matrix.build_std || false) == false }} - - run: | - rustup component add rust-src - echo "CARGO_UNSTABLE_BUILD_STD=std" >> $GITHUB_ENV - if: ${{ matrix.build_std }} - - run: rustup component add rustfmt + - uses: actions/checkout@v6 + - name: Install Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + - run: rustup target add ${{ matrix.target }} + if: ${{ (matrix.build_std || false) == false }} + - run: | + rustup component add rust-src + echo "CARGO_UNSTABLE_BUILD_STD=std" >> $GITHUB_ENV + if: ${{ matrix.build_std }} + - run: rustup component add rustfmt - # Configure some env vars based on matrix configuration - - run: echo "PROFILE=${{ matrix.profile }}" >> $GITHUB_ENV - - run: ./ci/intrinsic-test-docker.sh ${{ matrix.target }} ${{ matrix.cc }} - if: ${{ !startsWith(matrix.target, 'thumb') }} - env: - TARGET: ${{ matrix.target }} + # Configure some env vars based on matrix configuration + - run: echo "PROFILE=${{ matrix.profile }}" >> $GITHUB_ENV + - run: ./ci/intrinsic-test-docker.sh ${{ matrix.target }} ${{ matrix.cc }} + if: ${{ !startsWith(matrix.target, 'thumb') }} + env: + TARGET: ${{ matrix.target }} # Check that the generated files agree with the checked-in versions. check-stdarch-gen: - needs: [style] + needs: [ style ] name: Check stdarch-gen-{arm, loongarch, hexagon} output runs-on: ubuntu-latest env: STDARCH_GEN_MODE: check steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: rustup update nightly && rustup default nightly && rustup component add rustfmt - - name: Check arm spec - run: | - cargo run --bin=stdarch-gen-arm --release -- crates/stdarch-gen-arm/spec - - name: Check loongarch lsx - run: | - cargo run -p stdarch-gen-loongarch --release -- lsx - git diff --exit-code - - name: Check loongarch lasx - run: | - cargo run -p stdarch-gen-loongarch --release -- lasx - git diff --exit-code - - name: Check hexagon - run: | - cargo run -p stdarch-gen-hexagon --release - git diff --exit-code - + - uses: actions/checkout@v6 + - name: Install Rust + run: rustup update nightly && rustup default nightly && rustup component add rustfmt + - name: Check arm spec + run: | + cargo run --bin=stdarch-gen-arm --release -- crates/stdarch-gen-arm/spec + - name: Check loongarch lsx + run: | + cargo run -p stdarch-gen-loongarch --release -- lsx + - name: Check loongarch lasx + run: | + cargo run -p stdarch-gen-loongarch --release -- lasx + - name: Check hexagon + run: | + cargo run -p stdarch-gen-hexagon --release + # Run some tests with Miri. Most stdarch functions use platform-specific intrinsics # that Miri does not support. Also Miri is reltively slow. # # Below we run some tests where Miri might catch UB, for instance on intrinsics that read from # or write to pointers. miri: - needs: [style] + needs: [ style ] name: Run some tests with miri runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: rustup update nightly && rustup default nightly && rustup component add miri - - name: Run miri tests - env: - TARGET: "aarch64-unknown-linux-gnu" - RUSTFLAGS: "-Ctarget-cpu=neoverse-v3" - run: | - # read filters and join them with a space. - FILTERS=$(cat aarch64-miri-tests.txt | tr '\n' ' ') - cargo miri test -p core_arch --target aarch64-unknown-linux-gnu -- $FILTERS + - uses: actions/checkout@v6 + - name: Install Rust + run: rustup update nightly && rustup default nightly && rustup component add miri + - name: Run miri tests + env: + TARGET: "aarch64-unknown-linux-gnu" + RUSTFLAGS: "-Ctarget-cpu=neoverse-v3" + run: | + # read filters and join them with a space. + FILTERS=$(cat aarch64-miri-tests.txt | tr '\n' ' ') + cargo miri test -p core_arch --target aarch64-unknown-linux-gnu -- $FILTERS conclusion: needs: diff --git a/library/stdarch/Cargo.lock b/library/stdarch/Cargo.lock index 9ec3227f49e7d..490161626c164 100644 --- a/library/stdarch/Cargo.lock +++ b/library/stdarch/Cargo.lock @@ -88,6 +88,16 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +[[package]] +name = "bstr" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" +dependencies = [ + "memchr", + "serde_core", +] + [[package]] name = "cc" version = "1.2.59" @@ -800,10 +810,20 @@ dependencies = [ "syn", ] +[[package]] +name = "similar" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f66ca1f7aca2474dc10c942eb22feffc897735f54cd1db90138c2fddb490987" +dependencies = [ + "bstr", +] + [[package]] name = "stdarch-gen-arm" version = "0.1.0" dependencies = [ + "clap", "itertools", "proc-macro2", "quote", @@ -819,6 +839,7 @@ dependencies = [ name = "stdarch-gen-common" version = "0.1.0" dependencies = [ + "similar", "tempfile", ] @@ -826,6 +847,7 @@ dependencies = [ name = "stdarch-gen-hexagon" version = "0.1.0" dependencies = [ + "clap", "regex", "stdarch-gen-common", ] @@ -834,6 +856,7 @@ dependencies = [ name = "stdarch-gen-loongarch" version = "0.1.0" dependencies = [ + "clap", "rand 0.9.4", "stdarch-gen-common", ] diff --git a/library/stdarch/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile b/library/stdarch/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile index e803dae1006a0..8cbd2d8080002 100644 --- a/library/stdarch/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile +++ b/library/stdarch/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile @@ -3,8 +3,15 @@ FROM ubuntu:25.10 RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev qemu-user ca-certificates \ - gcc-loongarch64-linux-gnu libc6-dev-loong64-cross + gcc-loongarch64-linux-gnu libc6-dev-loong64-cross \ + wget +RUN wget https://ci-mirrors.rust-lang.org/llvm/llvm-22.1.4-x86_64.tar.gz -O llvm.tar.xz +RUN mkdir llvm +RUN tar -xvf llvm.tar.xz --strip-components=1 -C llvm + +ENV CLANG_PATH="/llvm/bin/clang" +ENV GCC_PATH=loongarch64-linux-gnu-gcc ENV CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_LINKER=loongarch64-linux-gnu-gcc \ CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_RUNNER="qemu-loongarch64 -cpu max -L /usr/loongarch64-linux-gnu" \ diff --git a/library/stdarch/ci/intrinsic-test.sh b/library/stdarch/ci/intrinsic-test.sh index 3966aa88d8f41..4b7a3d27ea4e2 100755 --- a/library/stdarch/ci/intrinsic-test.sh +++ b/library/stdarch/ci/intrinsic-test.sh @@ -65,6 +65,12 @@ case ${TARGET} in ARCH=x86 RUNTIME_RUSTFLAGS= ;; + + loongarch64*) + export CFLAGS="-I/usr/loongarch64-linux-gnu/include/" + ARCH=loongarch64 + RUNTIME_RUSTFLAGS=-Ctarget-feature=+lsx,+lasx,+frecipe + ;; *) ;; @@ -80,6 +86,14 @@ case "${TARGET}" in --target "${TARGET}" \ --cc-arg-style "${CC_ARG_STYLE}" ;; + loongarch64*) + cargo run "${INTRINSIC_TEST}" --release \ + --bin intrinsic-test -- crates/stdarch-gen-loongarch \ + --skip "crates/intrinsic-test/missing_${ARCH}_common.txt" \ + --skip "crates/intrinsic-test/missing_${ARCH}_${CC_KIND}.txt" \ + --target "${TARGET}" \ + --cc-arg-style "${CC_ARG_STYLE}" + ;; *) cargo run "${INTRINSIC_TEST}" --release \ --bin intrinsic-test -- intrinsics_data/arm_intrinsics.json \ diff --git a/library/stdarch/crates/core_arch/Cargo.toml b/library/stdarch/crates/core_arch/Cargo.toml index ab8b9bcd9fcef..ee3eff825c790 100644 --- a/library/stdarch/crates/core_arch/Cargo.toml +++ b/library/stdarch/crates/core_arch/Cargo.toml @@ -24,6 +24,9 @@ stdarch-test = { version = "0.*", path = "../stdarch-test" } [target.'cfg(all(target_arch = "x86_64", target_os = "linux"))'.dev-dependencies] syscalls = { version = "0.6.18", default-features = false } +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_has_reliable_f16)'] } + [lints.clippy] too_long_first_doc_paragraph = "allow" missing_transmute_annotations = "allow" diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index 9fb0e1464683e..72ce377acc9fb 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -25081,7 +25081,7 @@ pub unsafe fn vst1q_f64_x4(a: *mut f64, b: float64x2x4_t) { #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_lane_f64(a: *mut f64, b: float64x1_t) { static_assert!(LANE == 0); - *a = simd_extract!(b, LANE as u32); + core::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_f64)"] @@ -25094,7 +25094,7 @@ pub unsafe fn vst1_lane_f64(a: *mut f64, b: float64x1_t) { #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_lane_f64(a: *mut f64, b: float64x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + core::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple 2-element structures from two registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst2_f64)"] diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index c66702814cfb2..e04c93ac1acae 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -120,7 +120,7 @@ pub unsafe fn vld1q_dup_f64(ptr: *const f64) -> float64x2_t { #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_lane_f64(ptr: *const f64, src: float64x1_t) -> float64x1_t { static_assert!(LANE == 0); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } /// Load one single-element structure to one lane of one register. @@ -131,7 +131,7 @@ pub unsafe fn vld1_lane_f64(ptr: *const f64, src: float64x1_t) #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_lane_f64(ptr: *const f64, src: float64x2_t) -> float64x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } /// Bitwise Select instructions. This instruction sets each bit in the destination SIMD&FP register diff --git a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs index 324b5bccf3777..75393f594ad64 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs @@ -11,8 +11,8 @@ use stdarch_test::assert_instr; use super::*; -use crate::core_arch::arch::aarch64::*; use super::{AsSigned, AsUnsigned}; +use crate::core_arch::arch::aarch64::*; #[doc = "Absolute difference"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svabd[_f32]_m)"] diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 094b13ca8023a..237f8fb413c99 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -18265,7 +18265,7 @@ pub unsafe fn vld1q_dup_f16(ptr: *const f16) -> float16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -18279,7 +18279,7 @@ pub unsafe fn vld1q_dup_f16(ptr: *const f16) -> float16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_f32(ptr: *const f32) -> float32x2_t { - transmute(f32x2::splat(*ptr)) + transmute(f32x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_p16)"] @@ -18302,7 +18302,7 @@ pub unsafe fn vld1_dup_f32(ptr: *const f32) -> float32x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_p16(ptr: *const p16) -> poly16x4_t { - transmute(u16x4::splat(*ptr)) + transmute(u16x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_p8)"] @@ -18325,7 +18325,7 @@ pub unsafe fn vld1_dup_p16(ptr: *const p16) -> poly16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_p8(ptr: *const p8) -> poly8x8_t { - transmute(u8x8::splat(*ptr)) + transmute(u8x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_s16)"] @@ -18348,7 +18348,7 @@ pub unsafe fn vld1_dup_p8(ptr: *const p8) -> poly8x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_s16(ptr: *const i16) -> int16x4_t { - transmute(i16x4::splat(*ptr)) + transmute(i16x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_s32)"] @@ -18371,7 +18371,7 @@ pub unsafe fn vld1_dup_s16(ptr: *const i16) -> int16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_s32(ptr: *const i32) -> int32x2_t { - transmute(i32x2::splat(*ptr)) + transmute(i32x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_s8)"] @@ -18394,7 +18394,7 @@ pub unsafe fn vld1_dup_s32(ptr: *const i32) -> int32x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_s8(ptr: *const i8) -> int8x8_t { - transmute(i8x8::splat(*ptr)) + transmute(i8x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_u16)"] @@ -18417,7 +18417,7 @@ pub unsafe fn vld1_dup_s8(ptr: *const i8) -> int8x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_u16(ptr: *const u16) -> uint16x4_t { - transmute(u16x4::splat(*ptr)) + transmute(u16x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_u32)"] @@ -18440,7 +18440,7 @@ pub unsafe fn vld1_dup_u16(ptr: *const u16) -> uint16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_u32(ptr: *const u32) -> uint32x2_t { - transmute(u32x2::splat(*ptr)) + transmute(u32x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_u8)"] @@ -18463,7 +18463,7 @@ pub unsafe fn vld1_dup_u32(ptr: *const u32) -> uint32x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_u8(ptr: *const u8) -> uint8x8_t { - transmute(u8x8::splat(*ptr)) + transmute(u8x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_f32)"] @@ -18472,7 +18472,7 @@ pub unsafe fn vld1_dup_u8(ptr: *const u8) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -18486,7 +18486,7 @@ pub unsafe fn vld1_dup_u8(ptr: *const u8) -> uint8x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_f32(ptr: *const f32) -> float32x4_t { - transmute(f32x4::splat(*ptr)) + transmute(f32x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_p16)"] @@ -18509,7 +18509,7 @@ pub unsafe fn vld1q_dup_f32(ptr: *const f32) -> float32x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_p16(ptr: *const p16) -> poly16x8_t { - transmute(u16x8::splat(*ptr)) + transmute(u16x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_p8)"] @@ -18532,7 +18532,7 @@ pub unsafe fn vld1q_dup_p16(ptr: *const p16) -> poly16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_p8(ptr: *const p8) -> poly8x16_t { - transmute(u8x16::splat(*ptr)) + transmute(u8x16::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s16)"] @@ -18555,7 +18555,7 @@ pub unsafe fn vld1q_dup_p8(ptr: *const p8) -> poly8x16_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s16(ptr: *const i16) -> int16x8_t { - transmute(i16x8::splat(*ptr)) + transmute(i16x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s32)"] @@ -18578,7 +18578,7 @@ pub unsafe fn vld1q_dup_s16(ptr: *const i16) -> int16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s32(ptr: *const i32) -> int32x4_t { - transmute(i32x4::splat(*ptr)) + transmute(i32x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s64)"] @@ -18587,7 +18587,7 @@ pub unsafe fn vld1q_dup_s32(ptr: *const i32) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -18601,7 +18601,7 @@ pub unsafe fn vld1q_dup_s32(ptr: *const i32) -> int32x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s64(ptr: *const i64) -> int64x2_t { - transmute(i64x2::splat(*ptr)) + transmute(i64x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s8)"] @@ -18624,7 +18624,7 @@ pub unsafe fn vld1q_dup_s64(ptr: *const i64) -> int64x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s8(ptr: *const i8) -> int8x16_t { - transmute(i8x16::splat(*ptr)) + transmute(i8x16::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u16)"] @@ -18647,7 +18647,7 @@ pub unsafe fn vld1q_dup_s8(ptr: *const i8) -> int8x16_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u16(ptr: *const u16) -> uint16x8_t { - transmute(u16x8::splat(*ptr)) + transmute(u16x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u32)"] @@ -18670,7 +18670,7 @@ pub unsafe fn vld1q_dup_u16(ptr: *const u16) -> uint16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u32(ptr: *const u32) -> uint32x4_t { - transmute(u32x4::splat(*ptr)) + transmute(u32x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u64)"] @@ -18679,7 +18679,7 @@ pub unsafe fn vld1q_dup_u32(ptr: *const u32) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -18693,7 +18693,7 @@ pub unsafe fn vld1q_dup_u32(ptr: *const u32) -> uint32x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u64(ptr: *const u64) -> uint64x2_t { - transmute(u64x2::splat(*ptr)) + transmute(u64x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u8)"] @@ -18716,7 +18716,7 @@ pub unsafe fn vld1q_dup_u64(ptr: *const u64) -> uint64x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u8(ptr: *const u8) -> uint8x16_t { - transmute(u8x16::splat(*ptr)) + transmute(u8x16::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_p64)"] @@ -19307,7 +19307,7 @@ pub unsafe fn vld1q_f32_x4(a: *const f32) -> float32x4x4_t { #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1_lane_f16(ptr: *const f16, src: float16x4_t) -> float16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_f16)"] @@ -19327,7 +19327,7 @@ pub unsafe fn vld1_lane_f16(ptr: *const f16, src: float16x4_t) #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1q_lane_f16(ptr: *const f16, src: float16x8_t) -> float16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_f32)"] @@ -19337,7 +19337,7 @@ pub unsafe fn vld1q_lane_f16(ptr: *const f16, src: float16x8_t) #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(ldr, LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19352,7 +19352,7 @@ pub unsafe fn vld1q_lane_f16(ptr: *const f16, src: float16x8_t) )] pub unsafe fn vld1_lane_f32(ptr: *const f32, src: float32x2_t) -> float32x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_p16)"] @@ -19377,7 +19377,7 @@ pub unsafe fn vld1_lane_f32(ptr: *const f32, src: float32x2_t) )] pub unsafe fn vld1_lane_p16(ptr: *const p16, src: poly16x4_t) -> poly16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_p8)"] @@ -19402,7 +19402,7 @@ pub unsafe fn vld1_lane_p16(ptr: *const p16, src: poly16x4_t) - )] pub unsafe fn vld1_lane_p8(ptr: *const p8, src: poly8x8_t) -> poly8x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s16)"] @@ -19427,7 +19427,7 @@ pub unsafe fn vld1_lane_p8(ptr: *const p8, src: poly8x8_t) -> p )] pub unsafe fn vld1_lane_s16(ptr: *const i16, src: int16x4_t) -> int16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s32)"] @@ -19452,7 +19452,7 @@ pub unsafe fn vld1_lane_s16(ptr: *const i16, src: int16x4_t) -> )] pub unsafe fn vld1_lane_s32(ptr: *const i32, src: int32x2_t) -> int32x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s64)"] @@ -19462,7 +19462,7 @@ pub unsafe fn vld1_lane_s32(ptr: *const i32, src: int32x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 0))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 0))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ldr, LANE = 0) @@ -19477,7 +19477,7 @@ pub unsafe fn vld1_lane_s32(ptr: *const i32, src: int32x2_t) -> )] pub unsafe fn vld1_lane_s64(ptr: *const i64, src: int64x1_t) -> int64x1_t { static_assert!(LANE == 0); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s8)"] @@ -19502,7 +19502,7 @@ pub unsafe fn vld1_lane_s64(ptr: *const i64, src: int64x1_t) -> )] pub unsafe fn vld1_lane_s8(ptr: *const i8, src: int8x8_t) -> int8x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u16)"] @@ -19527,7 +19527,7 @@ pub unsafe fn vld1_lane_s8(ptr: *const i8, src: int8x8_t) -> in )] pub unsafe fn vld1_lane_u16(ptr: *const u16, src: uint16x4_t) -> uint16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u32)"] @@ -19552,7 +19552,7 @@ pub unsafe fn vld1_lane_u16(ptr: *const u16, src: uint16x4_t) - )] pub unsafe fn vld1_lane_u32(ptr: *const u32, src: uint32x2_t) -> uint32x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u64)"] @@ -19562,7 +19562,7 @@ pub unsafe fn vld1_lane_u32(ptr: *const u32, src: uint32x2_t) - #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 0))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 0))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ldr, LANE = 0) @@ -19577,7 +19577,7 @@ pub unsafe fn vld1_lane_u32(ptr: *const u32, src: uint32x2_t) - )] pub unsafe fn vld1_lane_u64(ptr: *const u64, src: uint64x1_t) -> uint64x1_t { static_assert!(LANE == 0); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u8)"] @@ -19602,7 +19602,7 @@ pub unsafe fn vld1_lane_u64(ptr: *const u64, src: uint64x1_t) - )] pub unsafe fn vld1_lane_u8(ptr: *const u8, src: uint8x8_t) -> uint8x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_f32)"] @@ -19612,7 +19612,7 @@ pub unsafe fn vld1_lane_u8(ptr: *const u8, src: uint8x8_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 3))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(ldr, LANE = 3))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 3) @@ -19627,7 +19627,7 @@ pub unsafe fn vld1_lane_u8(ptr: *const u8, src: uint8x8_t) -> u )] pub unsafe fn vld1q_lane_f32(ptr: *const f32, src: float32x4_t) -> float32x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_p16)"] @@ -19652,7 +19652,7 @@ pub unsafe fn vld1q_lane_f32(ptr: *const f32, src: float32x4_t) )] pub unsafe fn vld1q_lane_p16(ptr: *const p16, src: poly16x8_t) -> poly16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_p8)"] @@ -19677,7 +19677,7 @@ pub unsafe fn vld1q_lane_p16(ptr: *const p16, src: poly16x8_t) )] pub unsafe fn vld1q_lane_p8(ptr: *const p8, src: poly8x16_t) -> poly8x16_t { static_assert_uimm_bits!(LANE, 4); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s16)"] @@ -19702,7 +19702,7 @@ pub unsafe fn vld1q_lane_p8(ptr: *const p8, src: poly8x16_t) -> )] pub unsafe fn vld1q_lane_s16(ptr: *const i16, src: int16x8_t) -> int16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s32)"] @@ -19727,7 +19727,7 @@ pub unsafe fn vld1q_lane_s16(ptr: *const i16, src: int16x8_t) - )] pub unsafe fn vld1q_lane_s32(ptr: *const i32, src: int32x4_t) -> int32x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s64)"] @@ -19737,7 +19737,7 @@ pub unsafe fn vld1q_lane_s32(ptr: *const i32, src: int32x4_t) - #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19752,7 +19752,7 @@ pub unsafe fn vld1q_lane_s32(ptr: *const i32, src: int32x4_t) - )] pub unsafe fn vld1q_lane_s64(ptr: *const i64, src: int64x2_t) -> int64x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s8)"] @@ -19777,7 +19777,7 @@ pub unsafe fn vld1q_lane_s64(ptr: *const i64, src: int64x2_t) - )] pub unsafe fn vld1q_lane_s8(ptr: *const i8, src: int8x16_t) -> int8x16_t { static_assert_uimm_bits!(LANE, 4); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u16)"] @@ -19802,7 +19802,7 @@ pub unsafe fn vld1q_lane_s8(ptr: *const i8, src: int8x16_t) -> )] pub unsafe fn vld1q_lane_u16(ptr: *const u16, src: uint16x8_t) -> uint16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u32)"] @@ -19827,7 +19827,7 @@ pub unsafe fn vld1q_lane_u16(ptr: *const u16, src: uint16x8_t) )] pub unsafe fn vld1q_lane_u32(ptr: *const u32, src: uint32x4_t) -> uint32x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u64)"] @@ -19837,7 +19837,7 @@ pub unsafe fn vld1q_lane_u32(ptr: *const u32, src: uint32x4_t) #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19852,7 +19852,7 @@ pub unsafe fn vld1q_lane_u32(ptr: *const u32, src: uint32x4_t) )] pub unsafe fn vld1q_lane_u64(ptr: *const u64, src: uint64x2_t) -> uint64x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u8)"] @@ -19877,7 +19877,7 @@ pub unsafe fn vld1q_lane_u64(ptr: *const u64, src: uint64x2_t) )] pub unsafe fn vld1q_lane_u8(ptr: *const u8, src: uint8x16_t) -> uint8x16_t { static_assert_uimm_bits!(LANE, 4); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_p64)"] @@ -19887,7 +19887,7 @@ pub unsafe fn vld1q_lane_u8(ptr: *const u8, src: uint8x16_t) -> #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 0))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 0))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ldr, LANE = 0) @@ -19902,7 +19902,7 @@ pub unsafe fn vld1q_lane_u8(ptr: *const u8, src: uint8x16_t) -> )] pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) -> poly64x1_t { static_assert!(LANE == 0); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_p64)"] @@ -19912,7 +19912,7 @@ pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) - #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19927,7 +19927,7 @@ pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) - )] pub unsafe fn vld1q_lane_p64(ptr: *const p64, src: poly64x2_t) -> poly64x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load multiple single-element structures to one, two, three, or four registers."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p64)"] @@ -21734,7 +21734,7 @@ unsafe fn vld1q_v8f16(a: *const i8, b: i32) -> float16x8_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -58579,7 +58579,7 @@ pub unsafe fn vst1q_f32_x4(a: *mut f32, b: float32x4x4_t) { #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vst1_lane_f16(a: *mut f16, b: float16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_f16)"] @@ -58599,7 +58599,7 @@ pub unsafe fn vst1_lane_f16(a: *mut f16, b: float16x4_t) { #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vst1q_lane_f16(a: *mut f16, b: float16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_f32)"] @@ -58624,7 +58624,7 @@ pub unsafe fn vst1q_lane_f16(a: *mut f16, b: float16x8_t) { )] pub unsafe fn vst1_lane_f32(a: *mut f32, b: float32x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_f32)"] @@ -58649,7 +58649,7 @@ pub unsafe fn vst1_lane_f32(a: *mut f32, b: float32x2_t) { )] pub unsafe fn vst1q_lane_f32(a: *mut f32, b: float32x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_s8)"] @@ -58674,7 +58674,7 @@ pub unsafe fn vst1q_lane_f32(a: *mut f32, b: float32x4_t) { )] pub unsafe fn vst1_lane_s8(a: *mut i8, b: int8x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_s8)"] @@ -58699,7 +58699,7 @@ pub unsafe fn vst1_lane_s8(a: *mut i8, b: int8x8_t) { )] pub unsafe fn vst1q_lane_s8(a: *mut i8, b: int8x16_t) { static_assert_uimm_bits!(LANE, 4); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_s16)"] @@ -58724,7 +58724,7 @@ pub unsafe fn vst1q_lane_s8(a: *mut i8, b: int8x16_t) { )] pub unsafe fn vst1_lane_s16(a: *mut i16, b: int16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_s16)"] @@ -58749,7 +58749,7 @@ pub unsafe fn vst1_lane_s16(a: *mut i16, b: int16x4_t) { )] pub unsafe fn vst1q_lane_s16(a: *mut i16, b: int16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_s32)"] @@ -58774,7 +58774,7 @@ pub unsafe fn vst1q_lane_s16(a: *mut i16, b: int16x8_t) { )] pub unsafe fn vst1_lane_s32(a: *mut i32, b: int32x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_s32)"] @@ -58799,7 +58799,7 @@ pub unsafe fn vst1_lane_s32(a: *mut i32, b: int32x2_t) { )] pub unsafe fn vst1q_lane_s32(a: *mut i32, b: int32x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_s64)"] @@ -58824,7 +58824,7 @@ pub unsafe fn vst1q_lane_s32(a: *mut i32, b: int32x4_t) { )] pub unsafe fn vst1q_lane_s64(a: *mut i64, b: int64x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_u8)"] @@ -58849,7 +58849,7 @@ pub unsafe fn vst1q_lane_s64(a: *mut i64, b: int64x2_t) { )] pub unsafe fn vst1_lane_u8(a: *mut u8, b: uint8x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_u8)"] @@ -58874,7 +58874,7 @@ pub unsafe fn vst1_lane_u8(a: *mut u8, b: uint8x8_t) { )] pub unsafe fn vst1q_lane_u8(a: *mut u8, b: uint8x16_t) { static_assert_uimm_bits!(LANE, 4); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_u16)"] @@ -58899,7 +58899,7 @@ pub unsafe fn vst1q_lane_u8(a: *mut u8, b: uint8x16_t) { )] pub unsafe fn vst1_lane_u16(a: *mut u16, b: uint16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_u16)"] @@ -58924,7 +58924,7 @@ pub unsafe fn vst1_lane_u16(a: *mut u16, b: uint16x4_t) { )] pub unsafe fn vst1q_lane_u16(a: *mut u16, b: uint16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_u32)"] @@ -58949,7 +58949,7 @@ pub unsafe fn vst1q_lane_u16(a: *mut u16, b: uint16x8_t) { )] pub unsafe fn vst1_lane_u32(a: *mut u32, b: uint32x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_u32)"] @@ -58974,7 +58974,7 @@ pub unsafe fn vst1_lane_u32(a: *mut u32, b: uint32x2_t) { )] pub unsafe fn vst1q_lane_u32(a: *mut u32, b: uint32x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_u64)"] @@ -58999,7 +58999,7 @@ pub unsafe fn vst1q_lane_u32(a: *mut u32, b: uint32x4_t) { )] pub unsafe fn vst1q_lane_u64(a: *mut u64, b: uint64x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_p8)"] @@ -59024,7 +59024,7 @@ pub unsafe fn vst1q_lane_u64(a: *mut u64, b: uint64x2_t) { )] pub unsafe fn vst1_lane_p8(a: *mut p8, b: poly8x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_p8)"] @@ -59049,7 +59049,7 @@ pub unsafe fn vst1_lane_p8(a: *mut p8, b: poly8x8_t) { )] pub unsafe fn vst1q_lane_p8(a: *mut p8, b: poly8x16_t) { static_assert_uimm_bits!(LANE, 4); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_p16)"] @@ -59074,7 +59074,7 @@ pub unsafe fn vst1q_lane_p8(a: *mut p8, b: poly8x16_t) { )] pub unsafe fn vst1_lane_p16(a: *mut p16, b: poly16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_p16)"] @@ -59099,7 +59099,7 @@ pub unsafe fn vst1_lane_p16(a: *mut p16, b: poly16x4_t) { )] pub unsafe fn vst1q_lane_p16(a: *mut p16, b: poly16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_p64)"] @@ -59124,7 +59124,7 @@ pub unsafe fn vst1q_lane_p16(a: *mut p16, b: poly16x8_t) { )] pub unsafe fn vst1_lane_p64(a: *mut p64, b: poly64x1_t) { static_assert!(LANE == 0); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_s64)"] @@ -59149,7 +59149,7 @@ pub unsafe fn vst1_lane_p64(a: *mut p64, b: poly64x1_t) { )] pub unsafe fn vst1_lane_s64(a: *mut i64, b: int64x1_t) { static_assert!(LANE == 0); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_u64)"] @@ -59174,7 +59174,7 @@ pub unsafe fn vst1_lane_s64(a: *mut i64, b: int64x1_t) { )] pub unsafe fn vst1_lane_u64(a: *mut u64, b: uint64x1_t) { static_assert!(LANE == 0); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_p64_x2)"] @@ -61181,7 +61181,7 @@ unsafe fn vst1q_v8f16(addr: *const i8, val: float16x8_t, align: i32) { )] pub unsafe fn vst1q_lane_p64(a: *mut p64, b: poly64x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple 2-element structures from two registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst2_f16)"] diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs index 70a37f7c05dad..a4db10f7c1d26 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs @@ -223,3 +223,65 @@ fn test_vld1q_f32() { let r = unsafe { f32x4::from(vld1q_f32(a[1..].as_ptr())) }; assert_eq!(r, e) } + +#[simd_test(enable = "neon")] +fn test_vld1q_lane_u32_unaligned() { + // ld1 single-lane loads impose no alignment requirement: read from an odd byte offset. + let a: [u8; 5] = [0, 1, 2, 3, 4]; + let e = u32::from_ne_bytes([1, 2, 3, 4]); + let src = u32x4::new(10, 11, 12, 13); + let r = unsafe { + u32x4::from(vld1q_lane_u32::<2>( + a.as_ptr().add(1) as *const u32, + src.into(), + )) + }; + assert_eq!(r, u32x4::new(10, 11, e, 13)); +} + +#[simd_test(enable = "neon")] +fn test_vld1q_lane_u64_unaligned() { + let a: [u8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e = u64::from_ne_bytes([1, 2, 3, 4, 5, 6, 7, 8]); + let src = u64x2::new(10, 11); + let r = unsafe { + u64x2::from(vld1q_lane_u64::<1>( + a.as_ptr().add(1) as *const u64, + src.into(), + )) + }; + assert_eq!(r, u64x2::new(10, e)); +} + +#[simd_test(enable = "neon")] +fn test_vld1q_lane_f32_unaligned() { + // Float loads legalize differently from integer ones under low alignment + // (armv7 uses ldr + vmov), so the type class needs its own coverage. + let a: [u8; 5] = [0, 1, 2, 3, 4]; + let e = f32::from_ne_bytes([1, 2, 3, 4]); + let src = f32x4::new(10., 11., 12., 13.); + let r = unsafe { + f32x4::from(vld1q_lane_f32::<2>( + a.as_ptr().add(1) as *const f32, + src.into(), + )) + }; + assert_eq!(r, f32x4::new(10., 11., e, 13.)); +} + +#[simd_test(enable = "neon")] +fn test_vld1q_dup_u32_unaligned() { + // ld1r replicate loads impose no alignment requirement either. + let a: [u8; 5] = [0, 1, 2, 3, 4]; + let e = u32::from_ne_bytes([1, 2, 3, 4]); + let r = unsafe { u32x4::from(vld1q_dup_u32(a.as_ptr().add(1) as *const u32)) }; + assert_eq!(r, u32x4::new(e, e, e, e)); +} + +#[simd_test(enable = "neon")] +fn test_vld1q_dup_u64_unaligned() { + let a: [u8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e = u64::from_ne_bytes([1, 2, 3, 4, 5, 6, 7, 8]); + let r = unsafe { u64x2::from(vld1q_dup_u64(a.as_ptr().add(1) as *const u64)) }; + assert_eq!(r, u64x2::new(e, e)); +} diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs index 6eb60e4c78bc8..68df3ec944abd 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs @@ -473,3 +473,27 @@ fn test_vst1q_f32() { assert_eq!(vals[3], 3.); assert_eq!(vals[4], 4.); } + +#[simd_test(enable = "neon")] +fn test_vst1q_lane_u32_unaligned() { + // st1 single-lane stores impose no alignment requirement: write to an odd byte offset. + let mut vals = [0_u8; 5]; + let a = u32x4::new(1, 2, 3, 4); + unsafe { + vst1q_lane_u32::<2>(vals.as_mut_ptr().add(1) as *mut u32, a.into()); + } + assert_eq!(vals[0], 0); + assert_eq!(u32::from_ne_bytes([vals[1], vals[2], vals[3], vals[4]]), 3); +} + +#[simd_test(enable = "neon")] +fn test_vst1q_lane_u64_unaligned() { + let mut vals = [0_u8; 9]; + let a = u64x2::new(1, 2); + unsafe { + vst1q_lane_u64::<1>(vals.as_mut_ptr().add(1) as *mut u64, a.into()); + } + assert_eq!(vals[0], 0); + let stored: [u8; 8] = vals[1..9].try_into().unwrap(); + assert_eq!(u64::from_ne_bytes(stored), 2); +} diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 55163fffedd78..513ecc5e5489d 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -42,7 +42,15 @@ clflushopt_target_feature, min_adt_const_params )] -#![cfg_attr(test, feature(test, abi_vectorcall, stdarch_internal))] +#![cfg_attr( + test, + feature( + test, + abi_vectorcall, + stdarch_internal, + cfg_target_has_reliable_f16_f128 + ) +)] #![deny(clippy::missing_inline_in_public_items)] #![allow( clippy::identity_op, diff --git a/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs b/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs index f481a159eb632..cfc4aced34173 100644 --- a/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs +++ b/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs @@ -6,8 +6,8 @@ // OUT_DIR=`pwd`/crates/core_arch cargo run -p stdarch-gen-loongarch -- crates/stdarch-gen-loongarch/lasx.spec // ``` -use crate::mem::transmute; use super::super::*; +use crate::mem::transmute; #[allow(improper_ctypes)] unsafe extern "llvm-intrinsic" { @@ -3033,168 +3033,312 @@ pub fn lasx_xvhsubw_qu_du(a: m256i, b: m256i) -> m256i { #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_q_d(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_q_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_q_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_d_w(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_d_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_d_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_w_h(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_w_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_w_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_h_b(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_h_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_h_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_q_du(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_q_du(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_q_du( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_d_wu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_d_wu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_d_wu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_w_hu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_w_hu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_w_hu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_h_bu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_h_bu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_h_bu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_q_d(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_q_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_q_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_d_w(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_d_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_d_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_w_h(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_w_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_w_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_h_b(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_h_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_h_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_q_du(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_q_du(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_q_du( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_d_wu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_d_wu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_d_wu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_w_hu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_w_hu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_w_hu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_h_bu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_h_bu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_h_bu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_q_du_d(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_q_du_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_q_du_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_d_wu_w(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_d_wu_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_d_wu_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_w_hu_h(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_w_hu_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_w_hu_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_h_bu_b(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_h_bu_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_h_bu_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_q_du_d(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_q_du_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_q_du_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_d_wu_w(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_d_wu_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_d_wu_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_w_hu_h(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_w_hu_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_w_hu_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_h_bu_b(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_h_bu_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_h_bu_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] diff --git a/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs b/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs index 7915ef07d68e7..aa4e31ce8da6c 100644 --- a/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs +++ b/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs @@ -6,8 +6,8 @@ // OUT_DIR=`pwd`/crates/core_arch cargo run -p stdarch-gen-loongarch -- crates/stdarch-gen-loongarch/lsx.spec // ``` -use crate::mem::transmute; use super::super::*; +use crate::mem::transmute; #[allow(improper_ctypes)] unsafe extern "llvm-intrinsic" { @@ -2747,21 +2747,39 @@ pub fn lsx_vmaddwev_h_b(a: m128i, b: m128i, c: m128i) -> m128i { #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_d_wu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_d_wu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_d_wu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_w_hu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_w_hu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_w_hu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_h_bu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_h_bu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_h_bu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] @@ -2789,63 +2807,117 @@ pub fn lsx_vmaddwod_h_b(a: m128i, b: m128i, c: m128i) -> m128i { #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_d_wu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_d_wu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_d_wu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_w_hu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_w_hu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_w_hu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_h_bu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_h_bu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_h_bu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_d_wu_w(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_d_wu_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_d_wu_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_w_hu_h(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_w_hu_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_w_hu_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_h_bu_b(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_h_bu_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_h_bu_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_d_wu_w(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_d_wu_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_d_wu_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_w_hu_h(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_w_hu_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_w_hu_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_h_bu_b(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_h_bu_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_h_bu_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] @@ -2866,28 +2938,52 @@ pub fn lsx_vmaddwod_q_d(a: m128i, b: m128i, c: m128i) -> m128i { #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_q_du(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_q_du(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_q_du( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_q_du(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_q_du(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_q_du( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_q_du_d(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_q_du_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_q_du_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_q_du_d(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_q_du_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_q_du_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] diff --git a/library/stdarch/crates/core_arch/src/s390x/vector.rs b/library/stdarch/crates/core_arch/src/s390x/vector.rs index 6703691f080b2..8fd9fd83a64cd 100644 --- a/library/stdarch/crates/core_arch/src/s390x/vector.rs +++ b/library/stdarch/crates/core_arch/src/s390x/vector.rs @@ -122,8 +122,6 @@ unsafe extern "llvm-intrinsic" { #[link_name = "llvm.s390.vsrlb"] fn vsrlb(a: vector_signed_char, b: vector_signed_char) -> vector_signed_char; #[link_name = "llvm.s390.vslb"] fn vslb(a: vector_signed_char, b: vector_signed_char) -> vector_signed_char; - #[link_name = "llvm.s390.vsrd"] fn vsrd(a: i8x16, b: i8x16, c: u32) -> i8x16; - #[link_name = "llvm.s390.verimb"] fn verimb(a: vector_signed_char, b: vector_signed_char, c: vector_signed_char, d: i32) -> vector_signed_char; #[link_name = "llvm.s390.verimh"] fn verimh(a: vector_signed_short, b: vector_signed_short, c: vector_signed_short, d: i32) -> vector_signed_short; #[link_name = "llvm.s390.verimf"] fn verimf(a: vector_signed_int, b: vector_signed_int, c: vector_signed_int, d: i32) -> vector_signed_int; @@ -140,9 +138,6 @@ unsafe extern "llvm-intrinsic" { #[link_name = "llvm.s390.vsumqf"] fn vsumqf(a: vector_unsigned_int, b: vector_unsigned_int) -> u128; #[link_name = "llvm.s390.vsumqg"] fn vsumqg(a: vector_unsigned_long_long, b: vector_unsigned_long_long) -> u128; - #[link_name = "llvm.s390.vaccq"] fn vaccq(a: u128, b: u128) -> u128; - #[link_name = "llvm.s390.vacccq"] fn vacccq(a: u128, b: u128, c: u128) -> u128; - #[link_name = "llvm.s390.vscbiq"] fn vscbiq(a: u128, b: u128) -> u128; #[link_name = "llvm.s390.vsbiq"] fn vsbiq(a: u128, b: u128, c: u128) -> u128; #[link_name = "llvm.s390.vsbcbiq"] fn vsbcbiq(a: u128, b: u128, c: u128) -> u128; @@ -3664,12 +3659,7 @@ mod sealed { #[target_feature(enable = "vector-enhancements-2")] unsafe fn vec_srdb(self, b: Self) -> Self { static_assert_uimm_bits!(C, 3); - transmute(vsrd(transmute(self), transmute(b), C)) - // FIXME(llvm): https://github.com/llvm/llvm-project/issues/129955#issuecomment-3207488190 - // LLVM currently rewrites `fshr` to `fshl`, and the logic in the s390x - // backend cannot deal with that yet. - // #[link_name = "llvm.fshr.i128"] fn fshr_i128(a: u128, b: u128, c: u128) -> u128; - // transmute(fshr_i128(transmute(self), transmute(b), const { C as u128 })) + transmute(u128::funnel_shr(transmute(self), transmute(b), C)) } } )* @@ -4849,9 +4839,7 @@ pub unsafe fn vec_addc_u128( ) -> vector_unsigned_char { let a: u128 = transmute(a); let b: u128 = transmute(b); - // FIXME(llvm) https://github.com/llvm/llvm-project/pull/153557 - // transmute(a.overflowing_add(b).1 as u128) - transmute(vaccq(a, b)) + transmute(a.overflowing_add(b).1 as u128) } /// Vector Add With Carry unsigned 128-bits @@ -4886,10 +4874,8 @@ pub unsafe fn vec_addec_u128( let a: u128 = transmute(a); let b: u128 = transmute(b); let c: u128 = transmute(c); - // FIXME(llvm) https://github.com/llvm/llvm-project/pull/153557 - // let (_d, carry) = a.carrying_add(b, c & 1 != 0); - // transmute(carry as u128) - transmute(vacccq(a, b, c)) + let (_d, carry) = a.carrying_add(b, c & 1 != 0); + transmute(carry as u128) } /// Vector Subtract with Carryout diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 333f38e5474cc..7ad45421cf89f 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -5142,10 +5142,24 @@ mod tests { #[simd_test(enable = "avx2")] fn test_mm_sllv_epi64() { - let a = _mm_set1_epi64x(2); - let b = _mm_set1_epi64x(1); + let a = _mm_set_epi64x(2, 3); + let b = _mm_set_epi64x(1, 2); let r = _mm_sllv_epi64(a, b); - let e = _mm_set1_epi64x(4); + // Compare with the scalar version of the same computation. + let e = _mm_set_epi64x(2i64.unbounded_shl(1), 3i64.unbounded_shl(2)); + assert_eq_m128i(r, e); + // Compare with hardcoded output. + let e = _mm_set_epi64x(4, 12); + assert_eq_m128i(r, e); + + // The shift has unbounded semantics: if the shift amount + // is >= the number of bits the result is 0. + let a = _mm_set_epi64x(1, 2); + let b = _mm_set_epi64x(64, 65); + let r = _mm_sllv_epi64(a, b); + let e = _mm_set_epi64x(1i64.unbounded_shl(64), 2i64.unbounded_shl(65)); + assert_eq_m128i(r, e); + let e = _mm_set_epi64x(0, 0); assert_eq_m128i(r, e); } @@ -5192,10 +5206,27 @@ mod tests { #[simd_test(enable = "avx2")] fn test_mm_srav_epi32() { - let a = _mm_set1_epi32(4); - let count = _mm_set1_epi32(1); - let r = _mm_srav_epi32(a, count); - let e = _mm_set1_epi32(2); + let a = _mm_set_epi32(16, -32, 64, -128); + let b = _mm_set_epi32(4, 3, 2, 1); + let r = _mm_srav_epi32(a, b); + let e = _mm_set_epi32(1, -4, 16, -64); + assert_eq_m128i(r, e); + + // The shift has unbounded semantics: if the shift amount + // is >= the number of bits the result is -1. + let a = _mm_set_epi32(-16, -32, -64, -128); + let b = _mm_set_epi32(31, 32, 33, 0); + let r = _mm_srav_epi32(a, b); + // Compare with the scalar version of the same computation. + let e = _mm_set_epi32( + (-16i32).unbounded_shr(31), + (-32i32).unbounded_shr(32), + (-64i32).unbounded_shr(33), + (-128i32).unbounded_shr(0), + ); + assert_eq_m128i(r, e); + // Compare with hardcoded output. + let e = _mm_set_epi32(-1, -1, -1, -128); assert_eq_m128i(r, e); } @@ -5296,10 +5327,24 @@ mod tests { #[simd_test(enable = "avx2")] fn test_mm_srlv_epi64() { - let a = _mm_set1_epi64x(2); - let count = _mm_set1_epi64x(1); - let r = _mm_srlv_epi64(a, count); - let e = _mm_set1_epi64x(1); + let a = _mm_set_epi64x(4, 8); + let b = _mm_set_epi64x(2, 1); + let r = _mm_srlv_epi64(a, b); + // Compare with the scalar version of the same computation. + let e = _mm_set_epi64x(4i64.unbounded_shr(2), 8i64.unbounded_shr(1)); + assert_eq_m128i(r, e); + // Compare with hardcoded output. + let e = _mm_set_epi64x(1, 4); + assert_eq_m128i(r, e); + + // The shift has unbounded semantics: if the shift amount + // is >= the number of bits the result is 0. + let a = _mm_set_epi64x(i64::MAX, i64::MAX); + let b = _mm_set_epi64x(64, 65); + let r = _mm_sllv_epi64(a, b); + let e = _mm_set_epi64x(i64::MAX.unbounded_shr(64), i64::MAX.unbounded_shr(65)); + assert_eq_m128i(r, e); + let e = _mm_set_epi64x(0, 0); assert_eq_m128i(r, e); } diff --git a/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs b/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs index 869f577a55905..d54c222eb7ccf 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs @@ -16837,6 +16837,7 @@ unsafe extern "llvm-intrinsic" { } #[cfg(test)] +#[cfg(target_has_reliable_f16)] mod tests { use crate::core_arch::assert_eq_const as assert_eq; use crate::core_arch::x86::*; diff --git a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs index 832384b11e68b..9c261784553bd 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs @@ -9583,7 +9583,7 @@ mod tests { let a = _mm_set_epi64x(-1, -2); let b = _mm_set_epi64x(64, 65); let r = _mm_srav_epi64(a, b); - let e = _mm_set_epi64x((-1i64).unbounded_shl(64), (-2i64).unbounded_shl(65)); + let e = _mm_set_epi64x((-1i64).unbounded_shr(64), (-2i64).unbounded_shr(65)); assert_eq_m128i(r, e); let e = _mm_set_epi64x(-1, -1); assert_eq_m128i(r, e); diff --git a/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs b/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs index f8d21e3f9d7fd..5b26fc9f45426 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs @@ -227,6 +227,7 @@ unsafe extern "llvm-intrinsic" { } #[cfg(test)] +#[cfg(target_has_reliable_f16)] mod tests { use crate::core_arch::{x86::*, x86_64::*}; use stdarch_test::simd_test; diff --git a/library/stdarch/crates/intrinsic-test/missing_loongarch64_clang.txt b/library/stdarch/crates/intrinsic-test/missing_loongarch64_clang.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/library/stdarch/crates/intrinsic-test/missing_loongarch64_common.txt b/library/stdarch/crates/intrinsic-test/missing_loongarch64_common.txt new file mode 100644 index 0000000000000..5817247c2f4d2 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/missing_loongarch64_common.txt @@ -0,0 +1,31 @@ +# Missing in old c compiler +lasx_concat_128 +lasx_concat_128_d +lasx_concat_128_s +lasx_extract_128_hi +lasx_extract_128_lo +lasx_extract_128_hi_d +lasx_extract_128_lo_d +lasx_extract_128_hi_s +lasx_extract_128_lo_s +lasx_insert_128_hi +lasx_insert_128_lo +lasx_insert_128_hi_d +lasx_insert_128_lo_d +lasx_insert_128_hi_s +lasx_insert_128_lo_s + +# Missing in old qemu +lasx_xvfrecipe_d +lasx_xvfrecipe_s +lasx_xvfrsqrte_d +lasx_xvfrsqrte_s +lsx_vfrecipe_d +lsx_vfrecipe_s +lsx_vfrsqrte_d +lsx_vfrsqrte_s + +# Top bits are undefined, unclear how to test these +lasx_cast_128 +lasx_cast_128_d +lasx_cast_128_s diff --git a/library/stdarch/crates/intrinsic-test/missing_loongarch64_gcc.txt b/library/stdarch/crates/intrinsic-test/missing_loongarch64_gcc.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs index 9c2d0f336a7aa..5e892c613464a 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs @@ -37,6 +37,8 @@ impl SupportedArchitecture for Arm { "#; const RUST_PRELUDE: &str = RUST_PRELUDE; + const C_NAME_PREFIX: &str = ""; + fn c_compiler_flags(&self, cli_options: &ProcessedCli) -> Vec<&str> { // GCC uses an extra `-` in the arch name let big_endian = cli_options.target.starts_with("aarch64_be"); 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 bbff7a91b6c41..a749afd17d367 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs @@ -1,5 +1,6 @@ use itertools::Itertools; +use crate::common::imm_value_to_ident; use crate::common::{SupportedArchitecture, intrinsic::Intrinsic}; use super::intrinsic_helpers::TypeDefinition; @@ -37,13 +38,18 @@ pub fn write_wrapper_c( fmt(&format_args!( " void {name}_wrapper{imm_arglist}({return_ty}* __dst{arglist}) {{ - *__dst = {name}({params}); + *__dst = {prefix}{name}({params}); }}", return_ty = intrinsic.results.c_type(), + prefix = A::C_NAME_PREFIX, name = intrinsic.name, - imm_arglist = imm_values - .iter() - .format_with("", |i, fmt| fmt(&format_args!("_{i}"))), + imm_arglist = + imm_values + .iter() + .format_with("", |i, fmt| fmt(&format_args!( + "_{}", + imm_value_to_ident(i) + ))), arglist = intrinsic.arguments.as_non_imm_arglist_c(), params = intrinsic.arguments.as_call_params_c(&imm_values) )) 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 bfe37edbcfe43..f319418b49c7f 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs @@ -4,6 +4,7 @@ use itertools::Itertools; use super::intrinsic_helpers::TypeDefinition; use crate::common::cli::{CcArgStyle, ProcessedCli}; +use crate::common::imm_value_to_ident; use crate::common::intrinsic::Intrinsic; use crate::common::intrinsic_helpers::TypeKind; use crate::common::values::{test_values_array_name, test_values_array_static}; @@ -276,7 +277,7 @@ for (id, rust, c) in specializations {{ } }) .join(","), - c_const_args = imm_values.iter().join("_"), + c_const_args = imm_values.iter().map(imm_value_to_ident).join("_"), )) } }), @@ -343,9 +344,13 @@ unsafe extern "C" {{ "fn {name}_wrapper{imm_arglist}(__dst: *mut {return_ty}{arglist});", return_ty = intrinsic.results.rust_type(), name = intrinsic.name, - imm_arglist = imm_values - .iter() - .format_with("", |i, fmt| fmt(&format_args!("_{i}"))), + imm_arglist = + imm_values + .iter() + .format_with("", |i, fmt| fmt(&format_args!( + "_{}", + imm_value_to_ident(i) + ))), arglist = intrinsic.arguments.as_non_imm_arglist_rust(), )) })) diff --git a/library/stdarch/crates/intrinsic-test/src/common/mod.rs b/library/stdarch/crates/intrinsic-test/src/common/mod.rs index b476ad477ca36..9cde80daff76c 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/mod.rs @@ -49,6 +49,10 @@ pub trait SupportedArchitecture: Sized { const C_PRELUDE: &str; const RUST_PRELUDE: &str; + /// Per-architecture prefix used to convert a Rust intrinsic name to the + /// corresponding C intrinsic name by prepending it to the Rust name. + const C_NAME_PREFIX: &str; + fn c_compiler_flags(&self, cli_options: &ProcessedCli) -> Vec<&str>; fn generate_c_file(&self) { @@ -138,3 +142,8 @@ pub fn manual_chunk(intrinsic_count: usize) -> (usize, usize) { let number_of_chunks = intrinsic_count.div_ceil(max_intrinsics_per_chunk); (max_intrinsics_per_chunk, number_of_chunks) } + +pub fn imm_value_to_ident(value: impl std::fmt::Display) -> String { + let value = value.to_string(); + value.replace('-', "neg") +} diff --git a/library/stdarch/crates/intrinsic-test/src/loongarch/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/loongarch/intrinsic.rs new file mode 100644 index 0000000000000..f8ebb3e7ab34c --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/loongarch/intrinsic.rs @@ -0,0 +1,19 @@ +use crate::common::intrinsic_helpers::IntrinsicType; +use std::ops::{Deref, DerefMut}; + +#[derive(Debug, Clone, PartialEq)] +pub struct LoongArchType(pub IntrinsicType); + +impl Deref for LoongArchType { + type Target = IntrinsicType; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for LoongArchType { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} diff --git a/library/stdarch/crates/intrinsic-test/src/loongarch/mod.rs b/library/stdarch/crates/intrinsic-test/src/loongarch/mod.rs new file mode 100644 index 0000000000000..00cff20a0f083 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/loongarch/mod.rs @@ -0,0 +1,139 @@ +mod intrinsic; +mod parser; +mod types; + +use std::path::Path; + +use crate::common::SupportedArchitecture; +use crate::common::cli::ProcessedCli; +use crate::common::intrinsic::Intrinsic; +use crate::common::intrinsic_helpers::TypeKind; +use intrinsic::LoongArchType; +use parser::get_intrinsics; + +#[derive(PartialEq)] +pub struct LoongArch { + intrinsics: Vec>, +} + +impl SupportedArchitecture for LoongArch { + type Type = LoongArchType; + + fn intrinsics(&self) -> &[Intrinsic] { + &self.intrinsics + } + + const NOTICE: &str = r#" +// This is a transient test file, not intended for distribution. Some aspects of the +// test are derived from LoongArch specification files, published under the same license as the +// `intrinsic-test` crate. +"#; + + const C_PRELUDE: &str = r#" +#include +#include +"#; + const RUST_PRELUDE: &str = RUST_PRELUDE; + + const C_NAME_PREFIX: &str = "__"; + + fn c_compiler_flags(&self, _cli_options: &ProcessedCli) -> Vec<&str> { + let mut flags = vec!["-mlsx"]; + if self + .intrinsics + .iter() + .any(|intrinsic| intrinsic.extension == "LASX") + { + flags.push("-mlasx"); + } + if self.intrinsics.iter().any(|intrinsic| { + intrinsic.name.contains("frecipe") || intrinsic.name.contains("frsqrte") + }) { + flags.push("-mfrecipe"); + } + flags + } + + fn create(cli_options: &ProcessedCli) -> Self { + let mut intrinsics = + load_intrinsics(&cli_options.filename).expect("Error parsing input file"); + + intrinsics.sort_by(|a, b| a.name.cmp(&b.name)); + intrinsics.dedup_by(|a, b| { + a.name == b.name && a.results == b.results && a.arguments == b.arguments + }); + + let intrinsics = intrinsics + .into_iter() + // Skip intrinsics that don't return a value. + .filter(|intrinsic| intrinsic.results.kind() != TypeKind::Void) + .filter(|intrinsic| !intrinsic.arguments.args.is_empty()) + // Skip pointers for now, we would probably need to look at the return + // type to work out how many elements we need to point to. + .filter(|intrinsic| !intrinsic.arguments.iter().any(|arg| arg.is_ptr())) + // Skip intrinsics from `--skip` + .filter(|intrinsic| !cli_options.skip.contains(&intrinsic.name)) + .collect::>(); + + let sample_percentage: usize = cli_options.sample_percentage as usize; + let sample_size = (intrinsics.len() * sample_percentage) / 100; + let intrinsics = intrinsics.into_iter().take(sample_size).collect(); + + Self { intrinsics } + } + + fn predicate_function(_: u32) -> String { + unimplemented!("no scalable vectors on LoongArch") + } +} + +fn load_intrinsics(path: &Path) -> Result>, Box> { + if path.is_dir() { + let mut intrinsics = Vec::new(); + for spec in ["lsx.spec", "lasx.spec"] { + let spec_path = path.join(spec); + if spec_path.exists() { + intrinsics.extend(get_intrinsics(&spec_path)?); + } + } + return Ok(intrinsics); + } + + get_intrinsics(path) +} + +const RUST_PRELUDE: &str = r#" +#![feature(stdarch_loongarch)] + +use core_arch::arch::loongarch64::*; + +#[inline] +unsafe fn lsx_vld_to_m128i(mem_addr: *const i8) -> m128i { + lsx_vld::<0>(mem_addr) +} + +#[inline] +unsafe fn lsx_vld_to_m128(mem_addr: *const i8) -> m128 { + core::mem::transmute(lsx_vld::<0>(mem_addr)) +} + +#[inline] +unsafe fn lsx_vld_to_m128d(mem_addr: *const i8) -> m128d { + core::mem::transmute(lsx_vld::<0>(mem_addr)) +} + +#[inline] +unsafe fn lasx_xvld_to_m256i(mem_addr: *const i8) -> m256i { + lasx_xvld::<0>(mem_addr) +} + +#[inline] +unsafe fn lasx_xvld_to_m256(mem_addr: *const i8) -> m256 { + core::mem::transmute(lasx_xvld::<0>(mem_addr)) +} + +#[inline] +unsafe fn lasx_xvld_to_m256d(mem_addr: *const i8) -> m256d { + core::mem::transmute(lasx_xvld::<0>(mem_addr)) +} +"#; diff --git a/library/stdarch/crates/intrinsic-test/src/loongarch/parser.rs b/library/stdarch/crates/intrinsic-test/src/loongarch/parser.rs new file mode 100644 index 0000000000000..ecb5d1ab3e8df --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/loongarch/parser.rs @@ -0,0 +1,179 @@ +use std::path::Path; + +use super::intrinsic::LoongArchType; +use super::types::parse_intrinsic_type; +use crate::common::argument::{Argument, ArgumentList}; +use crate::common::constraint::Constraint; +use crate::common::intrinsic::Intrinsic; +use crate::loongarch::LoongArch; + +pub fn get_intrinsics( + filename: &Path, +) -> Result>, Box> { + parse_spec_file(filename) +} + +fn parse_spec_file( + filename: &Path, +) -> Result>, Box> { + let contents = std::fs::read_to_string(filename)?; + parse_spec_contents(&contents) +} + +fn parse_spec_contents( + contents: &str, +) -> Result>, Box> { + let mut intrinsics = Vec::new(); + let mut record = Vec::new(); + + for line in contents.lines().chain(std::iter::once("")) { + let line = line.trim(); + if line.is_empty() { + if !record.is_empty() { + if let Some(intrinsic) = parse_record(&record)? { + intrinsics.push(intrinsic); + } + record.clear(); + } + continue; + } + record.push(line); + } + + Ok(intrinsics) +} + +fn parse_record( + record: &[&str], +) -> Result>, Box> { + let mut name = None; + let mut asm_formats = Vec::new(); + let mut data_types = None; + + for line in record { + if let Some(value) = line.strip_prefix("name = ") { + name = Some(value.to_string()); + } else if let Some(value) = line.strip_prefix("asm-fmts = ") { + asm_formats = value + .split(',') + .map(|part| part.trim().to_string()) + .collect(); + } else if let Some(value) = line.strip_prefix("data-types = ") { + data_types = Some(value); + } + } + + let Some(data_types) = data_types else { + return Ok(None); + }; + + let name = name.ok_or("missing name before data-types")?; + Ok(Some(parse_intrinsic(&name, &asm_formats, data_types)?)) +} + +fn parse_intrinsic( + name: &str, + asm_formats: &[String], + data_types: &str, +) -> Result, Box> { + let data_types = data_types + .split(',') + .map(|value| value.trim()) + .filter(|value| !value.is_empty()) + .collect::>(); + let Some((result_type, argument_types)) = data_types.split_first() else { + return Err("missing data-types for intrinsic".into()); + }; + let result = LoongArchType(parse_intrinsic_type(result_type)?); + let asm_offset = asm_formats + .len() + .checked_sub(argument_types.len()) + .ok_or_else(|| format!("{name}: fewer asm formats than arguments"))?; + let arguments = argument_types + .iter() + .enumerate() + .map(|(pos, data_type)| { + let constraint = asm_formats + .get(pos + asm_offset) + .and_then(|format| parse_constraint(name, format)); + let mut ty = LoongArchType(parse_intrinsic_type(data_type)?); + if constraint.is_some() { + ty.constant = true; + } + Ok(Argument::new( + pos, + format!("arg_{pos}"), + ty, + constraint, + false, + )) + }) + .collect::, String>>()?; + + Ok(Intrinsic { + name: name.to_string(), + arguments: ArgumentList { args: arguments }, + results: result, + arch_tags: Vec::new(), + extension: extension_for(name)?.to_string(), + }) +} + +fn parse_constraint(name: &str, asm_format: &str) -> Option { + if let Some(cons) = special_constraint(name) { + return Some(cons); + } + if let Some(bits) = asm_format.strip_prefix("ui") { + return Some(unsigned_constraint(bits.parse::().ok()?)); + } + if let Some(bits) = asm_format + .strip_prefix("si") + .or_else(|| asm_format.strip_prefix('i')) + { + return Some(signed_constraint(bits.parse::().ok()?)); + } + None +} + +fn special_constraint(name: &str) -> Option { + match name { + "lsx_vldi" | "lasx_xvldi" => { + // CC: imm13 only support 0000 ~ 1100 in bits 9 ~ 12 when bit ‘13’ is 1 + let values: Vec = (0i64..8192i64) + .filter(|&x| x < 4096 || ((x >> 8) & 0xf) < 13) + // sign extend + .map(|x| ((x << 51) as i64) >> 51) + .collect(); + Some(Constraint::Set(values)) + } + _ => None, + } +} + +fn unsigned_constraint(bits: u32) -> Constraint { + Constraint::Range(0..(1i64 << bits.min(63))) +} + +fn signed_constraint(bits: u32) -> Constraint { + let min = if bits == 64 { + i64::MIN + } else { + -(1i64 << (bits - 1)) + }; + let max = if bits == 64 { + i64::MAX + } else { + 1i64 << (bits - 1) + }; + Constraint::Range(min..max) +} + +fn extension_for(name: &str) -> Result<&'static str, Box> { + if name.starts_with("lasx_") { + Ok("LASX") + } else if name.starts_with("lsx_") { + Ok("LSX") + } else { + Err(format!("unsupported LoongArch intrinsic name {name}").into()) + } +} diff --git a/library/stdarch/crates/intrinsic-test/src/loongarch/types.rs b/library/stdarch/crates/intrinsic-test/src/loongarch/types.rs new file mode 100644 index 0000000000000..dd4e578e67a41 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/loongarch/types.rs @@ -0,0 +1,309 @@ +use super::intrinsic::LoongArchType; +use crate::common::intrinsic_helpers::{IntrinsicType, Sign, SimdLen, TypeDefinition, TypeKind}; + +impl TypeDefinition for LoongArchType { + fn c_type(&self) -> String { + if self.ptr { + return if self.ptr_constant { + "const void*".to_string() + } else { + "void*".to_string() + }; + } + + match (self.kind(), self.simd_len) { + (_, Some(SimdLen::Fixed(lanes))) => { + format!( + "__{}", + vector_type_name(lanes, self.inner_size(), self.kind()) + ) + } + (TypeKind::Int(Sign::Signed), None) => { + scalar_type_name(true, scalar_signature_bits(self.inner_size())).to_string() + } + (TypeKind::Int(Sign::Unsigned), None) => { + scalar_type_name(false, scalar_signature_bits(self.inner_size())).to_string() + } + (TypeKind::Float, None) => match self.inner_size() { + 32 => "float".to_string(), + 64 => "double".to_string(), + bits => unreachable!("unsupported scalar float width {bits}"), + }, + (TypeKind::Void, None) => "void".to_string(), + _ => unreachable!("unsupported LoongArch type {self:#?}"), + } + } + + fn rust_type(&self) -> String { + if self.ptr { + return format!( + "*{} core::ffi::c_void", + if self.ptr_constant { "const" } else { "mut" }, + ); + } + + match (self.kind(), self.simd_len) { + (_, Some(SimdLen::Fixed(lanes))) => { + vector_type_name(lanes, self.inner_size(), self.kind()).to_string() + } + (TypeKind::Int(Sign::Signed), None) => { + semantic_rust_scalar_type(true, scalar_signature_bits(self.inner_size())) + .to_string() + } + (TypeKind::Int(Sign::Unsigned), None) => { + semantic_rust_scalar_type(false, scalar_signature_bits(self.inner_size())) + .to_string() + } + (TypeKind::Float, None) => match self.inner_size() { + 32 => "f32".to_string(), + 64 => "f64".to_string(), + bits => unreachable!("unsupported scalar float width {bits}"), + }, + (TypeKind::Void, None) => "()".to_string(), + _ => unreachable!("unsupported LoongArch type {self:#?}"), + } + } + + fn rust_scalar_type(&self) -> String { + match self.kind() { + TypeKind::Int(Sign::Signed) => { + semantic_rust_scalar_type(true, self.inner_size()).to_string() + } + TypeKind::Int(Sign::Unsigned) => { + semantic_rust_scalar_type(false, self.inner_size()).to_string() + } + TypeKind::Float => match self.inner_size() { + 32 => "f32".to_string(), + 64 => "f64".to_string(), + bits => unreachable!("unsupported scalar float width {bits}"), + }, + _ => unreachable!("unsupported LoongArch scalar type {self:#?}"), + } + } + + fn load_function(&self) -> String { + let Some(SimdLen::Fixed(lanes)) = self.simd_len else { + unreachable!("LoongArch loads are only used for SIMD types") + }; + + match (lanes * self.inner_size(), self.kind()) { + (128, TypeKind::Float) if self.inner_size() == 64 => "lsx_vld_to_m128d".to_string(), + (128, TypeKind::Float) => "lsx_vld_to_m128".to_string(), + (128, _) => "lsx_vld_to_m128i".to_string(), + (256, TypeKind::Float) if self.inner_size() == 64 => "lasx_xvld_to_m256d".to_string(), + (256, TypeKind::Float) => "lasx_xvld_to_m256".to_string(), + (256, _) => "lasx_xvld_to_m256i".to_string(), + bits => unreachable!("unsupported LoongArch vector width {bits:?}"), + } + } +} + +fn vector_type_name(lanes: u32, bit_len: u32, kind: TypeKind) -> &'static str { + match (lanes * bit_len, kind, bit_len) { + (128, TypeKind::Float, 32) => "m128", + (128, TypeKind::Float, 64) => "m128d", + (128, _, _) => "m128i", + (256, TypeKind::Float, 32) => "m256", + (256, TypeKind::Float, 64) => "m256d", + (256, _, _) => "m256i", + _ => unreachable!("unsupported LoongArch vector shape {kind:?}x{bit_len}x{lanes}"), + } +} + +fn scalar_type_name(signed: bool, bit_len: u32) -> &'static str { + match (signed, bit_len) { + (true, 32) => "int32_t", + (true, 64) => "int64_t", + (false, 32) => "uint32_t", + (false, 64) => "uint64_t", + _ => unreachable!("unsupported LoongArch scalar width {bit_len}"), + } +} + +fn scalar_signature_bits(bit_len: u32) -> u32 { + match bit_len { + 8 | 16 | 32 => 32, + 64 => 64, + _ => unreachable!("unsupported LoongArch scalar width {bit_len}"), + } +} + +fn semantic_rust_scalar_type(signed: bool, bit_len: u32) -> &'static str { + match (signed, bit_len) { + (true, 8) => "i8", + (true, 16) => "i16", + (true, 32) => "i32", + (true, 64) => "i64", + (false, 8) => "u8", + (false, 16) => "u16", + (false, 32) => "u32", + (false, 64) => "u64", + _ => unreachable!("unsupported LoongArch scalar width {bit_len}"), + } +} + +pub fn parse_intrinsic_type(s: &str) -> Result { + let (kind, bit_len, simd_len, ptr, ptr_constant) = match s { + "V16QI" => ( + TypeKind::Int(Sign::Signed), + Some(8), + Some(SimdLen::Fixed(16)), + false, + false, + ), + "V32QI" => ( + TypeKind::Int(Sign::Signed), + Some(8), + Some(SimdLen::Fixed(32)), + false, + false, + ), + "V8HI" => ( + TypeKind::Int(Sign::Signed), + Some(16), + Some(SimdLen::Fixed(8)), + false, + false, + ), + "V16HI" => ( + TypeKind::Int(Sign::Signed), + Some(16), + Some(SimdLen::Fixed(16)), + false, + false, + ), + "V4SI" => ( + TypeKind::Int(Sign::Signed), + Some(32), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "V8SI" => ( + TypeKind::Int(Sign::Signed), + Some(32), + Some(SimdLen::Fixed(8)), + false, + false, + ), + "V2DI" => ( + TypeKind::Int(Sign::Signed), + Some(64), + Some(SimdLen::Fixed(2)), + false, + false, + ), + "V4DI" => ( + TypeKind::Int(Sign::Signed), + Some(64), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "UV16QI" => ( + TypeKind::Int(Sign::Unsigned), + Some(8), + Some(SimdLen::Fixed(16)), + false, + false, + ), + "UV32QI" => ( + TypeKind::Int(Sign::Unsigned), + Some(8), + Some(SimdLen::Fixed(32)), + false, + false, + ), + "UV8HI" => ( + TypeKind::Int(Sign::Unsigned), + Some(16), + Some(SimdLen::Fixed(8)), + false, + false, + ), + "UV16HI" => ( + TypeKind::Int(Sign::Unsigned), + Some(16), + Some(SimdLen::Fixed(16)), + false, + false, + ), + "UV4SI" => ( + TypeKind::Int(Sign::Unsigned), + Some(32), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "UV8SI" => ( + TypeKind::Int(Sign::Unsigned), + Some(32), + Some(SimdLen::Fixed(8)), + false, + false, + ), + "UV2DI" => ( + TypeKind::Int(Sign::Unsigned), + Some(64), + Some(SimdLen::Fixed(2)), + false, + false, + ), + "UV4DI" => ( + TypeKind::Int(Sign::Unsigned), + Some(64), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "V4SF" => ( + TypeKind::Float, + Some(32), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "V8SF" => ( + TypeKind::Float, + Some(32), + Some(SimdLen::Fixed(8)), + false, + false, + ), + "V2DF" => ( + TypeKind::Float, + Some(64), + Some(SimdLen::Fixed(2)), + false, + false, + ), + "V4DF" => ( + TypeKind::Float, + Some(64), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "QI" => (TypeKind::Int(Sign::Signed), Some(8), None, false, false), + "HI" => (TypeKind::Int(Sign::Signed), Some(16), None, false, false), + "SI" => (TypeKind::Int(Sign::Signed), Some(32), None, false, false), + "UQI" => (TypeKind::Int(Sign::Unsigned), Some(8), None, false, false), + "UHI" => (TypeKind::Int(Sign::Unsigned), Some(16), None, false, false), + "USI" => (TypeKind::Int(Sign::Unsigned), Some(32), None, false, false), + "DI" => (TypeKind::Int(Sign::Signed), Some(64), None, false, false), + "UDI" => (TypeKind::Int(Sign::Unsigned), Some(64), None, false, false), + "CVPOINTER" => (TypeKind::Int(Sign::Signed), Some(8), None, true, true), + "VOID" => (TypeKind::Void, None, None, false, false), + _ => return Err(format!("unsupported LoongArch type {s}")), + }; + + Ok(IntrinsicType { + constant: false, + ptr_constant, + ptr, + kind, + bit_len, + simd_len, + vec_len: None, + }) +} diff --git a/library/stdarch/crates/intrinsic-test/src/main.rs b/library/stdarch/crates/intrinsic-test/src/main.rs index e25eb48a456d1..91e76d8f5fa50 100644 --- a/library/stdarch/crates/intrinsic-test/src/main.rs +++ b/library/stdarch/crates/intrinsic-test/src/main.rs @@ -3,11 +3,13 @@ extern crate log; mod arm; mod common; +mod loongarch; mod x86; use arm::Arm; use common::SupportedArchitecture; use common::cli::{Cli, ProcessedCli}; +use loongarch::LoongArch; use x86::X86; fn main() { @@ -21,6 +23,11 @@ fn main() { run(Arm::create(&processed_cli_options), processed_cli_options) } else if processed_cli_options.target.starts_with("x86") { run(X86::create(&processed_cli_options), processed_cli_options) + } else if processed_cli_options.target.starts_with("loongarch64") { + run( + LoongArch::create(&processed_cli_options), + processed_cli_options, + ) } else { unimplemented!("Unsupported target {}", processed_cli_options.target) } diff --git a/library/stdarch/crates/intrinsic-test/src/x86/mod.rs b/library/stdarch/crates/intrinsic-test/src/x86/mod.rs index 36f4fee43741b..9eafcf1fc7b96 100644 --- a/library/stdarch/crates/intrinsic-test/src/x86/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/x86/mod.rs @@ -32,6 +32,8 @@ impl SupportedArchitecture for X86 { "#; const RUST_PRELUDE: &str = RUST_PRELUDE; + const C_NAME_PREFIX: &str = ""; + fn c_compiler_flags(&self, _cli_options: &ProcessedCli) -> Vec<&str> { vec![ "-maes", diff --git a/library/stdarch/crates/stdarch-gen-arm/Cargo.toml b/library/stdarch/crates/stdarch-gen-arm/Cargo.toml index cb284d5f2c57b..9d803538474c7 100644 --- a/library/stdarch/crates/stdarch-gen-arm/Cargo.toml +++ b/library/stdarch/crates/stdarch-gen-arm/Cargo.toml @@ -12,6 +12,7 @@ edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clap = { version = "4", features = ["derive", "env"] } itertools = "0.15.0" proc-macro2 = "1.0" quote = "1.0" diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index e5ce77ed8b33f..01942246a0997 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -4321,10 +4321,7 @@ intrinsics: - ['*mut f64', float64x1_t] compose: - FnCall: [static_assert!, ['LANE == 0']] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: [core::ptr::write_unaligned, [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst1{neon_type[1].lane_nox}" doc: "Store multiple single-element structures from one, two, three, or four registers" @@ -4340,10 +4337,7 @@ intrinsics: - ['*mut f64', float64x2_t] compose: - FnCall: [static_assert_uimm_bits!, [LANE, '1']] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: [core::ptr::write_unaligned, [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst2{neon_type[1].nox}" doc: "Store multiple 2-element structures from two registers" diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index a4ade26e45c37..35c2a108c39ab 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -2868,7 +2868,7 @@ intrinsics: - ["*const f16", float16x8_t, 'q_lane', '3'] compose: - FnCall: [static_assert_uimm_bits!, [LANE, '{type[3]}']] - - FnCall: [simd_insert!, [src, "LANE as u32", "*ptr"]] + - FnCall: [simd_insert!, [src, "LANE as u32", {FnCall: ["crate::ptr::read_unaligned", [ptr]]}]] - name: "vld1{type[2]}_{neon_type[1]}" doc: "Load one single-element structure and replicate to all lanes of one register" @@ -4683,10 +4683,7 @@ intrinsics: - ['*mut u64', uint64x1_t] compose: - FnCall: [static_assert!, ['LANE == 0']] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst1{neon_type[1].lane_nox}" doc: "Store multiple single-element structures from one, two, three, or four registers" @@ -4708,10 +4705,7 @@ intrinsics: - ['*mut p64', poly64x1_t] compose: - FnCall: [static_assert!, ['LANE == 0']] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst1{neon_type[1].lane_nox}" doc: "Store multiple single-element structures from one, two, three, or four registers" @@ -4733,10 +4727,7 @@ intrinsics: - ['*mut p64', poly64x2_t] compose: - FnCall: [static_assert_uimm_bits!, [LANE, '1']] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst1{neon_type[1].lane_nox}" doc: "Store multiple single-element structures from one, two, three, or four registers" @@ -4774,10 +4765,7 @@ intrinsics: - ['*mut f32', float32x4_t, '2'] compose: - FnCall: [static_assert_uimm_bits!, [LANE, "{type[2]}"]] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst1{neon_type[1].lane_nox}" @@ -4799,10 +4787,7 @@ intrinsics: - ['*mut f16', float16x8_t, '3'] compose: - FnCall: [static_assert_uimm_bits!, [LANE, "{type[2]}"]] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: 'vst1{neon_type[1].no}' @@ -14310,17 +14295,17 @@ intrinsics: - ['vld1q_lane_p16', '*const p16', 'poly16x8_t', '"vld1.16"', '7', 'ld1', 'static_assert_uimm_bits!', 'LANE, 3'] - ['vld1_lane_s32', '*const i32', 'int32x2_t', '"vld1.32"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] - ['vld1_lane_u32', '*const u32', 'uint32x2_t', '"vld1.32"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] - - ['vld1_lane_f32', '*const f32', 'float32x2_t', '"vld1.32"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] + - ['vld1_lane_f32', '*const f32', 'float32x2_t', 'ldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] - ['vld1q_lane_s32', '*const i32', 'int32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2'] - ['vld1q_lane_u32', '*const u32', 'uint32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2'] - - ['vld1q_lane_f32', '*const f32', 'float32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2'] - - ['vld1_lane_s64', '*const i64', 'int64x1_t', 'vldr', '0', 'ldr', 'static_assert!', 'LANE == 0'] - - ['vld1_lane_u64', '*const u64', 'uint64x1_t', 'vldr', '0', 'ldr', 'static_assert!', 'LANE == 0'] - - ['vld1q_lane_s64', '*const i64', 'int64x2_t', 'vldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] - - ['vld1q_lane_u64', '*const u64', 'uint64x2_t', 'vldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] + - ['vld1q_lane_f32', '*const f32', 'float32x4_t', 'ldr', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2'] + - ['vld1_lane_s64', '*const i64', 'int64x1_t', '"vld1.8"', '0', 'ldr', 'static_assert!', 'LANE == 0'] + - ['vld1_lane_u64', '*const u64', 'uint64x1_t', '"vld1.8"', '0', 'ldr', 'static_assert!', 'LANE == 0'] + - ['vld1q_lane_s64', '*const i64', 'int64x2_t', '"vld1.8"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] + - ['vld1q_lane_u64', '*const u64', 'uint64x2_t', '"vld1.8"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] compose: - FnCall: ["{type[6]}", ["{type[7]}"]] - - FnCall: [simd_insert!, [src, 'LANE as u32', '*ptr']] + - FnCall: [simd_insert!, [src, 'LANE as u32', {FnCall: ['crate::ptr::read_unaligned', [ptr]]}]] - name: "{type[0]}" doc: "Load one single-element structure to one lane of one register." @@ -14338,11 +14323,11 @@ intrinsics: safety: unsafe: [neon] types: - - ['vld1_lane_p64', '*const p64', 'poly64x1_t', 'vldr', '0', 'ldr', 'static_assert!', 'LANE == 0'] - - ['vld1q_lane_p64', '*const p64', 'poly64x2_t', 'vldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] + - ['vld1_lane_p64', '*const p64', 'poly64x1_t', '"vld1.8"', '0', 'ldr', 'static_assert!', 'LANE == 0'] + - ['vld1q_lane_p64', '*const p64', 'poly64x2_t', '"vld1.8"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] compose: - FnCall: ["{type[6]}", ["{type[7]}"]] - - FnCall: [simd_insert!, [src, 'LANE as u32', '*ptr']] + - FnCall: [simd_insert!, [src, 'LANE as u32', {FnCall: ['crate::ptr::read_unaligned', [ptr]]}]] - name: "{type[0]}" doc: "Load one single-element structure and Replicate to all lanes (of one register)." @@ -14396,7 +14381,7 @@ intrinsics: safety: unsafe: [neon] types: - - ['vld1q_dup_p64', '*const p64', 'poly64x2_t', 'vldr', 'ld1r', 'vld1q_lane_p64::<0>', 'u64x2::splat(0)', '[0, 0]'] + - ['vld1q_dup_p64', '*const p64', 'poly64x2_t', '"vld1.8"', 'ld1r', 'vld1q_lane_p64::<0>', 'u64x2::splat(0)', '[0, 0]'] compose: - Let: - x @@ -14437,18 +14422,18 @@ intrinsics: - ['vld1_dup_s32', '*const i32', 'int32x2_t', 'vld1.32', 'ld1r', 'i32x2::splat'] - ['vld1_dup_u32', '*const u32', 'uint32x2_t', 'vld1.32', 'ld1r', 'u32x2::splat'] - - ['vld1_dup_f32', '*const f32', 'float32x2_t', 'vld1.32', 'ld1r', 'f32x2::splat'] + - ['vld1_dup_f32', '*const f32', 'float32x2_t', 'ldr', 'ld1r', 'f32x2::splat'] - ['vld1q_dup_s32', '*const i32', 'int32x4_t', 'vld1.32', 'ld1r', 'i32x4::splat'] - ['vld1q_dup_u32', '*const u32', 'uint32x4_t', 'vld1.32', 'ld1r', 'u32x4::splat'] - - ['vld1q_dup_f32', '*const f32', 'float32x4_t', 'vld1.32', 'ld1r', 'f32x4::splat'] + - ['vld1q_dup_f32', '*const f32', 'float32x4_t', 'ldr', 'ld1r', 'f32x4::splat'] - - ['vld1q_dup_s64', '*const i64', 'int64x2_t', 'vldr', 'ld1r', 'i64x2::splat'] - - ['vld1q_dup_u64', '*const u64', 'uint64x2_t', 'vldr', 'ld1r', 'u64x2::splat'] + - ['vld1q_dup_s64', '*const i64', 'int64x2_t', 'vld1.8', 'ld1r', 'i64x2::splat'] + - ['vld1q_dup_u64', '*const u64', 'uint64x2_t', 'vld1.8', 'ld1r', 'u64x2::splat'] compose: - FnCall: - transmute - - - FnCall: ['{type[5]}', ["*ptr"]] + - - FnCall: ['{type[5]}', [{FnCall: ['crate::ptr::read_unaligned', [ptr]]}]] - name: "{type[0]}" doc: "Absolute difference and accumulate (64-bit)" diff --git a/library/stdarch/crates/stdarch-gen-arm/src/load_store_tests.rs b/library/stdarch/crates/stdarch-gen-arm/src/load_store_tests.rs index 672047fc057b8..3e3c20c592be0 100644 --- a/library/stdarch/crates/stdarch-gen-arm/src/load_store_tests.rs +++ b/library/stdarch/crates/stdarch-gen-arm/src/load_store_tests.rs @@ -1,10 +1,9 @@ use std::fs::File; -use std::io::Write; -use std::path::PathBuf; +use std::io::{BufWriter, Write}; +use std::path::Path; use std::str::FromStr; use std::sync::LazyLock; -use crate::format_code; use crate::input::InputType; use crate::intrinsic::Intrinsic; use crate::typekinds::BaseType; @@ -38,15 +37,11 @@ const LEN_U64: usize = VL_MAX_BYTES / core::mem::size_of::(); pub fn generate_load_store_tests( load_intrinsics: Vec, store_intrinsics: Vec, - out_path: Option<&PathBuf>, + out_path: &Path, ) -> Result<(), String> { - let output = match out_path { - Some(out) => { - Box::new(File::create(out).map_err(|e| format!("couldn't create tests file: {e}"))?) - as Box - } - None => Box::new(std::io::stdout()) as Box, - }; + let mut output = BufWriter::new( + File::create(out_path).map_err(|e| format!("couldn't create tests file: {e}"))?, + ); let mut used_stores = vec![false; store_intrinsics.len()]; let tests: Vec<_> = load_intrinsics .iter() @@ -89,10 +84,9 @@ pub fn generate_load_store_tests( .map_err(|e| format!("Manual tests are invalid: {e}"))?, _ => quote!(), }; - format_code( + write!( output, - format!( - "// This code is automatically generated. DO NOT MODIFY. + "// This code is automatically generated. DO NOT MODIFY. // // Instead, modify `crates/stdarch-gen-arm/spec/sve` and run the following command to re-generate // this file: @@ -101,8 +95,7 @@ pub fn generate_load_store_tests( // cargo run --bin=stdarch-gen-arm -- crates/stdarch-gen-arm/spec // ``` {}", - quote! { #preamble #(#tests)* #manual_tests } - ), + quote! { #preamble #(#tests)* #manual_tests } ) .map_err(|e| format!("couldn't write tests: {e}")) } diff --git a/library/stdarch/crates/stdarch-gen-arm/src/main.rs b/library/stdarch/crates/stdarch-gen-arm/src/main.rs index 276cc5ba41b01..db1cfb2bb92b2 100644 --- a/library/stdarch/crates/stdarch-gen-arm/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-arm/src/main.rs @@ -14,19 +14,51 @@ mod typekinds; mod wildcards; mod wildstring; +use clap::Parser; use intrinsic::Test; use itertools::Itertools; use quote::quote; use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; -use std::process::{Command, Stdio}; -use stdarch_gen_common::{Mode, run_generator}; +use stdarch_gen_common::{GeneratorCtx, Mode, run_generator}; use walkdir::WalkDir; +#[derive(clap::Parser)] +struct Args { + /// Directory with spec files: //.spec.yml + input_dir: PathBuf, + /// Output directory to generate the files into, such as crates/core_arch/src + output_dir: Option, + /// Generation mode. + #[arg(long, env = "STDARCH_GEN_MODE")] + mode: Option, + /// Path to a rustfmt binary that will be used to reformat the generated code. + /// If unset, it will just use "rustfmt" from the environment. + #[arg(long)] + rustfmt_path: Option, +} + fn main() -> Result<(), String> { - let (in_path, out_base) = parse_args(); - let mode = Mode::from_env(); + let args = Args::parse(); + + let in_path = args.input_dir; + let out_base = args.output_dir.unwrap_or_else(|| { + std::env::current_exe() + .ok() + .map(|mut f| { + f.pop(); + f.push("../../crates/core_arch/src/"); + f + }) + .filter(|f| f.exists()) + .expect("could not locate crates/core_arch/src; pass OUTPUT_DIR command-line argument explicitly") + }); + assert!(in_path.exists()); + assert!(out_base.exists()); + + let mode = args.mode.unwrap_or_default(); + let ctx = GeneratorCtx::new(args.rustfmt_path); for filepath in WalkDir::new(&in_path) .into_iter() @@ -42,7 +74,7 @@ fn main() -> Result<(), String> { .expect("generated output path must have a parent directory") .to_path_buf(); - run_generator(&committed, mode, |scratch: &Path| { + run_generator(&ctx, &committed, mode, |scratch: &Path| { generate_spec(&filepath, scratch) }) .map_err(|e| e.to_string())?; @@ -92,7 +124,7 @@ fn generate_spec(filepath: &Path, out_dir: &Path) -> Result<(), String> { .expect("load/store test path must have a file name") .to_owned(); let tests_path = out_dir.join(tests_name); - load_store_tests::generate_load_store_tests(loads, stores, Some(&tests_path))?; + load_store_tests::generate_load_store_tests(loads, stores, &tests_path)?; } let generated = input::GeneratorInput { @@ -105,44 +137,6 @@ fn generate_spec(filepath: &Path, out_dir: &Path) -> Result<(), String> { .map_err(|e| format!("could not generate output file: {e}")) } -fn parse_args() -> (PathBuf, PathBuf) { - let mut args_it = std::env::args().skip(1); - assert!( - 1 <= args_it.len() && args_it.len() <= 2, - "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(); - assert!( - in_path.exists() && in_path.is_dir(), - "invalid path {in_path:#?} given" - ); - - let out_base = if let Some(dir) = args_it.next() { - let out_path = Path::new(dir.as_str()).to_path_buf(); - assert!( - out_path.exists() && out_path.is_dir(), - "invalid path {out_path:#?} given" - ); - out_path - } else { - std::env::current_exe() - .ok() - .map(|mut f| { - f.pop(); - f.push("../../crates/core_arch/src/"); - f - }) - .filter(|f| f.exists()) - .expect("could not locate crates/core_arch/src; pass OUTPUT_DIR command-line argument explicitly") - }; - - (in_path, out_base) -} - fn generate_file( generated_input: input::GeneratorInput, mut out: Box, @@ -171,25 +165,10 @@ use super::*;{uses_neon} }, )?; let intrinsics = generated_input.intrinsics; - format_code(out, quote! { #(#intrinsics)* })?; + write!(out, "{}", quote! { #(#intrinsics)* })?; Ok(()) } -pub fn format_code( - mut output: impl std::io::Write, - input: impl std::fmt::Display, -) -> std::io::Result<()> { - let proc = Command::new("rustfmt") - // Ensure that we generate the same file contents on both Linux and Windows. - .arg("--config") - .arg("newline_style=Unix") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn()?; - write!(proc.stdin.as_ref().unwrap(), "{input}")?; - output.write_all(proc.wait_with_output()?.stdout.as_slice()) -} - /// Derive an output file path from an input file path and an output directory. /// /// `in_filepath` is expected to have a structure like: diff --git a/library/stdarch/crates/stdarch-gen-common/Cargo.toml b/library/stdarch/crates/stdarch-gen-common/Cargo.toml index 691be14971a0d..fda09cb4c5994 100644 --- a/library/stdarch/crates/stdarch-gen-common/Cargo.toml +++ b/library/stdarch/crates/stdarch-gen-common/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2024" [dependencies] -tempfile = "3" \ No newline at end of file +tempfile = "3" +similar = "3" diff --git a/library/stdarch/crates/stdarch-gen-common/src/lib.rs b/library/stdarch/crates/stdarch-gen-common/src/lib.rs index 13d788594ca55..5dbfc76f27dfe 100644 --- a/library/stdarch/crates/stdarch-gen-common/src/lib.rs +++ b/library/stdarch/crates/stdarch-gen-common/src/lib.rs @@ -1,11 +1,14 @@ //! Shared check/bless harness for stdarch generators. +use similar::TextDiff; use std::error::Error as StdError; use std::fmt; use std::fs; use std::io; use std::io::Read; use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; +use std::str::FromStr; /// First-line marker identifying an auto-generated file. Generators emit this /// as the first line of every file they produce; the harness uses it to @@ -13,7 +16,7 @@ use std::path::{Path, PathBuf}; pub const GENERATED_MARKER: &str = "// This code is automatically generated. DO NOT MODIFY."; /// Controls what `run_generator` does with the generator's output. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub enum Mode { /// Verify that the `committed` matches the generator's output for owned files. /// @@ -26,23 +29,20 @@ pub enum Mode { /// into `committed`. If the generator no longer produces an owned file, the /// committed copy is deleted. Files in `committed` that are not owned /// are left untouched. + #[default] Bless, } -impl Mode { - /// Read the mode from the `STDARCH_GEN_MODE` environment variable. - /// - /// Recognized values: - /// - `"check"` → [`Mode::Check`] - /// - `"bless"` → [`Mode::Bless`] - /// - unset → [`Mode::Bless`] - /// - any other value → panic - pub fn from_env() -> Self { - match std::env::var("STDARCH_GEN_MODE").as_deref() { - Ok("check") => Mode::Check, - Ok("bless") => Mode::Bless, - Ok(other) => panic!("unknown STDARCH_GEN_MODE value: {other:?}"), - Err(_) => Mode::Bless, +impl FromStr for Mode { + type Err = String; + + fn from_str(s: &str) -> std::result::Result { + match s { + "check" => Ok(Mode::Check), + "bless" => Ok(Mode::Bless), + other => Err(format!( + "unknown stdarch generation mode: {other:?}. Possible values are `check` or `bless`." + )), } } } @@ -102,6 +102,18 @@ impl From for Error { pub type Result = std::result::Result; +pub struct GeneratorCtx { + rustfmt_path: PathBuf, +} + +impl GeneratorCtx { + pub fn new(rustfmt_path: Option) -> Self { + Self { + rustfmt_path: rustfmt_path.unwrap_or_else(|| PathBuf::from("rustfmt")), + } + } +} + /// Run a generator under the chosen `mode`, reconciling its output with `committed`. /// /// Arguments: @@ -120,7 +132,12 @@ pub type Result = std::result::Result; /// - [`Mode::Bless`]: runs the generator into a temp dir and copies owned /// files into `committed`, or removes `committed`'s copy if the generator no /// longer produces them. -pub fn run_generator(committed: &Path, mode: Mode, generate: F) -> Result<()> +pub fn run_generator( + ctx: &GeneratorCtx, + committed: &Path, + mode: Mode, + generate: F, +) -> Result<()> where F: FnOnce(&Path) -> std::result::Result<(), E>, E: Into>, @@ -131,6 +148,14 @@ where let owned = discover_owned(committed)?; let produced = discover_all(scratch.path())?; + // Format all generated Rust files + for file in &produced { + let fullpath = scratch.path().join(file); + if fullpath.extension().and_then(|s| s.to_str()) == Some("rs") { + reformat_file(ctx, &fullpath)?; + } + } + let mut names: Vec<&String> = owned.iter().chain(produced.iter()).collect(); names.sort(); names.dedup(); @@ -144,6 +169,34 @@ where Ok(()) } +fn reformat_file(ctx: &GeneratorCtx, path: &Path) -> std::io::Result<()> { + let file = std::fs::File::open(path)?; + let proc = Command::new(&ctx.rustfmt_path) + // Ensure that rustfmt config files in other directories won't interfere with the formatting + // This is important for usage within the rust-lang/rust repository + .arg("--config-path") + .arg( + Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .parent() + .unwrap() + .join("rustfmt.toml"), + ) + .stdin(Stdio::from(file)) + .stdout(Stdio::piped()) + .spawn()?; + + let output = proc.wait_with_output()?; + if !output.status.success() { + panic!( + "Running {:?} on {path:?} failed with exit code {:?}", + ctx.rustfmt_path, output.status + ); + } + std::fs::write(path, output.stdout) +} + /// Returns the names of files in `dir` whose first line begins with /// [`GENERATED_MARKER`]. Files without the marker are skipped. fn discover_owned(dir: &Path) -> Result> { @@ -199,7 +252,23 @@ fn compare(generated_dir: &Path, committed_dir: &Path, filename: &str) -> Result }), (false, false) => Ok(()), (true, true) => { - if fs::read(&gen_path)? != fs::read(&comm_path)? { + let generated = fs::read(&gen_path)?; + let committed = fs::read(&comm_path)?; + if generated != committed { + if let (Ok(committed), Ok(generated)) = + (str::from_utf8(&committed), str::from_utf8(&generated)) + { + eprintln!( + "{}", + TextDiff::from_lines(committed, generated) + .unified_diff() + .context_radius(3) + .header( + &format!("committed/{filename}"), + &format!("generated/{filename}"), + ) + ); + } Err(Error::Mismatch { path: rel_path, kind: MismatchKind::ContentsDiffer, @@ -249,7 +318,10 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); let committed = tmp.path().join("c"); write_marker(&committed.join("a.txt"), b"hi"); + + let ctx = GeneratorCtx::new(None); let e = run_generator( + &ctx, &committed, Mode::Check, |out| -> std::result::Result<(), io::Error> { @@ -272,7 +344,10 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); let committed = tmp.path().join("c"); write_marker(&committed.join("a.txt"), b"hi"); + + let ctx = GeneratorCtx::new(None); let e = run_generator( + &ctx, &committed, Mode::Check, |_| -> std::result::Result<(), io::Error> { Ok(()) }, @@ -292,7 +367,10 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); let committed = tmp.path().join("c"); fs::create_dir_all(&committed).unwrap(); + + let ctx = GeneratorCtx::new(None); let e = run_generator( + &ctx, &committed, Mode::Check, |out| -> std::result::Result<(), io::Error> { @@ -316,7 +394,10 @@ mod tests { let committed = tmp.path().join("c"); write_marker(&committed.join("keep.txt"), b""); write_marker(&committed.join("stale.txt"), b""); + + let ctx = GeneratorCtx::new(None); run_generator( + &ctx, &committed, Mode::Bless, |out| -> std::result::Result<(), io::Error> { @@ -336,7 +417,9 @@ mod tests { fs::create_dir_all(&committed).unwrap(); fs::write(committed.join("mod.rs"), b"hand-written").unwrap(); fs::write(committed.join("old.txt"), b"old").unwrap(); + let ctx = GeneratorCtx::new(None); run_generator( + &ctx, &committed, Mode::Bless, |out| -> std::result::Result<(), io::Error> { @@ -349,4 +432,32 @@ mod tests { assert_eq!(fs::read(committed.join("old.txt")).unwrap(), b"old"); assert!(committed.join("new.txt").exists()); } + + #[test] + fn generation_reformats_files() { + let tmp = tempfile::tempdir().unwrap(); + let committed = tmp.path().join("c"); + let file = committed.join("a.rs"); + write_marker(&file, b"foo"); + + let ctx = GeneratorCtx::new(None); + run_generator( + &ctx, + &committed, + Mode::Bless, + |out| -> std::result::Result<(), io::Error> { + write_marker(&out.join("a.rs"), b"fn main() {}"); + Ok(()) + }, + ) + .unwrap(); + assert_eq!( + std::fs::read_to_string(file).unwrap(), + format!( + r#"{GENERATED_MARKER} +fn main() {{}} +"# + ) + ); + } } diff --git a/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml b/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml index c7dfce2c0fd7b..7d457868398ac 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml +++ b/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml @@ -6,5 +6,6 @@ license = "MIT OR Apache-2.0" edition = "2021" [dependencies] +clap = { version = "4", features = ["derive", "env"] } regex = "1.10" stdarch-gen-common = { path = "../stdarch-gen-common" } diff --git a/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs b/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs index 537c59bbce861..95c77ae4700a4 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs +++ b/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs @@ -19,7 +19,7 @@ use regex::Regex; use std::collections::{HashMap, HashSet}; use std::fs::File; -use std::io::Write; +use std::io::{BufWriter, Write}; use std::path::Path; use stdarch_gen_common::GENERATED_MARKER; @@ -1606,30 +1606,16 @@ fn generate_module_file( intrinsics: &[IntrinsicInfo], output_path: &Path, mode: VectorMode, -) -> Result<(), String> { - let mut output = - File::create(output_path).map_err(|e| format!("Failed to create output: {}", e))?; - - writeln!(output, "{}", GENERATED_MARKER).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_module_doc(mode)).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_types(mode)).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_extern_block(intrinsics, mode)).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_functions(intrinsics)).map_err(|e| e.to_string())?; - - // Ensure file is flushed before running rustfmt - drop(output); - - // Run rustfmt on the generated file - let status = std::process::Command::new("rustfmt") - .arg(output_path) - .status() - .map_err(|e| format!("Failed to run rustfmt: {}", e))?; - - if !status.success() { - return Err("rustfmt failed".to_string()); - } +) -> std::io::Result<()> { + let mut output = BufWriter::new(File::create(output_path)?); - Ok(()) + writeln!(output, "{}", GENERATED_MARKER)?; + writeln!(output, "{}", generate_module_doc(mode))?; + writeln!(output, "{}", generate_types(mode))?; + writeln!(output, "{}", generate_extern_block(intrinsics, mode))?; + writeln!(output, "{}", generate_functions(intrinsics))?; + + output.flush() } /// Parse the HVX header in `crate_dir` and write `v64.rs` and `v128.rs` into `out_dir`. @@ -1642,7 +1628,8 @@ pub fn generate(crate_dir: &std::path::Path, out_dir: &std::path::Path) -> Resul .collect(); for (filename, vmode) in [("v64.rs", VectorMode::V64), ("v128.rs", VectorMode::V128)] { let path = out_dir.join(filename); - generate_module_file(&intrinsics, &path, vmode)?; + generate_module_file(&intrinsics, &path, vmode) + .map_err(|e| format!("Cannot generate {path:?}: {e:?}"))?; } Ok(()) } diff --git a/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs b/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs index 88ef4fe11f332..1e23e993ef918 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs @@ -1,18 +1,31 @@ -//! Hexagon code generator. -//! -//! Single binary that produces every generated file under -//! `core_arch/src/hexagon/`: scalar.rs (scalar intrinsics) and -//! v64.rs / v128.rs (HVX intrinsics). -//! -//! Run in check or bless mode via `STDARCH_GEN_MODE`. - mod hvx; mod scalar; +use clap::Parser; use std::path::PathBuf; -use stdarch_gen_common::{run_generator, Mode}; +use stdarch_gen_common::{run_generator, GeneratorCtx, Mode}; + +/// Hexagon code generator. +/// +/// Produces every generated file under +/// `core_arch/src/hexagon/`: scalar.rs (scalar intrinsics) and +/// v64.rs / v128.rs (HVX intrinsics). +/// +/// Run in check or bless mode via `STDARCH_GEN_MODE`. +#[derive(clap::Parser)] +struct Args { + /// Generation mode. + #[arg(long, env = "STDARCH_GEN_MODE")] + mode: Option, + /// Path to a rustfmt binary that will be used to reformat the generated code. + /// If unset, it will just use "rustfmt" from the environment. + #[arg(long)] + rustfmt_path: Option, +} fn main() -> Result<(), String> { + let args = Args::parse(); + let crate_dir = std::env::var("CARGO_MANIFEST_DIR") .map(PathBuf::from) .unwrap_or_else(|_| std::env::current_dir().unwrap()); @@ -20,9 +33,10 @@ fn main() -> Result<(), String> { let hexagon_dir = crate_dir.join("../core_arch/src/hexagon"); // Either "check" to check the output versus the committed output, or "bless" // to update the output. - let mode = Mode::from_env(); + let mode = args.mode.unwrap_or_default(); + let ctx = GeneratorCtx::new(args.rustfmt_path); - run_generator(&hexagon_dir, mode, |out_dir| -> Result<(), String> { + run_generator(&ctx, &hexagon_dir, mode, |out_dir| -> Result<(), String> { // Here scalar::generate writes scalar.rs . scalar::generate(&crate_dir, out_dir)?; // Here hvx::generate writes v64.rs and v128.rs . diff --git a/library/stdarch/crates/stdarch-gen-hexagon/src/scalar.rs b/library/stdarch/crates/stdarch-gen-hexagon/src/scalar.rs index 2a64798d097d1..8c7880b58a023 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/src/scalar.rs +++ b/library/stdarch/crates/stdarch-gen-hexagon/src/scalar.rs @@ -19,7 +19,7 @@ use regex::Regex; use std::collections::HashMap; use std::fs::File; -use std::io::Write; +use std::io::{BufWriter, Write}; use std::path::Path; use stdarch_gen_common::GENERATED_MARKER; @@ -627,30 +627,16 @@ fn generate_functions(intrinsics: &[ScalarIntrinsic]) -> String { } /// Generate the complete scalar.rs file -fn generate_scalar_file(intrinsics: &[ScalarIntrinsic], output_path: &Path) -> Result<(), String> { - let mut output = - File::create(output_path).map_err(|e| format!("Failed to create output: {}", e))?; - - writeln!(output, "{}", GENERATED_MARKER).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_module_doc()).map_err(|e| e.to_string())?; - writeln!(output, "").map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_extern_block(intrinsics)).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_functions(intrinsics)).map_err(|e| e.to_string())?; - - // Flush before running rustfmt - drop(output); - - // Run rustfmt on the generated file - let status = std::process::Command::new("rustfmt") - .arg(output_path) - .status() - .map_err(|e| format!("Failed to run rustfmt: {}", e))?; - - if !status.success() { - return Err("rustfmt failed".to_string()); - } +fn generate_scalar_file(intrinsics: &[ScalarIntrinsic], output_path: &Path) -> std::io::Result<()> { + let mut output = BufWriter::new(File::create(output_path)?); - Ok(()) + writeln!(output, "{}", GENERATED_MARKER)?; + writeln!(output, "{}", generate_module_doc())?; + writeln!(output, "")?; + writeln!(output, "{}", generate_extern_block(intrinsics))?; + writeln!(output, "{}", generate_functions(intrinsics))?; + + output.flush() } /// Parse the scalar header in `crate_dir` and write `scalar.rs` into `out_dir`. @@ -659,6 +645,6 @@ pub fn generate(crate_dir: &std::path::Path, out_dir: &std::path::Path) -> Resul let intrinsics = parse_header(&header_content); std::fs::create_dir_all(out_dir).map_err(|e| e.to_string())?; let scalar_path = out_dir.join("scalar.rs"); - generate_scalar_file(&intrinsics, &scalar_path)?; + generate_scalar_file(&intrinsics, &scalar_path).map_err(|e| e.to_string())?; Ok(()) } diff --git a/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml b/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml index a9ddc123b3688..d174b844b430a 100644 --- a/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml +++ b/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml @@ -7,5 +7,6 @@ edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clap = { version = "4", features = ["derive", "env"] } rand = "0.9.3" stdarch-gen-common = { path = "../stdarch-gen-common" } diff --git a/library/stdarch/crates/stdarch-gen-loongarch/src/main.rs b/library/stdarch/crates/stdarch-gen-loongarch/src/main.rs index 86fa8956e6ed1..1fed0b96f9426 100644 --- a/library/stdarch/crates/stdarch-gen-loongarch/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-loongarch/src/main.rs @@ -1,3 +1,4 @@ +use clap::Parser; use std::collections::HashSet; use std::env; use std::fmt; @@ -6,7 +7,7 @@ use std::io::prelude::*; use std::io::{self, BufReader}; use std::path::Path; use std::path::PathBuf; -use stdarch_gen_common::{Mode, run_generator}; +use stdarch_gen_common::{GeneratorCtx, Mode, run_generator}; /// Complete lines of generated source. /// @@ -1602,51 +1603,64 @@ static void {current_name}(void) /// Runs the check/bless harness for `lsx`/`lasx` when invoked with /// no args or a bare ext name. +#[derive(clap::Parser, Debug)] +struct Args { + /// Either: + /// - The extension (lsx/lasx) to generate, or: + /// - A path to a intrin.h file to generate the spec file from. Optionally followed + /// by "test". + arguments: Vec, + /// Generation mode. + #[arg(long, env = "STDARCH_GEN_MODE")] + mode: Option, + /// Path to a rustfmt binary that will be used to reformat the generated code. + /// If unset, it will just use "rustfmt" from the environment. + #[arg(long)] + rustfmt_path: Option, +} + pub fn main() -> Result<(), String> { - let args: Vec = env::args().collect(); - let arg_strs: Vec<&str> = args.iter().map(String::as_str).collect(); - let harness_exts: Option<&[&str]> = match arg_strs.as_slice() { - [_] => Some(&["lsx", "lasx"]), - [_, "lsx"] => Some(&["lsx"]), - [_, "lasx"] => Some(&["lasx"]), - _ => None, - }; - if let Some(exts) = harness_exts { - let crate_dir = - PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set")); - let core_arch_src = crate_dir.join("../core_arch/src"); - let mode = Mode::from_env(); - for ext in exts { - let spec_rel = format!("crates/stdarch-gen-loongarch/{ext}.spec"); - let committed = core_arch_src.join("loongarch64").join(ext); - run_generator(&committed, mode, |out_dir| { - gen_bind(&spec_rel, ext, out_dir) - }) - .map_err(|e| e.to_string())?; - } - return Ok(()); - } + let args = Args::parse(); + + let crate_dir = + PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set")); + let core_arch_src = crate_dir.join("../core_arch/src"); + let mode = args.mode.unwrap_or_default(); + let ctx = GeneratorCtx::new(args.rustfmt_path); - let in_file = args[1].clone(); - let in_file_name = PathBuf::from(&in_file) - .file_name() - .unwrap() - .to_string_lossy() - .into_owned(); - let ext_name = if in_file_name.starts_with("lasx") { - "lasx" + let arguments = &args.arguments; + if arguments.len() == 1 && (arguments[0] == "lsx" || arguments[0] == "lasx") { + let extension = arguments[0].as_str(); + let spec_rel = format!("crates/stdarch-gen-loongarch/{extension}.spec"); + let committed = core_arch_src.join("loongarch64").join(extension); + run_generator(&ctx, &committed, mode, |out_dir| { + gen_bind(&spec_rel, extension, out_dir) + }) + .map_err(|e| e.to_string())?; } else { - "lsx" - }; - if in_file_name.ends_with(".h") { - return gen_spec(in_file, ext_name).map_err(|e| e.to_string()); - } - if let [_, _lsx_or_lasx, "test"] = arg_strs.as_slice() { - return gen_test(in_file, ext_name).map_err(|e| e.to_string()); + let in_file = arguments[0].clone(); + let in_file_name = PathBuf::from(&in_file) + .file_name() + .unwrap() + .to_string_lossy() + .into_owned(); + let ext_name = if in_file_name.starts_with("lasx") { + "lasx" + } else { + "lsx" + }; + if in_file_name.ends_with(".h") { + return gen_spec(in_file, ext_name).map_err(|e| e.to_string()); + } + if arguments.last().map(|s| s.as_str()) == Some("test") { + return gen_test(in_file, ext_name).map_err(|e| e.to_string()); + } + // Note: this does not apply rustfmt formatting + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap_or("crates/core_arch".to_string())) + .join("src") + .join("loongarch64") + .join(ext_name); + gen_bind(&in_file, ext_name, &out_path).map_err(|e| e.to_string())?; } - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap_or("crates/core_arch".to_string())) - .join("src") - .join("loongarch64") - .join(ext_name); - gen_bind(&in_file, ext_name, &out_path).map_err(|e| e.to_string()) + Ok(()) } diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index 18fea436747c7..368cecc0b82f9 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -1 +1 @@ -32d94cc9be3f6e6c3fa1deaea9e0ab93c4980dba +220b36c420c49c59923f54cd4a76634fac98a067 diff --git a/library/stdarch/rustfmt.toml b/library/stdarch/rustfmt.toml index e69de29bb2d1d..3dd85bb2defbf 100644 --- a/library/stdarch/rustfmt.toml +++ b/library/stdarch/rustfmt.toml @@ -0,0 +1,2 @@ +# Ensure that we generate the same file contents on both Linux and Windows. +newline_style = "Unix" diff --git a/library/stdarch/triagebot.toml b/library/stdarch/triagebot.toml index 5b178f0cdf456..149646aa65f01 100644 --- a/library/stdarch/triagebot.toml +++ b/library/stdarch/triagebot.toml @@ -1,3 +1,35 @@ +[relabel] +allow-unauthenticated = [ + "A-*", + "B-*", + "C-*", + "D-*", + "E-*", + "F-*", + "I-*", + "L-*", + "NLL-*", + "O-*", + "PG-*", + "S-*", + "T-*", + "WG-*", + "-Z*", + "beta-nominated", + "CI-spurious-*", + "const-hack", + "llvm-*", + "needs-fcp", + "relnotes", + "release-blog-post", + "requires-*", + "regression-*", + "rla-*", + "perf-*", + "AsyncAwait-OnDeck", + "needs-triage", + "has-merge-commits",] + [assign] [assign.owners] diff --git a/tests/run-make/incremental-session-gc/rmake.rs b/tests/run-make/incremental-session-gc/rmake.rs index 341a21690f215..405708abb7e3c 100644 --- a/tests/run-make/incremental-session-gc/rmake.rs +++ b/tests/run-make/incremental-session-gc/rmake.rs @@ -12,14 +12,12 @@ fn main() { compile(); let mut previous = session_dir(); - rfs::write(previous.join("sentinel"), "previous session"); for _ in 0..2 { compile(); let current = session_dir(); assert_ne!(previous, current); assert!(!previous.exists(), "superseded session was not collected: {previous:?}"); - assert_eq!(rfs::read_to_string(current.join("sentinel")), "previous session"); previous = current; } @@ -36,7 +34,6 @@ fn main() { let current = session_dir(); assert_ne!(previous, newer); assert!(!newer.exists(), "superseded session was not collected: {previous:?}"); - assert_eq!(rfs::read_to_string(current.join("sentinel")), "previous session"); } fn session_dir() -> PathBuf { diff --git a/tests/ui/async-await/await-keyword/await-macro-rustfix.fixed b/tests/ui/async-await/await-keyword/await-macro-rustfix.fixed new file mode 100644 index 0000000000000..2946c05ad51b5 --- /dev/null +++ b/tests/ui/async-await/await-keyword/await-macro-rustfix.fixed @@ -0,0 +1,23 @@ +//@ run-rustfix +//@ edition: 2024 + +// Replacing `await!(...)` must preserve grouping and any following `?`. + +use std::future::ready; + +async fn check() -> Result<(), ()> { + let future = ready(1); + let _: i32 = future.await; + //~^ ERROR incorrect use of `await` + let _: i32 = ready(1).await; + //~^ ERROR incorrect use of `await` + let _: i32 = ready(Ok::(1)).await?; + //~^ ERROR incorrect use of `await` + let _: i32 = (/* keep */ &mut ready(1) /* keep */).await; + //~^ ERROR incorrect use of `await` + Ok(()) +} + +fn main() { + let _ = check(); +} diff --git a/tests/ui/async-await/await-keyword/await-macro-rustfix.rs b/tests/ui/async-await/await-keyword/await-macro-rustfix.rs new file mode 100644 index 0000000000000..7272a2084843d --- /dev/null +++ b/tests/ui/async-await/await-keyword/await-macro-rustfix.rs @@ -0,0 +1,23 @@ +//@ run-rustfix +//@ edition: 2024 + +// Replacing `await!(...)` must preserve grouping and any following `?`. + +use std::future::ready; + +async fn check() -> Result<(), ()> { + let future = ready(1); + let _: i32 = await!(future); + //~^ ERROR incorrect use of `await` + let _: i32 = await!(ready(1)); + //~^ ERROR incorrect use of `await` + let _: i32 = await!(ready(Ok::(1)))?; + //~^ ERROR incorrect use of `await` + let _: i32 = await!(/* keep */ &mut ready(1) /* keep */); + //~^ ERROR incorrect use of `await` + Ok(()) +} + +fn main() { + let _ = check(); +} diff --git a/tests/ui/async-await/await-keyword/await-macro-rustfix.stderr b/tests/ui/async-await/await-keyword/await-macro-rustfix.stderr new file mode 100644 index 0000000000000..42a1bdfdafcaa --- /dev/null +++ b/tests/ui/async-await/await-keyword/await-macro-rustfix.stderr @@ -0,0 +1,50 @@ +error: incorrect use of `await` + --> $DIR/await-macro-rustfix.rs:10:18 + | +LL | let _: i32 = await!(future); + | ^^^^^^^^^^^^^^ + | +help: `await` is a postfix operation + | +LL - let _: i32 = await!(future); +LL + let _: i32 = future.await; + | + +error: incorrect use of `await` + --> $DIR/await-macro-rustfix.rs:12:18 + | +LL | let _: i32 = await!(ready(1)); + | ^^^^^^^^^^^^^^^^ + | +help: `await` is a postfix operation + | +LL - let _: i32 = await!(ready(1)); +LL + let _: i32 = ready(1).await; + | + +error: incorrect use of `await` + --> $DIR/await-macro-rustfix.rs:14:18 + | +LL | let _: i32 = await!(ready(Ok::(1)))?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: `await` is a postfix operation + | +LL - let _: i32 = await!(ready(Ok::(1)))?; +LL + let _: i32 = ready(Ok::(1)).await?; + | + +error: incorrect use of `await` + --> $DIR/await-macro-rustfix.rs:16:18 + | +LL | let _: i32 = await!(/* keep */ &mut ready(1) /* keep */); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: `await` is a postfix operation + | +LL - let _: i32 = await!(/* keep */ &mut ready(1) /* keep */); +LL + let _: i32 = (/* keep */ &mut ready(1) /* keep */).await; + | + +error: aborting due to 4 previous errors + diff --git a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 0ccde7d8709f1..a6ec0b3f8542d 100644 --- a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -187,7 +187,7 @@ LL | let _ = await!(bar()); help: `await` is a postfix operation | LL - let _ = await!(bar()); -LL + let _ = bar().await); +LL + let _ = bar().await; | error: incorrect use of `await` @@ -199,7 +199,7 @@ LL | let _ = await!(bar())?; help: `await` is a postfix operation | LL - let _ = await!(bar())?; -LL + let _ = bar().await)?; +LL + let _ = bar().await?; | error: incorrect use of `await` @@ -211,7 +211,7 @@ LL | let _ = await!(bar())?; help: `await` is a postfix operation | LL - let _ = await!(bar())?; -LL + let _ = bar().await)?; +LL + let _ = bar().await?; | error: incorrect use of `await` @@ -223,7 +223,7 @@ LL | let _ = await!(bar())?; help: `await` is a postfix operation | LL - let _ = await!(bar())?; -LL + let _ = bar().await)?; +LL + let _ = bar().await?; | error: expected expression, found `=>` diff --git a/tests/ui/const-generics/gca/const-reference-to-constructor.rs b/tests/ui/const-generics/gca/const-reference-to-constructor.rs new file mode 100644 index 0000000000000..bafaf9f532545 --- /dev/null +++ b/tests/ui/const-generics/gca/const-reference-to-constructor.rs @@ -0,0 +1,10 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +//! https://github.com/rust-lang/rust/issues/162923 +#![feature(min_generic_const_args)] +#![feature(generic_const_args)] +enum T::B as u8 }> { + A = 2, + B, +} +fn main() {} diff --git a/tests/ui/eii/default/call_default.rs b/tests/ui/eii/default/call_default.rs index 7769ae00bb0f5..db5b7da45d470 100644 --- a/tests/ui/eii/default/call_default.rs +++ b/tests/ui/eii/default/call_default.rs @@ -3,7 +3,6 @@ //@ aux-build: decl_with_default.rs //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests EIIs with default implementations. diff --git a/tests/ui/eii/default/call_default_panics.rs b/tests/ui/eii/default/call_default_panics.rs index d027748b0ffb3..526e71856046b 100644 --- a/tests/ui/eii/default/call_default_panics.rs +++ b/tests/ui/eii/default/call_default_panics.rs @@ -5,7 +5,6 @@ //@ run-pass //@ needs-unwind //@ exec-env:RUST_BACKTRACE=1 -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // A small test to make sure that unwinding works properly. diff --git a/tests/ui/eii/default/call_impl.rs b/tests/ui/eii/default/call_impl.rs index 4b64033a940f5..7f7d5d0163cfb 100644 --- a/tests/ui/eii/default/call_impl.rs +++ b/tests/ui/eii/default/call_impl.rs @@ -4,7 +4,6 @@ //@ aux-build: impl1.rs //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests EIIs with default implementations. diff --git a/tests/ui/eii/default/local_crate.rs b/tests/ui/eii/default/local_crate.rs index d6e992c409453..bf97c8bd2fd68 100644 --- a/tests/ui/eii/default/local_crate.rs +++ b/tests/ui/eii/default/local_crate.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests EIIs with default implementations. diff --git a/tests/ui/eii/default/local_crate_explicit.rs b/tests/ui/eii/default/local_crate_explicit.rs index 7c29fa0edd6ae..c2e52f8bd174a 100644 --- a/tests/ui/eii/default/local_crate_explicit.rs +++ b/tests/ui/eii/default/local_crate_explicit.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests EIIs with default implementations. diff --git a/tests/ui/eii/default/local_crate_explicit.stderr b/tests/ui/eii/default/local_crate_explicit.stderr index d80acf14c516d..51b4d9b545b3d 100644 --- a/tests/ui/eii/default/local_crate_explicit.stderr +++ b/tests/ui/eii/default/local_crate_explicit.stderr @@ -1,5 +1,5 @@ warning: function `decl1` is never used - --> $DIR/local_crate_explicit.rs:11:8 + --> $DIR/local_crate_explicit.rs:10:8 | LL | pub fn decl1(x: u64) { | ^^^^^ diff --git a/tests/ui/eii/duplicate/both_decl_and_impl.rs b/tests/ui/eii/duplicate/both_decl_and_impl.rs index a2fc571d3f497..9cf122e40aac3 100644 --- a/tests/ui/eii/duplicate/both_decl_and_impl.rs +++ b/tests/ui/eii/duplicate/both_decl_and_impl.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that one item can't both define and impl an EII at the same time diff --git a/tests/ui/eii/duplicate/both_decl_and_impl.stderr b/tests/ui/eii/duplicate/both_decl_and_impl.stderr index 1cec485a90cff..d109eaee95a5e 100644 --- a/tests/ui/eii/duplicate/both_decl_and_impl.stderr +++ b/tests/ui/eii/duplicate/both_decl_and_impl.stderr @@ -1,23 +1,23 @@ error: a single item cannot both declare and implement EIIs - --> $DIR/both_decl_and_impl.rs:11:1 + --> $DIR/both_decl_and_impl.rs:10:1 | LL | #[eii] | ^^^^^^ error: only a small subset of attributes are supported on externally implementable items - --> $DIR/both_decl_and_impl.rs:21:1 + --> $DIR/both_decl_and_impl.rs:20:1 | LL | fn d(x: u64) {} | ^^^^^^^^^^^^ | note: this attribute is not supported - --> $DIR/both_decl_and_impl.rs:20:1 + --> $DIR/both_decl_and_impl.rs:19:1 | LL | #[c] | ^^^^ error: `#[c]` function required, but not found - --> $DIR/both_decl_and_impl.rs:16:4 + --> $DIR/both_decl_and_impl.rs:15:4 | LL | fn c(x: u64); | ^ expected because `#[c]` was declared here in crate `both_decl_and_impl` diff --git a/tests/ui/eii/duplicate/duplicate1.rs b/tests/ui/eii/duplicate/duplicate1.rs index 54803f31c85f4..9dc9038bec059 100644 --- a/tests/ui/eii/duplicate/duplicate1.rs +++ b/tests/ui/eii/duplicate/duplicate1.rs @@ -2,7 +2,6 @@ //@[dylib] needs-crate-type: dylib //@ aux-build: impl1.rs //@ aux-build: impl2.rs -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // tests that EIIs error properly, even if the conflicting implementations live in another crate. diff --git a/tests/ui/eii/duplicate/duplicate2.rs b/tests/ui/eii/duplicate/duplicate2.rs index 8b4d7c4913c91..95121e1e6d9b8 100644 --- a/tests/ui/eii/duplicate/duplicate2.rs +++ b/tests/ui/eii/duplicate/duplicate2.rs @@ -1,7 +1,6 @@ //@ aux-build: impl1.rs //@ aux-build: impl2.rs //@ aux-build: impl3.rs -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests the error message when there are multiple implementations of an EII in many crates. diff --git a/tests/ui/eii/duplicate/duplicate3.rs b/tests/ui/eii/duplicate/duplicate3.rs index 96d6543130ccb..d50b87865109b 100644 --- a/tests/ui/eii/duplicate/duplicate3.rs +++ b/tests/ui/eii/duplicate/duplicate3.rs @@ -2,7 +2,6 @@ //@ aux-build: impl2.rs //@ aux-build: impl3.rs //@ aux-build: impl4.rs -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests the error message when there are multiple implementations of an EII in many crates. diff --git a/tests/ui/eii/duplicate/dylib_default_duplicate.rs b/tests/ui/eii/duplicate/dylib_default_duplicate.rs index 5480bb13b4a49..a72a137eb9709 100644 --- a/tests/ui/eii/duplicate/dylib_default_duplicate.rs +++ b/tests/ui/eii/duplicate/dylib_default_duplicate.rs @@ -1,7 +1,6 @@ //@ aux-build: dylib_default.rs //@ needs-crate-type: dylib //@ compile-flags: --emit link -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Regression test for https://github.com/rust-lang/rust/issues/156320. diff --git a/tests/ui/eii/duplicate/dylib_default_duplicate.stderr b/tests/ui/eii/duplicate/dylib_default_duplicate.stderr index 04c6a13710e28..91c90edb02449 100644 --- a/tests/ui/eii/duplicate/dylib_default_duplicate.stderr +++ b/tests/ui/eii/duplicate/dylib_default_duplicate.stderr @@ -1,5 +1,5 @@ error: multiple implementations of `#[eii1]` - --> $DIR/dylib_default_duplicate.rs:15:1 + --> $DIR/dylib_default_duplicate.rs:14:1 | LL | fn other(x: u64) { | ^^^^^^^^^^^^^^^^ first implemented here in crate `dylib_default_duplicate` diff --git a/tests/ui/eii/duplicate/multiple_impls.rs b/tests/ui/eii/duplicate/multiple_impls.rs index 3e541cb16b131..8f1feaa530adb 100644 --- a/tests/ui/eii/duplicate/multiple_impls.rs +++ b/tests/ui/eii/duplicate/multiple_impls.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that one item can't implement two EIIs diff --git a/tests/ui/eii/duplicate/multiple_impls.stderr b/tests/ui/eii/duplicate/multiple_impls.stderr index efeec635c859a..b2e8871d2087a 100644 --- a/tests/ui/eii/duplicate/multiple_impls.stderr +++ b/tests/ui/eii/duplicate/multiple_impls.stderr @@ -1,17 +1,17 @@ error: a single item cannot implement multiple EIIs - --> $DIR/multiple_impls.rs:15:1 + --> $DIR/multiple_impls.rs:14:1 | LL | #[b] | ^^^^ error: a single item cannot implement multiple EIIs - --> $DIR/multiple_impls.rs:29:1 + --> $DIR/multiple_impls.rs:28:1 | LL | #[d] | ^^^^ error: `#[a]` function required, but not found - --> $DIR/multiple_impls.rs:8:4 + --> $DIR/multiple_impls.rs:7:4 | LL | fn a(x: u64); | ^ expected because `#[a]` was declared here in crate `multiple_impls` @@ -19,7 +19,7 @@ LL | fn a(x: u64); = help: expected at least one implementation in crate `multiple_impls` or any of its dependencies error: `#[c]` static required, but not found - --> $DIR/multiple_impls.rs:21:7 + --> $DIR/multiple_impls.rs:20:7 | LL | #[eii(c)] | ^ expected because `#[c]` was declared here in crate `multiple_impls` diff --git a/tests/ui/eii/eii_impl_with_contract.rs b/tests/ui/eii/eii_impl_with_contract.rs index 1789ec92ea60d..a33d7a0c23751 100644 --- a/tests/ui/eii/eii_impl_with_contract.rs +++ b/tests/ui/eii/eii_impl_with_contract.rs @@ -1,5 +1,4 @@ //@ run-pass -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu diff --git a/tests/ui/eii/linking/codegen_cross_crate.rs b/tests/ui/eii/linking/codegen_cross_crate.rs index ab0d4d4b9eb25..f11c8a04661b6 100644 --- a/tests/ui/eii/linking/codegen_cross_crate.rs +++ b/tests/ui/eii/linking/codegen_cross_crate.rs @@ -2,7 +2,6 @@ //@ check-run-results //@ aux-build: codegen_cross_crate_other_crate.rs //@ compile-flags: -O -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether calling EIIs works with the declaration in another crate. diff --git a/tests/ui/eii/linking/codegen_single_crate.rs b/tests/ui/eii/linking/codegen_single_crate.rs index 4faa30a79040f..81b56cd4261ba 100644 --- a/tests/ui/eii/linking/codegen_single_crate.rs +++ b/tests/ui/eii/linking/codegen_single_crate.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether calling EIIs works with the declaration in the same crate. diff --git a/tests/ui/eii/linking/same-symbol.rs b/tests/ui/eii/linking/same-symbol.rs index 02518f6bced03..57af6357f3de4 100644 --- a/tests/ui/eii/linking/same-symbol.rs +++ b/tests/ui/eii/linking/same-symbol.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu #![feature(extern_item_impls)] diff --git a/tests/ui/eii/linking/track_caller_cross_crate.rs b/tests/ui/eii/linking/track_caller_cross_crate.rs index e8ba5dc2b864b..b8d0d53336c39 100644 --- a/tests/ui/eii/linking/track_caller_cross_crate.rs +++ b/tests/ui/eii/linking/track_caller_cross_crate.rs @@ -2,7 +2,6 @@ //@ check-run-results //@ aux-build: track_caller_cross_other_crate.rs //@ compile-flags: -O -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that `#[track_caller]` on an EII declaration in one crate is derived diff --git a/tests/ui/eii/privacy1.rs b/tests/ui/eii/privacy1.rs index 95544ae867d89..e342441546513 100644 --- a/tests/ui/eii/privacy1.rs +++ b/tests/ui/eii/privacy1.rs @@ -1,7 +1,6 @@ //@ run-pass //@ check-run-results //@ aux-build: other_crate_privacy1.rs -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether re-exports work. diff --git a/tests/ui/eii/shadow_builtin.rs b/tests/ui/eii/shadow_builtin.rs index cd4c14514dc46..f9447b85273af 100644 --- a/tests/ui/eii/shadow_builtin.rs +++ b/tests/ui/eii/shadow_builtin.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether calling EIIs works with the declaration in the same crate. diff --git a/tests/ui/eii/shadow_builtin.stderr b/tests/ui/eii/shadow_builtin.stderr index 33f60b2d2f13f..bdb580785d15c 100644 --- a/tests/ui/eii/shadow_builtin.stderr +++ b/tests/ui/eii/shadow_builtin.stderr @@ -1,5 +1,5 @@ error[E0659]: `inline` is ambiguous - --> $DIR/shadow_builtin.rs:11:3 + --> $DIR/shadow_builtin.rs:10:3 | LL | #[inline] | ^^^^^^ ambiguous name @@ -7,14 +7,14 @@ LL | #[inline] = note: ambiguous because of a name conflict with a builtin attribute = note: `inline` could refer to a built-in attribute note: `inline` could also refer to the attribute macro defined here - --> $DIR/shadow_builtin.rs:7:1 + --> $DIR/shadow_builtin.rs:6:1 | LL | #[eii(inline)] | ^^^^^^^^^^^^^^ = help: use `crate::inline` to refer to this attribute macro unambiguously error: `#[inline]` function required, but not found - --> $DIR/shadow_builtin.rs:7:7 + --> $DIR/shadow_builtin.rs:6:7 | LL | #[eii(inline)] | ^^^^^^ expected because `#[inline]` was declared here in crate `shadow_builtin` diff --git a/tests/ui/eii/static/argument_required.rs b/tests/ui/eii/static/argument_required.rs index 9b00dcf194387..e8f66e083e983 100644 --- a/tests/ui/eii/static/argument_required.rs +++ b/tests/ui/eii/static/argument_required.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/argument_required.stderr b/tests/ui/eii/static/argument_required.stderr index 9e5ee398f77d8..9f722d2065e1e 100644 --- a/tests/ui/eii/static/argument_required.stderr +++ b/tests/ui/eii/static/argument_required.stderr @@ -1,5 +1,5 @@ error: `#[eii]` requires the name as an explicit argument when used on a static - --> $DIR/argument_required.rs:7:1 + --> $DIR/argument_required.rs:6:1 | LL | #[eii] | ^^^^^^ diff --git a/tests/ui/eii/static/cross_crate_decl.rs b/tests/ui/eii/static/cross_crate_decl.rs index 75333c48e40ef..ba038102099f5 100644 --- a/tests/ui/eii/static/cross_crate_decl.rs +++ b/tests/ui/eii/static/cross_crate_decl.rs @@ -2,7 +2,6 @@ //@ check-run-results //@ aux-build: cross_crate_decl.rs //@ compile-flags: -O -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether calling EIIs works with the declaration in another crate. diff --git a/tests/ui/eii/static/cross_crate_def.rs b/tests/ui/eii/static/cross_crate_def.rs index 19dbdaadeef05..0461c1dfe7398 100644 --- a/tests/ui/eii/static/cross_crate_def.rs +++ b/tests/ui/eii/static/cross_crate_def.rs @@ -4,7 +4,6 @@ //@ check-run-results //@ aux-build: cross_crate_def.rs //@ compile-flags: -O -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether calling EIIs works with the declaration and definition in another crate. diff --git a/tests/ui/eii/static/default.rs b/tests/ui/eii/static/default.rs index beb777cc32e82..c4e2208337914 100644 --- a/tests/ui/eii/static/default.rs +++ b/tests/ui/eii/static/default.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // FIXME(#157649): static EII defaults currently fail to link on Apple targets. diff --git a/tests/ui/eii/static/default_apple.rs b/tests/ui/eii/static/default_apple.rs index f638ee480f4cb..38446a2d17150 100644 --- a/tests/ui/eii/static/default_apple.rs +++ b/tests/ui/eii/static/default_apple.rs @@ -1,5 +1,4 @@ //@ only-apple -//@ ignore-backends: gcc #![feature(extern_item_impls)] #![crate_type = "lib"] diff --git a/tests/ui/eii/static/default_apple.stderr b/tests/ui/eii/static/default_apple.stderr index d4ced5948970d..3fbcde6dbb9a5 100644 --- a/tests/ui/eii/static/default_apple.stderr +++ b/tests/ui/eii/static/default_apple.stderr @@ -1,5 +1,5 @@ error: `#[eii]` cannot be used on statics with a value on Apple targets - --> $DIR/default_apple.rs:7:25 + --> $DIR/default_apple.rs:6:25 | LL | pub static DECL1: u64 = 5; | ^ diff --git a/tests/ui/eii/static/default_cross_crate.rs b/tests/ui/eii/static/default_cross_crate.rs index 9d6df257ffbef..a53c73876d977 100644 --- a/tests/ui/eii/static/default_cross_crate.rs +++ b/tests/ui/eii/static/default_cross_crate.rs @@ -3,7 +3,6 @@ //@ aux-build: decl_with_default.rs //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // FIXME(#157649): static EII defaults currently fail to link on Apple targets. diff --git a/tests/ui/eii/static/default_cross_crate_explicit.rs b/tests/ui/eii/static/default_cross_crate_explicit.rs index 6ad015b9b601b..4835e2ed323ab 100644 --- a/tests/ui/eii/static/default_cross_crate_explicit.rs +++ b/tests/ui/eii/static/default_cross_crate_explicit.rs @@ -4,7 +4,6 @@ //@ aux-build: impl_default_override.rs //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // FIXME(#157649): static EII defaults currently fail to link on Apple targets. diff --git a/tests/ui/eii/static/default_explicit.rs b/tests/ui/eii/static/default_explicit.rs index 8237b18106031..bc3f44e7e01b5 100644 --- a/tests/ui/eii/static/default_explicit.rs +++ b/tests/ui/eii/static/default_explicit.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // FIXME(#157649): static EII defaults currently fail to link on Apple targets. diff --git a/tests/ui/eii/static/duplicate.rs b/tests/ui/eii/static/duplicate.rs index a8db02f33051d..54cab82f617e7 100644 --- a/tests/ui/eii/static/duplicate.rs +++ b/tests/ui/eii/static/duplicate.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/duplicate.stderr b/tests/ui/eii/static/duplicate.stderr index 270664c8c74c6..e967e9c4e65c8 100644 --- a/tests/ui/eii/static/duplicate.stderr +++ b/tests/ui/eii/static/duplicate.stderr @@ -1,5 +1,5 @@ error: multiple implementations of `#[hello]` - --> $DIR/duplicate.rs:11:1 + --> $DIR/duplicate.rs:10:1 | LL | static HELLO_IMPL1: u64 = 5; | ^^^^^^^^^^^^^^^^^^^^^^^ first implemented here in crate `duplicate` diff --git a/tests/ui/eii/static/mismatch_fn_static.rs b/tests/ui/eii/static/mismatch_fn_static.rs index 8d8fa5b4d06c4..49003388526f8 100644 --- a/tests/ui/eii/static/mismatch_fn_static.rs +++ b/tests/ui/eii/static/mismatch_fn_static.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_fn_static.stderr b/tests/ui/eii/static/mismatch_fn_static.stderr index e8fa5f85b1f13..e8be6ccb7ef57 100644 --- a/tests/ui/eii/static/mismatch_fn_static.stderr +++ b/tests/ui/eii/static/mismatch_fn_static.stderr @@ -1,5 +1,5 @@ error: `#[hello]` must be used on a function - --> $DIR/mismatch_fn_static.rs:10:1 + --> $DIR/mismatch_fn_static.rs:9:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/static/mismatch_mut.rs b/tests/ui/eii/static/mismatch_mut.rs index 61c806fb976ca..b0e35b2bf84dc 100644 --- a/tests/ui/eii/static/mismatch_mut.rs +++ b/tests/ui/eii/static/mismatch_mut.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_mut.stderr b/tests/ui/eii/static/mismatch_mut.stderr index 537ac0de3c3a2..0812652a6a1bc 100644 --- a/tests/ui/eii/static/mismatch_mut.stderr +++ b/tests/ui/eii/static/mismatch_mut.stderr @@ -1,11 +1,11 @@ error: `#[eii]` cannot be used on mutable statics - --> $DIR/mismatch_mut.rs:7:1 + --> $DIR/mismatch_mut.rs:6:1 | LL | #[eii(hello)] | ^^^^^^^^^^^^^ error: mutability does not match with the definition of`#[hello]` - --> $DIR/mismatch_mut.rs:11:1 + --> $DIR/mismatch_mut.rs:10:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/static/mismatch_mut2.rs b/tests/ui/eii/static/mismatch_mut2.rs index ff21af5f0d714..f083e713d1769 100644 --- a/tests/ui/eii/static/mismatch_mut2.rs +++ b/tests/ui/eii/static/mismatch_mut2.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_mut2.stderr b/tests/ui/eii/static/mismatch_mut2.stderr index 6ac3df57697db..b4b953d61a23f 100644 --- a/tests/ui/eii/static/mismatch_mut2.stderr +++ b/tests/ui/eii/static/mismatch_mut2.stderr @@ -1,5 +1,5 @@ error: mutability does not match with the definition of`#[hello]` - --> $DIR/mismatch_mut2.rs:10:1 + --> $DIR/mismatch_mut2.rs:9:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/static/mismatch_safety.rs b/tests/ui/eii/static/mismatch_safety.rs index b8d503adc2d21..667c6fff14189 100644 --- a/tests/ui/eii/static/mismatch_safety.rs +++ b/tests/ui/eii/static/mismatch_safety.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_safety.stderr b/tests/ui/eii/static/mismatch_safety.stderr index d4fa85778ae11..19a3b0dd86639 100644 --- a/tests/ui/eii/static/mismatch_safety.stderr +++ b/tests/ui/eii/static/mismatch_safety.stderr @@ -1,5 +1,5 @@ error: safety does not match with the definition of`#[hello]` - --> $DIR/mismatch_safety.rs:10:1 + --> $DIR/mismatch_safety.rs:9:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/static/mismatch_safety2.rs b/tests/ui/eii/static/mismatch_safety2.rs index 412e2a694c1fc..5240184f6ada5 100644 --- a/tests/ui/eii/static/mismatch_safety2.rs +++ b/tests/ui/eii/static/mismatch_safety2.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_safety2.stderr b/tests/ui/eii/static/mismatch_safety2.stderr index 6957a6202b614..c49f55f2b911a 100644 --- a/tests/ui/eii/static/mismatch_safety2.stderr +++ b/tests/ui/eii/static/mismatch_safety2.stderr @@ -1,5 +1,5 @@ error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block - --> $DIR/mismatch_safety2.rs:11:1 + --> $DIR/mismatch_safety2.rs:10:1 | LL | unsafe static HELLO_IMPL: u64 = 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/eii/static/mismatch_static_fn.rs b/tests/ui/eii/static/mismatch_static_fn.rs index 06e3d95b7cdcb..b4fd139959d68 100644 --- a/tests/ui/eii/static/mismatch_static_fn.rs +++ b/tests/ui/eii/static/mismatch_static_fn.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_static_fn.stderr b/tests/ui/eii/static/mismatch_static_fn.stderr index 639e3cfa3beb3..56ea50c00fdd0 100644 --- a/tests/ui/eii/static/mismatch_static_fn.stderr +++ b/tests/ui/eii/static/mismatch_static_fn.stderr @@ -1,5 +1,5 @@ error: `#[hello]` must be used on a static - --> $DIR/mismatch_static_fn.rs:10:1 + --> $DIR/mismatch_static_fn.rs:9:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/static/mut.rs b/tests/ui/eii/static/mut.rs index 4c9d84061fb25..c351a6df8fbd2 100644 --- a/tests/ui/eii/static/mut.rs +++ b/tests/ui/eii/static/mut.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mut.stderr b/tests/ui/eii/static/mut.stderr index cd3a0ca23c7f4..299737d1f07b6 100644 --- a/tests/ui/eii/static/mut.stderr +++ b/tests/ui/eii/static/mut.stderr @@ -1,5 +1,5 @@ error: `#[eii]` cannot be used on mutable statics - --> $DIR/mut.rs:7:1 + --> $DIR/mut.rs:6:1 | LL | #[eii(hello)] | ^^^^^^^^^^^^^ diff --git a/tests/ui/eii/static/same_address.rs b/tests/ui/eii/static/same_address.rs index de316b9f5f9ff..a49ffd9a552b7 100644 --- a/tests/ui/eii/static/same_address.rs +++ b/tests/ui/eii/static/same_address.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs and their declarations share the same address diff --git a/tests/ui/eii/static/simple.rs b/tests/ui/eii/static/simple.rs index a592609e9153a..84d49bcef638a 100644 --- a/tests/ui/eii/static/simple.rs +++ b/tests/ui/eii/static/simple.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/subtype.rs b/tests/ui/eii/static/subtype.rs index 4553d7b8c59c0..a417838e2f7b0 100644 --- a/tests/ui/eii/static/subtype.rs +++ b/tests/ui/eii/static/subtype.rs @@ -1,5 +1,4 @@ //@ check-pass -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that mismatching types of the declaration and definition are rejected diff --git a/tests/ui/eii/static/subtype_wrong.rs b/tests/ui/eii/static/subtype_wrong.rs index ac975592a0f08..9d67d7b458cc7 100644 --- a/tests/ui/eii/static/subtype_wrong.rs +++ b/tests/ui/eii/static/subtype_wrong.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that mismatching types of the declaration and definition are rejected diff --git a/tests/ui/eii/static/subtype_wrong.stderr b/tests/ui/eii/static/subtype_wrong.stderr index a20074947c15d..77a1353aecc32 100644 --- a/tests/ui/eii/static/subtype_wrong.stderr +++ b/tests/ui/eii/static/subtype_wrong.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/subtype_wrong.rs:13:1 + --> $DIR/subtype_wrong.rs:12:1 | LL | static HELLO_IMPL: for<'a> fn(&'a u8) -> &'a u8 = |_| todo!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other diff --git a/tests/ui/eii/static/wrong_ty.rs b/tests/ui/eii/static/wrong_ty.rs index 40b7859b06b01..4f320603c512f 100644 --- a/tests/ui/eii/static/wrong_ty.rs +++ b/tests/ui/eii/static/wrong_ty.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that mismatching types of the declaration and definition are rejected diff --git a/tests/ui/eii/static/wrong_ty.stderr b/tests/ui/eii/static/wrong_ty.stderr index 5095513527747..b7569ea82b77f 100644 --- a/tests/ui/eii/static/wrong_ty.stderr +++ b/tests/ui/eii/static/wrong_ty.stderr @@ -1,11 +1,11 @@ error[E0806]: static `HELLO_IMPL` has a type that is incompatible with the declaration of `#[hello]` - --> $DIR/wrong_ty.rs:13:1 + --> $DIR/wrong_ty.rs:12:1 | LL | static HELLO_IMPL: bool = true; | ^^^^^^^^^^^^^^^^^^^^^^^ | note: expected this because of this attribute - --> $DIR/wrong_ty.rs:12:1 + --> $DIR/wrong_ty.rs:11:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/track_caller.rs b/tests/ui/eii/track_caller.rs index 5e298fba9675a..52807428f20d0 100644 --- a/tests/ui/eii/track_caller.rs +++ b/tests/ui/eii/track_caller.rs @@ -1,5 +1,4 @@ //@ run-pass -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that `#[track_caller]` on an EII declaration is threaded through both diff --git a/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.rs b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.rs new file mode 100644 index 0000000000000..9b6562ff578bf --- /dev/null +++ b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.rs @@ -0,0 +1,12 @@ +// Regression test for #162440. Diagnostics can run before closure capture +// analysis has inferred the tuple of upvar types. The capture-specific note +// must fall back instead of trying to access uninferred upvar types. + +//@ compile-flags: -Znext-solver=globally + +fn main() { + Some([0]).map(|s| s[..]); + //~^ ERROR the size for values of type `[{integer}]` cannot be known at compilation time + //~| ERROR the size for values of type `[{integer}]` cannot be known at compilation time + //~| ERROR the size for values of type `[{integer}]` cannot be known at compilation time +} diff --git a/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.stderr b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.stderr new file mode 100644 index 0000000000000..4aed7e179b8ef --- /dev/null +++ b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.stderr @@ -0,0 +1,41 @@ +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:15 + | +LL | Some([0]).map(|s| s[..]); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[{integer}]` +note: required by an implicit `Sized` bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:23 + | +LL | Some([0]).map(|s| s[..]); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[{integer}]` + = note: the return type of a function must have a statically known size + +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:19 + | +LL | Some([0]).map(|s| s[..]); + | --- ---^^^^^^ + | | | + | | doesn't have a size known at compile-time + | | within this `{closure@$DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:19: 8:22}` + | required by a bound introduced by this call + | + = help: within `{closure@$DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:19: 8:22}`, the trait `Sized` is not implemented for `[{integer}]` +note: required because it's used within this closure + --> $DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:19 + | +LL | Some([0]).map(|s| s[..]); + | ^^^ +note: required by a bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.rs b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.rs new file mode 100644 index 0000000000000..ff4a9b67a3fee --- /dev/null +++ b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.rs @@ -0,0 +1,16 @@ +// Diagnostics may run before closure capture analysis has inferred the upvar +// tuple, even for a closure which actually captures a value. + +//@ compile-flags: -Znext-solver=globally + +fn main() { + let x = String::new(); + + Some([0]).map(|s| { + //~^ ERROR the size for values of type `[{integer}]` cannot be known at compilation time + //~| ERROR the size for values of type `[{integer}]` cannot be known at compilation time + //~| ERROR the size for values of type `[{integer}]` cannot be known at compilation time + let _ = &x; + s[..] + }); +} diff --git a/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.stderr b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.stderr new file mode 100644 index 0000000000000..b19dca701f2fb --- /dev/null +++ b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.stderr @@ -0,0 +1,49 @@ +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-with-capture.rs:9:15 + | +LL | Some([0]).map(|s| { + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[{integer}]` +note: required by an implicit `Sized` bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-with-capture.rs:9:23 + | +LL | Some([0]).map(|s| { + | _______________________^ +... | +LL | | s[..] +LL | | }); + | |_____^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[{integer}]` + = note: the return type of a function must have a statically known size + +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-with-capture.rs:9:19 + | +LL | Some([0]).map(|s| { + | --- ^-- + | | | + | _______________|___within this `{closure@$DIR/closure-capture-uninferred-upvars-with-capture.rs:9:19: 9:22}` + | | | + | | required by a bound introduced by this call +... | +LL | | s[..] +LL | | }); + | |_____^ doesn't have a size known at compile-time + | + = help: within `{closure@$DIR/closure-capture-uninferred-upvars-with-capture.rs:9:19: 9:22}`, the trait `Sized` is not implemented for `[{integer}]` +note: required because it's used within this closure + --> $DIR/closure-capture-uninferred-upvars-with-capture.rs:9:19 + | +LL | Some([0]).map(|s| { + | ^^^ +note: required by a bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`.