From ec1b2fa38bebfe7f0150447b761046aced5b703f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 20 Oct 2025 18:00:04 +0200 Subject: [PATCH 01/14] Gracefully handle in case we cannot run the compiler in doctests --- src/librustdoc/doctest.rs | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index c9cd9f7fd4b11..f39d5aadfb491 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -500,7 +500,10 @@ fn add_exe_suffix(input: String, target: &TargetTuple) -> String { input + &exe_suffix } -fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Command { +fn wrapped_rustc_command<'a>( + rustc_wrappers: &'a [PathBuf], + rustc_binary: &'a Path, +) -> (Command, &'a Path) { let mut args = rustc_wrappers.iter().map(PathBuf::as_path).chain([rustc_binary]); let exe = args.next().expect("unable to create rustc command"); @@ -509,7 +512,7 @@ fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Com command.arg(arg); } - command + (command, rustc_wrappers.first().map(|p| &**p).unwrap_or(rustc_binary)) } /// Information needed for running a bundle of doctests. @@ -629,7 +632,8 @@ fn run_test( .test_builder .as_deref() .unwrap_or_else(|| rustc_interface::util::rustc_path(sysroot).expect("found rustc")); - let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary); + let (mut compiler, binary_path) = + wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary); compiler.args(&compiler_args); @@ -670,7 +674,13 @@ fn run_test( debug!("compiler invocation for doctest: {compiler:?}"); - let mut child = compiler.spawn().expect("Failed to spawn rustc process"); + let mut child = match compiler.spawn() { + Ok(child) => child, + Err(error) => { + eprintln!("Failed to spawn {binary_path:?}: {error:?}"); + return (Duration::default(), Err(TestFailure::CompileError)); + } + }; let output = if let Some(merged_test_code) = &doctest.merged_test_code { // compile-fail tests never get merged, so this should always pass let status = child.wait().expect("Failed to wait"); @@ -679,7 +689,7 @@ fn run_test( // build it now let runner_input_file = doctest.path_for_merged_doctest_runner(); - let mut runner_compiler = + let (mut runner_compiler, binary_path) = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary); // the test runner does not contain any user-written code, so this doesn't allow // the user to exploit nightly-only features on stable @@ -732,7 +742,13 @@ fn run_test( let status = if !status.success() { status } else { - let mut child_runner = runner_compiler.spawn().expect("Failed to spawn rustc process"); + let mut child_runner = match runner_compiler.spawn() { + Ok(child) => child, + Err(error) => { + eprintln!("Failed to spawn {binary_path:?}: {error:?}"); + return (Duration::default(), Err(TestFailure::CompileError)); + } + }; child_runner.wait().expect("Failed to wait") }; From 5d0011c1efe2ee91a6d15da31b369c3c5c187599 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 20 Oct 2025 18:00:48 +0200 Subject: [PATCH 02/14] Add regression test when unable to run compiler in doctest --- src/librustdoc/doctest.rs | 16 +++++--------- tests/run-make/rustdoc-test-builder/foo.rs | 3 +++ tests/run-make/rustdoc-test-builder/rmake.rs | 23 ++++++++++++++++++++ 3 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 tests/run-make/rustdoc-test-builder/foo.rs create mode 100644 tests/run-make/rustdoc-test-builder/rmake.rs diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index f39d5aadfb491..58f728082a44f 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -500,10 +500,7 @@ fn add_exe_suffix(input: String, target: &TargetTuple) -> String { input + &exe_suffix } -fn wrapped_rustc_command<'a>( - rustc_wrappers: &'a [PathBuf], - rustc_binary: &'a Path, -) -> (Command, &'a Path) { +fn wrapped_rustc_command(rustc_wrappers: &[PathBuf], rustc_binary: &Path) -> Command { let mut args = rustc_wrappers.iter().map(PathBuf::as_path).chain([rustc_binary]); let exe = args.next().expect("unable to create rustc command"); @@ -512,7 +509,7 @@ fn wrapped_rustc_command<'a>( command.arg(arg); } - (command, rustc_wrappers.first().map(|p| &**p).unwrap_or(rustc_binary)) + command } /// Information needed for running a bundle of doctests. @@ -632,8 +629,7 @@ fn run_test( .test_builder .as_deref() .unwrap_or_else(|| rustc_interface::util::rustc_path(sysroot).expect("found rustc")); - let (mut compiler, binary_path) = - wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary); + let mut compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary); compiler.args(&compiler_args); @@ -677,7 +673,7 @@ fn run_test( let mut child = match compiler.spawn() { Ok(child) => child, Err(error) => { - eprintln!("Failed to spawn {binary_path:?}: {error:?}"); + eprintln!("Failed to spawn {:?}: {error:?}", compiler.get_program()); return (Duration::default(), Err(TestFailure::CompileError)); } }; @@ -689,7 +685,7 @@ fn run_test( // build it now let runner_input_file = doctest.path_for_merged_doctest_runner(); - let (mut runner_compiler, binary_path) = + let mut runner_compiler = wrapped_rustc_command(&rustdoc_options.test_builder_wrappers, rustc_binary); // the test runner does not contain any user-written code, so this doesn't allow // the user to exploit nightly-only features on stable @@ -745,7 +741,7 @@ fn run_test( let mut child_runner = match runner_compiler.spawn() { Ok(child) => child, Err(error) => { - eprintln!("Failed to spawn {binary_path:?}: {error:?}"); + eprintln!("Failed to spawn {:?}: {error:?}", runner_compiler.get_program()); return (Duration::default(), Err(TestFailure::CompileError)); } }; diff --git a/tests/run-make/rustdoc-test-builder/foo.rs b/tests/run-make/rustdoc-test-builder/foo.rs new file mode 100644 index 0000000000000..51d17849fd718 --- /dev/null +++ b/tests/run-make/rustdoc-test-builder/foo.rs @@ -0,0 +1,3 @@ +//! ``` +//! let x = 12; +//! ``` diff --git a/tests/run-make/rustdoc-test-builder/rmake.rs b/tests/run-make/rustdoc-test-builder/rmake.rs new file mode 100644 index 0000000000000..c243b784eb9b2 --- /dev/null +++ b/tests/run-make/rustdoc-test-builder/rmake.rs @@ -0,0 +1,23 @@ +// This test ensures that if the rustdoc test binary is not executable, it will +// gracefully fail and not panic. + +//@ needs-target-std + +use run_make_support::{path, rfs, rustdoc}; + +fn main() { + let absolute_path = path("foo.rs").canonicalize().expect("failed to get absolute path"); + let output = rustdoc() + .input("foo.rs") + .arg("--test") + .arg("-Zunstable-options") + .arg("--test-builder") + .arg(&absolute_path) + .run_fail(); + + // We also double-check that we don't have the panic text in the output. + output.assert_stdout_contains("Failed to spawn "); + output.assert_stderr_not_contains("the compiler unexpectedly panicked. this is a bug."); + // Just in case... + output.assert_stdout_not_contains("the compiler unexpectedly panicked. this is a bug."); +} From e207006ad37d85b16929b16b843a81874eef7e4a Mon Sep 17 00:00:00 2001 From: Paul Kirth Date: Thu, 25 Sep 2025 12:47:36 -0700 Subject: [PATCH 03/14] Add default sanitizers to TargetOptions Some sanitizers are part of a system's ABI, like the shadow call stack on Aarch64 and RISC-V Fuchsia. Typically ABI options have other spellings, but LLVM has, for historical reasons, marked this as a sanitizer instead of an alternate ABI option. As a result, Fuchsia targets may not be compiled against the correct ABI unless this option is set. This hasn't caused correctness problems, since the backend reserves the SCS register, and thus preserves its value. But this is an issue for unwinding, as the SCS will not be an array of PCs describing the call complete call chain, and will have gaps from callers that don't use the correct ABI. In the long term, I'd like to see all the sanitizer configs that all frontends copy from clang moved into llvm's libFrontend, and exposed so that frontend consumers can use a small set of simple APIs to use sanitizers in a consistent way across the LLVM ecosystem, but that work is not yet ready today. --- compiler/rustc_codegen_llvm/src/abi.rs | 2 +- compiler/rustc_codegen_llvm/src/attributes.rs | 10 ++-------- compiler/rustc_codegen_ssa/src/back/link.rs | 8 ++------ compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_metadata/src/creader.rs | 10 +++++----- compiler/rustc_metadata/src/native_libs.rs | 2 +- compiler/rustc_session/src/config/cfg.rs | 2 +- compiler/rustc_session/src/options.rs | 11 ++++++----- compiler/rustc_session/src/session.rs | 10 +++++++--- compiler/rustc_target/src/spec/json.rs | 7 +++++++ compiler/rustc_target/src/spec/mod.rs | 8 ++++++++ .../src/spec/targets/aarch64_unknown_fuchsia.rs | 1 + .../src/spec/targets/riscv64gc_unknown_fuchsia.rs | 1 + 13 files changed, 43 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 3793a1470aada..6b296c3046ef3 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -96,7 +96,7 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&' } } } - } else if cx.tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) { + } else if cx.tcx.sess.sanitizers().contains(SanitizerSet::MEMORY) { // If we're not optimising, *but* memory sanitizer is on, emit noundef, since it affects // memory sanitizer's behavior. diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 209b8efa2c3b3..8092e9b9512d3 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -101,7 +101,7 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>( no_sanitize: SanitizerSet, ) -> SmallVec<[&'ll Attribute; 4]> { let mut attrs = SmallVec::new(); - let enabled = tcx.sess.opts.unstable_opts.sanitizer - no_sanitize; + let enabled = tcx.sess.sanitizers() - no_sanitize; if enabled.contains(SanitizerSet::ADDRESS) || enabled.contains(SanitizerSet::KERNELADDRESS) { attrs.push(llvm::AttributeKind::SanitizeAddress.create_attr(cx.llcx)); } @@ -240,13 +240,7 @@ fn probestack_attr<'ll, 'tcx>(cx: &SimpleCx<'ll>, tcx: TyCtxt<'tcx>) -> Option<& // Currently stack probes seem somewhat incompatible with the address // sanitizer and thread sanitizer. With asan we're already protected from // stack overflow anyway so we don't really need stack probes regardless. - if tcx - .sess - .opts - .unstable_opts - .sanitizer - .intersects(SanitizerSet::ADDRESS | SanitizerSet::THREAD) - { + if tcx.sess.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::THREAD) { return None; } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ea538d3d46981..5219ee1abe889 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1226,7 +1226,7 @@ fn add_sanitizer_libraries( return; } - let sanitizer = sess.opts.unstable_opts.sanitizer; + let sanitizer = sess.sanitizers(); if sanitizer.contains(SanitizerSet::ADDRESS) { link_sanitizer_runtime(sess, flavor, linker, "asan"); } @@ -2496,11 +2496,7 @@ fn add_order_independent_options( && crate_type == CrateType::Executable && !matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _)) { - let prefix = if sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::ADDRESS) { - "asan/" - } else { - "" - }; + let prefix = if sess.sanitizers().contains(SanitizerSet::ADDRESS) { "asan/" } else { "" }; cmd.link_arg(format!("--dynamic-linker={prefix}ld.so.1")); } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 368a2e307bb27..c1e80e08a0eb4 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -176,7 +176,7 @@ impl ModuleConfig { debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling, instrument_coverage: if_regular!(sess.instrument_coverage(), false), - sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()), + sanitizer: if_regular!(sess.sanitizers(), SanitizerSet::empty()), sanitizer_dataflow_abilist: if_regular!( sess.opts.unstable_opts.sanitizer_dataflow_abilist.clone(), Vec::new() diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 62de18072902e..4e2e1e21ec6dd 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -412,7 +412,7 @@ impl CStore { match (&left_name_val, &right_name_val) { (Some(l), Some(r)) => match l.1.opt.cmp(&r.1.opt) { cmp::Ordering::Equal => { - if !l.1.consistent(&tcx.sess.opts, Some(&r.1)) { + if !l.1.consistent(&tcx.sess, Some(&r.1)) { report_diff( &l.0.prefix, &l.0.name, @@ -424,26 +424,26 @@ impl CStore { right_name_val = None; } cmp::Ordering::Greater => { - if !r.1.consistent(&tcx.sess.opts, None) { + if !r.1.consistent(&tcx.sess, None) { report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name)); } right_name_val = None; } cmp::Ordering::Less => { - if !l.1.consistent(&tcx.sess.opts, None) { + if !l.1.consistent(&tcx.sess, None) { report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None); } left_name_val = None; } }, (Some(l), None) => { - if !l.1.consistent(&tcx.sess.opts, None) { + if !l.1.consistent(&tcx.sess, None) { report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None); } left_name_val = None; } (None, Some(r)) => { - if !r.1.consistent(&tcx.sess.opts, None) { + if !r.1.consistent(&tcx.sess, None) { report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name)); } right_name_val = None; diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 15572063d45a6..9044cc2737fd6 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -71,7 +71,7 @@ pub fn walk_native_lib_search_dirs( || sess.target.os == "linux" || sess.target.os == "fuchsia" || sess.target.is_like_aix - || sess.target.is_like_darwin && !sess.opts.unstable_opts.sanitizer.is_empty() + || sess.target.is_like_darwin && !sess.sanitizers().is_empty() { f(&sess.target_tlib_path.dir, false)?; } diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index a72f6201dcea2..ddf0dba730cbf 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -224,7 +224,7 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { ins_sym!(sym::relocation_model, sess.target.relocation_model.desc_symbol()); } - for mut s in sess.opts.unstable_opts.sanitizer { + for mut s in sess.sanitizers() { // KASAN is still ASAN under the hood, so it uses the same attribute. if s == SanitizerSet::KERNELADDRESS { s = SanitizerSet::ADDRESS; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index b89aec7d22a91..9c2fa2576c8e5 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -22,7 +22,7 @@ use rustc_target::spec::{ use crate::config::*; use crate::search_paths::SearchPath; use crate::utils::NativeLib; -use crate::{EarlyDiagCtxt, lint}; +use crate::{EarlyDiagCtxt, Session, lint}; macro_rules! insert { ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr) => { @@ -111,12 +111,12 @@ mod target_modifier_consistency_check { lparsed & tmod_sanitizers == rparsed & tmod_sanitizers } pub(super) fn sanitizer_cfi_normalize_integers( - opts: &Options, + sess: &Session, l: &TargetModifier, r: Option<&TargetModifier>, ) -> bool { // For kCFI, the helper flag -Zsanitizer-cfi-normalize-integers should also be a target modifier - if opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI) { + if sess.sanitizers().contains(SanitizerSet::KCFI) { if let Some(r) = r { return l.extend().tech_value == r.extend().tech_value; } else { @@ -133,7 +133,7 @@ impl TargetModifier { } // Custom consistency check for target modifiers (or default `l.tech_value == r.tech_value`) // When other is None, consistency with default value is checked - pub fn consistent(&self, opts: &Options, other: Option<&TargetModifier>) -> bool { + pub fn consistent(&self, sess: &Session, other: Option<&TargetModifier>) -> bool { assert!(other.is_none() || self.opt == other.unwrap().opt); match self.opt { OptionsTargetModifiers::UnstableOptions(unstable) => match unstable { @@ -142,7 +142,7 @@ impl TargetModifier { } UnstableOptionsTargetModifiers::sanitizer_cfi_normalize_integers => { return target_modifier_consistency_check::sanitizer_cfi_normalize_integers( - opts, self, other, + sess, self, other, ); } _ => {} @@ -2575,6 +2575,7 @@ written to standard error output)"), retpoline_external_thunk: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER], "enables retpoline-external-thunk, retpoline-indirect-branches and retpoline-indirect-calls \ target features (default: no)"), + #[rustc_lint_opt_deny_field_access("use `Session::sanitizers()` instead of this field")] sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED TARGET_MODIFIER], "use a sanitizer"), sanitizer_cfi_canonical_jump_tables: Option = (Some(true), parse_opt_bool, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 522faf1db9ff1..e1e20959f902b 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -323,7 +323,7 @@ impl Session { } pub fn is_sanitizer_cfi_enabled(&self) -> bool { - self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI) + self.sanitizers().contains(SanitizerSet::CFI) } pub fn is_sanitizer_cfi_canonical_jump_tables_disabled(&self) -> bool { @@ -347,7 +347,7 @@ impl Session { } pub fn is_sanitizer_kcfi_enabled(&self) -> bool { - self.opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI) + self.sanitizers().contains(SanitizerSet::KCFI) } pub fn is_split_lto_unit_enabled(&self) -> bool { @@ -527,7 +527,7 @@ impl Session { // AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs. // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables. // HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future. - || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS) + || self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS) } pub fn diagnostic_width(&self) -> usize { @@ -922,6 +922,10 @@ impl Session { min } } + + pub fn sanitizers(&self) -> SanitizerSet { + return self.opts.unstable_opts.sanitizer | self.target.options.default_sanitizers; + } } // JUSTIFICATION: part of session construction diff --git a/compiler/rustc_target/src/spec/json.rs b/compiler/rustc_target/src/spec/json.rs index f236be92b3b60..1bcf3ce409d2d 100644 --- a/compiler/rustc_target/src/spec/json.rs +++ b/compiler/rustc_target/src/spec/json.rs @@ -214,6 +214,11 @@ impl Target { supported_sanitizers.into_iter().fold(SanitizerSet::empty(), |a, b| a | b); } + if let Some(default_sanitizers) = json.default_sanitizers { + base.default_sanitizers = + default_sanitizers.into_iter().fold(SanitizerSet::empty(), |a, b| a | b); + } + forward!(generate_arange_section); forward!(supports_stack_protector); forward!(small_data_threshold_support); @@ -392,6 +397,7 @@ impl ToJson for Target { target_option_val!(split_debuginfo); target_option_val!(supported_split_debuginfo); target_option_val!(supported_sanitizers); + target_option_val!(default_sanitizers); target_option_val!(c_enum_min_bits); target_option_val!(generate_arange_section); target_option_val!(supports_stack_protector); @@ -612,6 +618,7 @@ struct TargetSpecJson { split_debuginfo: Option, supported_split_debuginfo: Option>, supported_sanitizers: Option>, + default_sanitizers: Option>, generate_arange_section: Option, supports_stack_protector: Option, small_data_threshold_support: Option, diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index b49e7fc9cff66..c753089b1d3d3 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2327,6 +2327,13 @@ pub struct TargetOptions { /// distributed with the target, the sanitizer should still appear in this list for the target. pub supported_sanitizers: SanitizerSet, + /// The sanitizers that are enabled by default on this target. + /// + /// Note that the support here is at a codegen level. If the machine code with sanitizer + /// enabled can generated on this target, but the necessary supporting libraries are not + /// distributed with the target, the sanitizer should still appear in this list for the target. + pub default_sanitizers: SanitizerSet, + /// Minimum number of bits in #[repr(C)] enum. Defaults to the size of c_int pub c_enum_min_bits: Option, @@ -2575,6 +2582,7 @@ impl Default for TargetOptions { // `Off` is supported by default, but targets can remove this manually, e.g. Windows. supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), supported_sanitizers: SanitizerSet::empty(), + default_sanitizers: SanitizerSet::empty(), c_enum_min_bits: None, generate_arange_section: true, supports_stack_protector: true, diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs index 8366b6d9bd824..6dbe376d02f86 100644 --- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs @@ -12,6 +12,7 @@ pub(crate) fn target() -> Target { | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::SHADOWCALLSTACK; + base.default_sanitizers = SanitizerSet::SHADOWCALLSTACK; base.supports_xray = true; base.add_pre_link_args( diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs index c4466e13d1439..28d2b4c54ef91 100644 --- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs +++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs @@ -9,6 +9,7 @@ pub(crate) fn target() -> Target { base.max_atomic_width = Some(64); base.stack_probes = StackProbeType::Inline; base.supported_sanitizers = SanitizerSet::SHADOWCALLSTACK; + base.default_sanitizers = SanitizerSet::SHADOWCALLSTACK; base.supports_xray = true; Target { From 3e8a433e314b5018b2251db0c8ba41039dda3c0f Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Sun, 12 Oct 2025 22:41:03 -0700 Subject: [PATCH 04/14] Add -Zannotate-moves for profiler visibility of move/copy operations This implements a new unstable compiler flag `-Zannotate-moves` that makes move and copy operations visible in profilers by creating synthetic debug information. This is achieved with zero runtime cost by manipulating debug info scopes to make moves/copies appear as calls to `compiler_move` and `compiler_copy` marker functions in profiling tools. This allows developers to identify expensive move/copy operations in their code using standard profiling tools, without requiring specialized tooling or runtime instrumentation. The implementation works at codegen time. When processing MIR operands (`Operand::Move` and `Operand::Copy`), the codegen creates an `OperandRef` with an optional `move_annotation` field containing an `Instance` of the appropriate profiling marker function. When storing the operand, `store_with_annotation()` wraps the store operation in a synthetic debug scope that makes it appear inlined from the marker. Two marker functions (`compiler_move` and `compiler_copy`) are defined in `library/core/src/profiling.rs`. These are never actually called - they exist solely as debug info anchors. Operations are only annotated if the type: - Meets the size threshold (default: 65 bytes, configurable via `-Zannotate-moves=SIZE`) - Has a non-scalar backend representation (scalars use registers, not memcpy) This has a very small size impact on object file size. With the default limit it's well under 0.1%, and even with a very small limit of 8 bytes it's still ~1.5%. This could be enabled by default. --- compiler/rustc_codegen_gcc/src/builder.rs | 2 +- compiler/rustc_codegen_gcc/src/debuginfo.rs | 2 +- compiler/rustc_codegen_llvm/src/abi.rs | 2 +- compiler/rustc_codegen_llvm/src/builder.rs | 2 +- .../rustc_codegen_llvm/src/debuginfo/mod.rs | 53 ++++- compiler/rustc_codegen_ssa/src/mir/block.rs | 14 +- compiler/rustc_codegen_ssa/src/mir/mod.rs | 2 + compiler/rustc_codegen_ssa/src/mir/operand.rs | 122 ++++++++++- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 47 +++-- .../rustc_codegen_ssa/src/traits/builder.rs | 2 +- .../rustc_codegen_ssa/src/traits/debuginfo.rs | 16 +- compiler/rustc_hir/src/lang_items.rs | 4 + compiler/rustc_interface/src/tests.rs | 3 +- compiler/rustc_session/src/config.rs | 25 ++- compiler/rustc_session/src/options.rs | 28 +++ compiler/rustc_span/src/symbol.rs | 2 + library/core/src/lib.rs | 2 + library/core/src/profiling.rs | 33 +++ .../src/compiler-flags/annotate-moves.md | 92 +++++++++ .../annotate-moves/call-arg-scope.rs | 114 +++++++++++ tests/codegen-llvm/annotate-moves/disabled.rs | 35 ++++ .../annotate-moves/integration.rs | 192 ++++++++++++++++++ .../codegen-llvm/annotate-moves/size-limit.rs | 112 ++++++++++ .../ui/annotate-moves/annotate-moves-basic.rs | 15 ++ .../annotate-moves-invalid-flag.rs | 10 + .../annotate-moves-invalid-flag.stderr | 2 + .../annotate-moves-size-limit-invalid.rs | 10 + .../annotate-moves-size-limit-invalid.stderr | 2 + 28 files changed, 897 insertions(+), 48 deletions(-) create mode 100644 library/core/src/profiling.rs create mode 100644 src/doc/unstable-book/src/compiler-flags/annotate-moves.md create mode 100644 tests/codegen-llvm/annotate-moves/call-arg-scope.rs create mode 100644 tests/codegen-llvm/annotate-moves/disabled.rs create mode 100644 tests/codegen-llvm/annotate-moves/integration.rs create mode 100644 tests/codegen-llvm/annotate-moves/size-limit.rs create mode 100644 tests/ui/annotate-moves/annotate-moves-basic.rs create mode 100644 tests/ui/annotate-moves/annotate-moves-invalid-flag.rs create mode 100644 tests/ui/annotate-moves/annotate-moves-invalid-flag.stderr create mode 100644 tests/ui/annotate-moves/annotate-moves-size-limit-invalid.rs create mode 100644 tests/ui/annotate-moves/annotate-moves-size-limit-invalid.stderr diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 5657620879ca1..86031a8a46342 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1069,7 +1069,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { OperandValue::Ref(place.val) }; - OperandRef { val, layout: place.layout } + OperandRef { val, layout: place.layout, move_annotation: None } } fn write_operand_repeatedly( diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs index 0f015cc23f52f..3979f62987f2c 100644 --- a/compiler/rustc_codegen_gcc/src/debuginfo.rs +++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs @@ -19,7 +19,7 @@ use crate::context::CodegenCx; pub(super) const UNKNOWN_LINE_NUMBER: u32 = 0; pub(super) const UNKNOWN_COLUMN_NUMBER: u32 = 0; -impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> { +impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // FIXME(eddyb) find a common convention for all of the debuginfo-related // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). fn dbg_var_addr( diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 3793a1470aada..77bbdcf3ff815 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -253,7 +253,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { ); bx.lifetime_end(llscratch, scratch_size); } - _ => { + PassMode::Pair(..) | PassMode::Direct { .. } => { OperandRef::from_immediate_or_packed_pair(bx, val, self.layout).val.store(bx, dst); } } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 49d38e05c8b06..42e03e9835e35 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -751,7 +751,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { OperandValue::Ref(place.val) }; - OperandRef { val, layout: place.layout } + OperandRef { val, layout: place.layout, move_annotation: None } } fn write_operand_repeatedly( diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index b95ad03b70e03..c2c55ee2b64f9 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -146,7 +146,7 @@ impl<'ll> Builder<'_, 'll, '_> { } } -impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { +impl<'ll, 'tcx> DebugInfoBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // FIXME(eddyb) find a common convention for all of the debuginfo-related // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). fn dbg_var_addr( @@ -284,6 +284,57 @@ impl<'ll> DebugInfoBuilderMethods for Builder<'_, 'll, '_> { llvm::set_value_name(value, name.as_bytes()); } } + + /// Annotate move/copy operations with debug info for profiling. + /// + /// This creates a temporary debug scope that makes the move/copy appear as an inlined call to + /// `compiler_move()` or `compiler_copy()`. The provided closure is executed + /// with this temporary debug location active. + /// + /// The `instance` parameter should be the monomorphized instance of the `compiler_move` or + /// `compiler_copy` function with the actual type and size. + fn with_move_annotation( + &mut self, + instance: ty::Instance<'tcx>, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + // Save the current debug location + let saved_loc = self.get_dbg_loc(); + + // Create a DIScope for the compiler_move/compiler_copy function + // We use the function's FnAbi for debug info generation + let fn_abi = self + .cx() + .tcx + .fn_abi_of_instance( + self.cx().typing_env().as_query_input((instance, ty::List::empty())), + ) + .unwrap(); + + let di_scope = self.cx().dbg_scope_fn(instance, fn_abi, None); + + // Create an inlined debug location: + // - scope: the compiler_move/compiler_copy function + // - inlined_at: the current location (where the move/copy actually occurs) + // - span: use the function's definition span + let fn_span = self.cx().tcx.def_span(instance.def_id()); + let inlined_loc = self.cx().dbg_loc(di_scope, saved_loc, fn_span); + + // Set the temporary debug location + self.set_dbg_loc(inlined_loc); + + // Execute the closure (which will generate the memcpy) + let result = f(self); + + // Restore the original debug location + if let Some(loc) = saved_loc { + self.set_dbg_loc(loc); + } else { + self.clear_dbg_loc(); + } + + result + } } /// A source code location used to generate debug information. diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 0d1e27a34dc5b..cce33107e2c27 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -557,9 +557,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let op = match self.locals[mir::RETURN_PLACE] { LocalRef::Operand(op) => op, LocalRef::PendingOperand => bug!("use of return before def"), - LocalRef::Place(cg_place) => { - OperandRef { val: Ref(cg_place.val), layout: cg_place.layout } - } + LocalRef::Place(cg_place) => OperandRef { + val: Ref(cg_place.val), + layout: cg_place.layout, + move_annotation: None, + }, LocalRef::UnsizedPlace(_) => bug!("return type must be sized"), }; let llslot = match op.val { @@ -1155,7 +1157,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { | (&mir::Operand::Constant(_), Ref(PlaceValue { llextra: None, .. })) => { let tmp = PlaceRef::alloca(bx, op.layout); bx.lifetime_start(tmp.val.llval, tmp.layout.size); - op.val.store(bx, tmp); + op.store_with_annotation(bx, tmp); op.val = Ref(tmp.val); lifetime_ends_after_call.push((tmp.val.llval, tmp.layout.size)); } @@ -1563,13 +1565,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align); bx.lifetime_start(scratch.llval, arg.layout.size); - op.val.store(bx, scratch.with_type(arg.layout)); + op.store_with_annotation(bx, scratch.with_type(arg.layout)); lifetime_ends_after_call.push((scratch.llval, arg.layout.size)); (scratch.llval, scratch.align, true) } PassMode::Cast { .. } => { let scratch = PlaceRef::alloca(bx, arg.layout); - op.val.store(bx, scratch); + op.store_with_annotation(bx, scratch); (scratch.val.llval, scratch.val.align, true) } _ => (op.immediate_or_packed_pair(bx), arg.layout.align.abi, false), diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 1670e2da71fb3..819abb9ae644d 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -480,6 +480,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( return local(OperandRef { val: OperandValue::Pair(a, b), layout: arg.layout, + move_annotation: None, }); } _ => {} @@ -552,6 +553,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx.caller_location = Some(OperandRef { val: OperandValue::Immediate(bx.get_param(llarg_idx)), layout: arg.layout, + move_annotation: None, }); } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 88a8e2a844cbc..5a139702f81d9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -5,12 +5,13 @@ use rustc_abi as abi; use rustc_abi::{ Align, BackendRepr, FIRST_VARIANT, FieldIdx, Primitive, Size, TagEncoding, VariantIdx, Variants, }; +use rustc_hir::LangItem; use rustc_middle::mir::interpret::{Pointer, Scalar, alloc_range}; use rustc_middle::mir::{self, ConstValue}; -use rustc_middle::ty::Ty; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::{self, Ty}; use rustc_middle::{bug, span_bug}; -use rustc_session::config::OptLevel; +use rustc_session::config::{AnnotateMoves, DebugInfo, OptLevel}; use tracing::{debug, instrument}; use super::place::{PlaceRef, PlaceValue}; @@ -131,6 +132,10 @@ pub struct OperandRef<'tcx, V> { /// The layout of value, based on its Rust type. pub layout: TyAndLayout<'tcx>, + + /// Annotation for profiler visibility of move/copy operations. + /// When set, the store operation should appear as an inlined call to this function. + pub move_annotation: Option>, } impl fmt::Debug for OperandRef<'_, V> { @@ -142,7 +147,7 @@ impl fmt::Debug for OperandRef<'_, V> { impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { pub fn zero_sized(layout: TyAndLayout<'tcx>) -> OperandRef<'tcx, V> { assert!(layout.is_zst()); - OperandRef { val: OperandValue::ZeroSized, layout } + OperandRef { val: OperandValue::ZeroSized, layout, move_annotation: None } } pub(crate) fn from_const>( @@ -180,7 +185,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { } }; - OperandRef { val, layout } + OperandRef { val, layout, move_annotation: None } } fn from_const_alloc>( @@ -214,7 +219,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { let size = s.size(bx); assert_eq!(size, layout.size, "abi::Scalar size does not match layout size"); let val = read_scalar(offset, size, s, bx.immediate_backend_type(layout)); - OperandRef { val: OperandValue::Immediate(val), layout } + OperandRef { val: OperandValue::Immediate(val), layout, move_annotation: None } } BackendRepr::ScalarPair( a @ abi::Scalar::Initialized { .. }, @@ -235,7 +240,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { b, bx.scalar_pair_element_backend_type(layout, 1, true), ); - OperandRef { val: OperandValue::Pair(a_val, b_val), layout } + OperandRef { val: OperandValue::Pair(a_val, b_val), layout, move_annotation: None } } _ if layout.is_zst() => OperandRef::zero_sized(layout), _ => { @@ -285,6 +290,22 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { self.val.deref(layout.align.abi).with_type(layout) } + /// Store this operand into a place, applying move/copy annotation if present. + /// + /// This is the preferred method for storing operands, as it automatically + /// applies profiler annotations for tracked move/copy operations. + pub fn store_with_annotation>( + self, + bx: &mut Bx, + dest: PlaceRef<'tcx, V>, + ) { + if let Some(instance) = self.move_annotation { + bx.with_move_annotation(instance, |bx| self.val.store(bx, dest)) + } else { + self.val.store(bx, dest) + } + } + /// If this operand is a `Pair`, we return an aggregate with the two values. /// For other cases, see `immediate`. pub fn immediate_or_packed_pair>( @@ -320,7 +341,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { } else { OperandValue::Immediate(llval) }; - OperandRef { val, layout } + OperandRef { val, layout, move_annotation: None } } pub(crate) fn extract_field>( @@ -388,7 +409,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { }) }; - OperandRef { val, layout: field } + OperandRef { val, layout: field, move_annotation: None } } /// Obtain the actual discriminant of a value. @@ -828,10 +849,15 @@ impl<'a, 'tcx, V: CodegenObject> OperandRefBuilder<'tcx, V> { } }, }; - OperandRef { val, layout } + OperandRef { val, layout, move_annotation: None } } } +/// Default size limit for move/copy annotations (in bytes). 64 bytes is a common size of a cache +/// line, and the assumption is that anything this size or below is very cheap to move/copy, so only +/// annotate copies larger than this. +const MOVE_ANNOTATION_DEFAULT_LIMIT: u64 = 65; + impl<'a, 'tcx, V: CodegenObject> OperandValue { /// Returns an `OperandValue` that's generally UB to use in any way. /// @@ -961,7 +987,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { abi::Variants::Single { index: vidx }, ); let layout = o.layout.for_variant(bx.cx(), vidx); - o = OperandRef { val: o.val, layout } + o = OperandRef { layout, ..o } } _ => return None, } @@ -1014,7 +1040,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { match *operand { mir::Operand::Copy(ref place) | mir::Operand::Move(ref place) => { - self.codegen_consume(bx, place.as_ref()) + let kind = match operand { + mir::Operand::Move(_) => LangItem::CompilerMove, + mir::Operand::Copy(_) => LangItem::CompilerCopy, + _ => unreachable!(), + }; + + // Check if we should annotate this move/copy for profiling + let move_annotation = self.move_copy_annotation_instance(bx, place.as_ref(), kind); + + OperandRef { move_annotation, ..self.codegen_consume(bx, place.as_ref()) } } mir::Operand::Constant(ref constant) => { @@ -1030,6 +1065,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { return OperandRef { val: OperandValue::Immediate(llval), layout: bx.layout_of(ty), + move_annotation: None, }; } } @@ -1037,4 +1073,68 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } } + + /// Creates an `Instance` for annotating a move/copy operation at codegen time. + /// + /// Returns `Some(instance)` if the operation should be annotated with debug info, `None` + /// otherwise. The instance represents a monomorphized `compiler_move` or + /// `compiler_copy` function that can be used to create debug scopes. + /// + /// There are a number of conditions that must be met for an annotation to be created, but aside + /// from the basics (annotation is enabled, we're generating debuginfo), the primary concern is + /// moves/copies which could result in a real `memcpy`. So we check for the size limit, but also + /// that the underlying representation of the type is in memory. + fn move_copy_annotation_instance( + &self, + bx: &Bx, + place: mir::PlaceRef<'tcx>, + kind: LangItem, + ) -> Option> { + let tcx = bx.tcx(); + let sess = tcx.sess; + + // Skip if we're not generating debuginfo + if sess.opts.debuginfo == DebugInfo::None { + return None; + } + + // Check if annotation is enabled and get size limit (otherwise skip) + let size_limit = match sess.opts.unstable_opts.annotate_moves { + AnnotateMoves::Disabled => return None, + AnnotateMoves::Enabled(None) => MOVE_ANNOTATION_DEFAULT_LIMIT, + AnnotateMoves::Enabled(Some(limit)) => limit, + }; + + let ty = self.monomorphized_place_ty(place); + let layout = bx.cx().layout_of(ty); + let ty_size = layout.size.bytes(); + + // Only annotate if type has a memory representation and exceeds size limit (and has a + // non-zero size) + if layout.is_zst() + || ty_size < size_limit + || !matches!(layout.backend_repr, BackendRepr::Memory { .. }) + { + return None; + } + + // Look up the DefId for compiler_move or compiler_copy lang item + let def_id = tcx.lang_items().get(kind)?; + + // Create generic args: compiler_move or compiler_copy + let size_const = ty::Const::from_target_usize(tcx, ty_size); + let generic_args = tcx.mk_args(&[ty.into(), size_const.into()]); + + // Create the Instance + let typing_env = self.mir.typing_env(tcx); + let instance = ty::Instance::expect_resolve( + tcx, + typing_env, + def_id, + generic_args, + rustc_span::DUMMY_SP, // span only used for error messages + ); + + Some(instance) + } } diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 640f7211dc994..e31dc86b926f2 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -36,7 +36,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } // FIXME: consider not copying constants through stack. (Fixable by codegen'ing // constants into `OperandValue::Ref`; why don’t we do that yet if we don’t?) - cg_operand.val.store(bx, dest); + cg_operand.store_with_annotation(bx, dest); } mir::Rvalue::Cast( @@ -50,7 +50,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Into-coerce of a thin pointer to a wide pointer -- just // use the operand path. let temp = self.codegen_rvalue_operand(bx, rvalue); - temp.val.store(bx, dest); + temp.store_with_annotation(bx, dest); return; } @@ -70,7 +70,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { debug!("codegen_rvalue: creating ugly alloca"); let scratch = PlaceRef::alloca(bx, operand.layout); scratch.storage_live(bx); - operand.val.store(bx, scratch); + operand.store_with_annotation(bx, scratch); base::coerce_unsized_into(bx, scratch, dest); scratch.storage_dead(bx); } @@ -183,7 +183,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { variant_dest.project_field(bx, field_index.as_usize()) }; - op.val.store(bx, field); + op.store_with_annotation(bx, field); } } dest.codegen_set_discr(bx, variant_index); @@ -191,7 +191,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => { let temp = self.codegen_rvalue_operand(bx, rvalue); - temp.val.store(bx, dest); + temp.store_with_annotation(bx, dest); } } } @@ -221,7 +221,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // Since in this path we have a place anyway, we can store or copy to it, // making sure we use the destination place's alignment even if the // source would normally have a higher one. - src.val.store(bx, dst.val.with_type(src.layout)); + src.store_with_annotation(bx, dst.val.with_type(src.layout)); } } @@ -320,7 +320,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let size = Ord::max(operand.layout.size, cast.size); let temp = PlaceValue::alloca(bx, size, align); bx.lifetime_start(temp.llval, size); - operand.val.store(bx, temp.with_type(operand.layout)); + operand.store_with_annotation(bx, temp.with_type(operand.layout)); let val = bx.load_operand(temp.with_type(cast)).val; bx.lifetime_end(temp.llval, size); val @@ -478,7 +478,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let to_backend_ty = bx.cx().immediate_backend_type(cast); if operand.layout.is_uninhabited() { let val = OperandValue::Immediate(bx.cx().const_poison(to_backend_ty)); - return OperandRef { val, layout: cast }; + return OperandRef { val, layout: cast, move_annotation: None }; } let abi::BackendRepr::Scalar(to_scalar) = cast.layout.backend_repr else { bug!("Found non-scalar for cast {cast:?}"); @@ -494,7 +494,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.codegen_transmute_operand(bx, operand, cast) } }; - OperandRef { val, layout: cast } + OperandRef { val, layout: cast, move_annotation: None } } mir::Rvalue::Ref(_, bk, place) => { @@ -525,7 +525,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ); let val_ty = op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty); let operand_ty = Ty::new_tup(bx.tcx(), &[val_ty, bx.tcx().types.bool]); - OperandRef { val: result, layout: bx.cx().layout_of(operand_ty) } + OperandRef { + val: result, + layout: bx.cx().layout_of(operand_ty), + move_annotation: None, + } } mir::Rvalue::BinaryOp(op, box (ref lhs, ref rhs)) => { let lhs = self.codegen_operand(bx, lhs); @@ -559,6 +563,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandRef { val: OperandValue::Immediate(llresult), layout: bx.cx().layout_of(op.ty(bx.tcx(), lhs.layout.ty, rhs.layout.ty)), + move_annotation: None, } } @@ -593,7 +598,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { val.is_expected_variant_for_type(self.cx, layout), "Made wrong variant {val:?} for type {layout:?}", ); - OperandRef { val, layout } + OperandRef { val, layout, move_annotation: None } } mir::Rvalue::Discriminant(ref place) => { @@ -604,6 +609,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandRef { val: OperandValue::Immediate(discr), layout: self.cx.layout_of(discr_ty), + move_annotation: None, } } @@ -631,6 +637,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandRef { val: OperandValue::Immediate(val), layout: self.cx.layout_of(null_op.ty(tcx)), + move_annotation: None, } } @@ -663,7 +670,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } else { bx.get_static(def_id) }; - OperandRef { val: OperandValue::Immediate(static_), layout } + OperandRef { val: OperandValue::Immediate(static_), layout, move_annotation: None } } mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand), mir::Rvalue::Repeat(ref elem, len_const) => { @@ -675,7 +682,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let array_ty = self.monomorphize(array_ty); let array_layout = bx.layout_of(array_ty); assert!(array_layout.is_zst()); - OperandRef { val: OperandValue::ZeroSized, layout: array_layout } + OperandRef { + val: OperandValue::ZeroSized, + layout: array_layout, + move_annotation: None, + } } mir::Rvalue::Aggregate(ref kind, ref fields) => { let (variant_index, active_field_index) = match **kind { @@ -704,7 +715,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // more optimizability, if that turns out to be helpful. bx.abort(); let val = OperandValue::poison(bx, layout); - OperandRef { val, layout } + OperandRef { val, layout, move_annotation: None } } Ok(maybe_tag_value) => { if let Some((tag_field, tag_imm)) = maybe_tag_value { @@ -718,7 +729,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let operand = self.codegen_operand(bx, operand); let binder_ty = self.monomorphize(binder_ty); let layout = bx.cx().layout_of(binder_ty); - OperandRef { val: operand.val, layout } + OperandRef { val: operand.val, layout, move_annotation: None } } mir::Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in codegen"), mir::Rvalue::ShallowInitBox(..) => bug!("`ShallowInitBox` in codegen"), @@ -745,7 +756,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { "Address of place was unexpectedly {val:?} for pointee type {ty:?}", ); - OperandRef { val, layout: self.cx.layout_of(mk_ptr_ty(self.cx.tcx(), ty)) } + OperandRef { + val, + layout: self.cx.layout_of(mk_ptr_ty(self.cx.tcx(), ty)), + move_annotation: None, + } } fn codegen_scalar_binop( diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index 60296e36e0c1a..f57f9108f744b 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -37,7 +37,7 @@ pub trait BuilderMethods<'a, 'tcx>: + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>> + Deref + CoverageInfoBuilderMethods<'tcx> - + DebugInfoBuilderMethods + + DebugInfoBuilderMethods<'tcx> + ArgAbiBuilderMethods<'tcx> + AbiBuilderMethods + IntrinsicCallBuilderMethods<'tcx> diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs index a4da6c915deec..268d863dcbd2c 100644 --- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs +++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs @@ -64,7 +64,7 @@ pub trait DebugInfoCodegenMethods<'tcx>: BackendTypes { ) -> Self::DIVariable; } -pub trait DebugInfoBuilderMethods: BackendTypes { +pub trait DebugInfoBuilderMethods<'tcx>: BackendTypes { // FIXME(eddyb) find a common convention for all of the debuginfo-related // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.). fn dbg_var_addr( @@ -95,4 +95,18 @@ pub trait DebugInfoBuilderMethods: BackendTypes { fn clear_dbg_loc(&mut self); fn insert_reference_to_gdb_debug_scripts_section_global(&mut self); fn set_var_name(&mut self, value: Self::Value, name: &str); + + /// Hook to allow move/copy operations to be annotated for profiling. + /// + /// The `instance` parameter should be the monomorphized instance of the + /// `compiler_move` or `compiler_copy` function with the actual type and size. + /// + /// Default implementation does no annotation (just executes the closure). + fn with_move_annotation( + &mut self, + _instance: Instance<'tcx>, + f: impl FnOnce(&mut Self) -> R, + ) -> R { + f(self) + } } diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 9f7f4c7583412..e454ed58699c9 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -345,6 +345,10 @@ language_item_table! { EhPersonality, sym::eh_personality, eh_personality, Target::Fn, GenericRequirement::None; EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None; + // Profiling markers for move/copy operations (used by -Z annotate-moves) + CompilerMove, sym::compiler_move, compiler_move_fn, Target::Fn, GenericRequirement::Exact(2); + CompilerCopy, sym::compiler_copy, compiler_copy_fn, Target::Fn, GenericRequirement::Exact(2); + OwnedBox, sym::owned_box, owned_box, Target::Struct, GenericRequirement::Minimum(1); GlobalAlloc, sym::global_alloc_ty, global_alloc_ty, Target::Struct, GenericRequirement::None; diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 6c08b37dec083..fcba546c87b70 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -10,7 +10,7 @@ use rustc_errors::emitter::HumanReadableErrorType; use rustc_errors::{ColorConfig, registry}; use rustc_hir::attrs::NativeLibKind; use rustc_session::config::{ - AutoDiff, BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel, + AnnotateMoves, AutoDiff, BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel, CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, FmtDebug, FunctionReturn, InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli, MirIncludeSpans, @@ -764,6 +764,7 @@ fn test_unstable_options_tracking_hash() { // tidy-alphabetical-start tracked!(allow_features, Some(vec![String::from("lang_items")])); tracked!(always_encode_mir, true); + tracked!(annotate_moves, AnnotateMoves::Enabled(Some(1234))); tracked!(assume_incomplete_release, true); tracked!(autodiff, vec![AutoDiff::Enable, AutoDiff::NoTT]); tracked!(binary_dep_depinfo, true); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index ce6f6434e793d..a9d96586890e4 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -262,6 +262,16 @@ pub enum AutoDiff { NoTT, } +/// The different settings that the `-Z annotate-moves` flag can have. +#[derive(Clone, Copy, PartialEq, Hash, Debug)] +pub enum AnnotateMoves { + /// `-Z annotate-moves=no` (or `off`, `false` etc.) + Disabled, + /// `-Z annotate-moves` or `-Z annotate-moves=yes` (use default size limit) + /// `-Z annotate-moves=SIZE` (use specified size limit) + Enabled(Option), +} + /// Settings for `-Z instrument-xray` flag. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] pub struct InstrumentXRay { @@ -3239,13 +3249,13 @@ pub(crate) mod dep_tracking { }; use super::{ - AutoDiff, BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, CoverageOptions, - CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, FunctionReturn, - InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail, - LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OomStrategy, OptLevel, OutFileName, - OutputType, OutputTypes, PatchableFunctionEntry, Polonius, RemapPathScopeComponents, - ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, SwitchWithOptPath, - SymbolManglingVersion, WasiExecModel, + AnnotateMoves, AutoDiff, BranchProtection, CFGuard, CFProtection, CollapseMacroDebuginfo, + CoverageOptions, CrateType, DebugInfo, DebugInfoCompression, ErrorOutputType, FmtDebug, + FunctionReturn, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, + LocationDetail, LtoCli, MirStripDebugInfo, NextSolverConfig, Offload, OomStrategy, + OptLevel, OutFileName, OutputType, OutputTypes, PatchableFunctionEntry, Polonius, + RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind, + SwitchWithOptPath, SymbolManglingVersion, WasiExecModel, }; use crate::lint; use crate::utils::NativeLib; @@ -3288,6 +3298,7 @@ pub(crate) mod dep_tracking { impl_dep_tracking_hash_via_hash!( (), + AnnotateMoves, AutoDiff, Offload, bool, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c9d73adf31d49..893302bb1338d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -864,6 +864,8 @@ mod desc { pub(crate) const parse_linker_features: &str = "a list of enabled (`+` prefix) and disabled (`-` prefix) features: `lld`"; pub(crate) const parse_polonius: &str = "either no value or `legacy` (the default), or `next`"; + pub(crate) const parse_annotate_moves: &str = + "either a boolean (`yes`, `no`, `on`, `off`, etc.), or a size limit in bytes"; pub(crate) const parse_stack_protector: &str = "one of (`none` (default), `basic`, `strong`, or `all`)"; pub(crate) const parse_branch_protection: &str = "a `,` separated combination of `bti`, `gcs`, `pac-ret`, (optionally with `pc`, `b-key`, `leaf` if `pac-ret` is set)"; @@ -949,6 +951,29 @@ pub mod parse { } } + pub(crate) fn parse_annotate_moves(slot: &mut AnnotateMoves, v: Option<&str>) -> bool { + let mut bslot = false; + let mut nslot = 0u64; + + *slot = match v { + // No value provided: -Z annotate-moves (enable with default limit) + None => AnnotateMoves::Enabled(None), + // Explicit boolean value provided: -Z annotate-moves=yes/no + s @ Some(_) if parse_bool(&mut bslot, s) => { + if bslot { + AnnotateMoves::Enabled(None) + } else { + AnnotateMoves::Disabled + } + } + // With numeric limit provided: -Z annotate-moves=1234 + s @ Some(_) if parse_number(&mut nslot, s) => AnnotateMoves::Enabled(Some(nslot)), + _ => return false, + }; + + true + } + /// Use this for any string option that has a static default. pub(crate) fn parse_string(slot: &mut String, v: Option<&str>) -> bool { match v { @@ -2198,6 +2223,9 @@ options! { "only allow the listed language features to be enabled in code (comma separated)"), always_encode_mir: bool = (false, parse_bool, [TRACKED], "encode MIR of all functions into the crate metadata (default: no)"), + annotate_moves: AnnotateMoves = (AnnotateMoves::Disabled, parse_annotate_moves, [TRACKED], + "emit debug info for compiler-generated move and copy operations \ + to make them visible in profilers. Can be a boolean or a size limit in bytes (default: disabled)"), assert_incr_state: Option = (None, parse_opt_string, [UNTRACKED], "assert that the incremental cache is in given state: \ either `loaded` or `not-loaded`."), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 86b6bb16835b9..f2cc68cf7f965 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -695,7 +695,9 @@ symbols! { compile_error, compiler, compiler_builtins, + compiler_copy, compiler_fence, + compiler_move, concat, concat_bytes, concat_idents, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f1948fc778ce2..121d26c8a3e3f 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -282,6 +282,8 @@ pub mod num; pub mod hint; pub mod intrinsics; pub mod mem; +#[unstable(feature = "profiling_marker_api", issue = "148197")] +pub mod profiling; pub mod ptr; #[unstable(feature = "ub_checks", issue = "none")] pub mod ub_checks; diff --git a/library/core/src/profiling.rs b/library/core/src/profiling.rs new file mode 100644 index 0000000000000..db4a62480a3a1 --- /dev/null +++ b/library/core/src/profiling.rs @@ -0,0 +1,33 @@ +//! Profiling markers for compiler instrumentation. + +/// Profiling marker for move operations. +/// +/// This function is never called at runtime. When `-Z annotate-moves` is enabled, +/// the compiler creates synthetic debug info that makes move operations appear as +/// calls to this function in profilers. +/// +/// The `SIZE` parameter encodes the size of the type being copied. It's the same as +/// `size_of::()`, and is only present for convenience. +#[unstable(feature = "profiling_marker_api", issue = "148197")] +#[lang = "compiler_move"] +pub fn compiler_move(_src: *const T, _dst: *mut T) { + unreachable!( + "compiler_move marks where the compiler-generated a memcpy for moves. It is never actually called." + ) +} + +/// Profiling marker for copy operations. +/// +/// This function is never called at runtime. When `-Z annotate-moves` is enabled, +/// the compiler creates synthetic debug info that makes copy operations appear as +/// calls to this function in profilers. +/// +/// The `SIZE` parameter encodes the size of the type being copied. It's the same as +/// `size_of::()`, and is only present for convenience. +#[unstable(feature = "profiling_marker_api", issue = "148197")] +#[lang = "compiler_copy"] +pub fn compiler_copy(_src: *const T, _dst: *mut T) { + unreachable!( + "compiler_copy marks where the compiler-generated a memcpy for Copies. It is never actually called." + ) +} diff --git a/src/doc/unstable-book/src/compiler-flags/annotate-moves.md b/src/doc/unstable-book/src/compiler-flags/annotate-moves.md new file mode 100644 index 0000000000000..46d8faf18fa07 --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/annotate-moves.md @@ -0,0 +1,92 @@ +# `annotate-moves` + +The tracking issue for this feature is: [#148197](https://github.com/rust-lang/rust/issues/148197). + +------------------------ + + +The `-Z annotate-moves` flag enables annotation of compiler-generated +move and copy operations, making them visible in profilers and stack traces +for performance debugging. + +When enabled, the compiler manipulates debug info to make large move and copy +operations appear as if they were inlined calls to `core::profiling::compiler_move` +and `core::profiling::compiler_copy`. No actual function calls are generated - +this is purely a debug info transformation that makes expensive memory operations +visible in profilers and stack traces. + +## Syntax + +```bash +rustc -Z annotate-moves[=] +``` + +Where `` can be: +- A boolean: `true`, `false`, `yes`, `no`, `on`, `off` +- A number: size threshold in bytes (e.g., `128`) +- Omitted: enables with default threshold (65 bytes) + +## Options + +- `-Z annotate-moves` or `-Z annotate-moves=true`: Enable with default size limit +- `-Z annotate-moves=false`: Disable annotation +- `-Z annotate-moves=N`: Enable with custom size limit of N bytes + +## Examples + +```bash +# Enable annotation with default threshold (65 bytes) +rustc -Z annotate-moves main.rs + +# Enable with custom 128-byte threshold +rustc -Z annotate-moves=128 main.rs + +# Only annotate very large moves (1KB+) +rustc -Z annotate-moves=1024 main.rs + +# Explicitly disable +rustc -Z annotate-moves=false main.rs +``` + +## Behavior + +The annotation only applies to: +- Types equal or larger than the specified size threshold +- Non-immediate types (those that would generate `memcpy`) +- Operations that actually move/copy data (not ZST types) + +Stack traces will show the operations: +```text +0: memcpy +1: core::profiling::compiler_move:: +2: my_function +``` + +The `compiler_move` and `compiler_copy` functions have two generic parameters: +the type being moved/copied and its size in bytes. The size is identical to +`size_of::()`, and is present just so that it's easy to immediately tell how +large the copy is. + +Note that this requires v0 mangling to be properly encoded; legacy mangling does +not substitute these with a specific type and size. + +## Example + +```rust +#[derive(Clone)] +struct LargeData { + buffer: [u8; 1000], +} + +fn example() { + let data = LargeData { buffer: [0; 1000] }; + let copy = data.clone(); // Shows as compiler_copy in profiler + let moved = data; // Shows as compiler_move in profiler +} +``` + +## Overhead + +This has no effect on generated code; it only adds debuginfo. The overhead is +typically very small; on rustc itself, the default limit of 65 bytes adds about +0.055% to the binary size. diff --git a/tests/codegen-llvm/annotate-moves/call-arg-scope.rs b/tests/codegen-llvm/annotate-moves/call-arg-scope.rs new file mode 100644 index 0000000000000..527ab0b09d7c8 --- /dev/null +++ b/tests/codegen-llvm/annotate-moves/call-arg-scope.rs @@ -0,0 +1,114 @@ +//@ compile-flags: -Z annotate-moves=8 -Copt-level=0 -g +// +// This test verifies that function call and return instructions use the correct debug scopes +// when passing/returning large values. The actual move/copy operations may be annotated, +// but the CALL and RETURN instructions themselves should reference the source location, +// NOT have an inlinedAt scope pointing to compiler_move/compiler_copy. + +#![crate_type = "lib"] + +#[derive(Clone, Copy)] +pub struct LargeStruct { + pub data: [u64; 20], // 160 bytes +} + +#[derive(Clone, Copy)] +pub struct MediumStruct { + pub data: [u64; 5], // 40 bytes +} + +pub struct SmallStruct { + pub x: u32, // 4 bytes +} + +// ============================================================================ +// Test 1: Single argument call +// ============================================================================ + +// CHECK-LABEL: call_arg_scope::test_call_with_single_arg +pub fn test_call_with_single_arg(s: LargeStruct) { + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CALL1_ARG_LOC:]] + // CHECK: call {{.*}}@{{.*}}helper_single{{.*}}({{.*}}), !dbg ![[#CALL1_LOC:]] + helper_single(s); +} + +#[inline(never)] +fn helper_single(_s: LargeStruct) {} + +// ============================================================================ +// Test 2: Multiple arguments of different types +// ============================================================================ + +// CHECK-LABEL: call_arg_scope::test_call_with_multiple_args +pub fn test_call_with_multiple_args(large: LargeStruct, medium: MediumStruct, small: SmallStruct) { + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CALL2_ARG1_LOC:]] + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CALL2_ARG2_LOC:]] + // CHECK: call {{.*}}@{{.*}}helper_multiple{{.*}}({{.*}}), !dbg ![[#CALL2_LOC:]] + helper_multiple(large, medium, small); +} + +#[inline(never)] +fn helper_multiple(_l: LargeStruct, _m: MediumStruct, _s: SmallStruct) {} + +// ============================================================================ +// Test 3: Return value +// ============================================================================ + +// CHECK-LABEL: call_arg_scope::test_return_large_value +pub fn test_return_large_value() -> LargeStruct { + let s = LargeStruct { data: [42; 20] }; + // CHECK: ret {{.*}}, !dbg ![[#RET1_LOC:]] + s +} + +// ============================================================================ +// Test 4: Calling a function that returns a large value +// ============================================================================ + +// CHECK-LABEL: call_arg_scope::test_call_returning_large +pub fn test_call_returning_large() { + // CHECK: call {{.*}}@{{.*}}make_large_struct{{.*}}({{.*}}), !dbg ![[#CALL3_LOC:]] + let _result = make_large_struct(); +} + +#[inline(never)] +fn make_large_struct() -> LargeStruct { + LargeStruct { data: [1; 20] } +} + +// ============================================================================ +// Test 5: Mixed scenario - passing and returning large values +// ============================================================================ + +// CHECK-LABEL: call_arg_scope::test_mixed_call +pub fn test_mixed_call(input: LargeStruct) -> LargeStruct { + // CHECK: call {{.*}}@{{.*}}transform_large{{.*}}({{.*}}), !dbg ![[#CALL4_LOC:]] + transform_large(input) +} + +#[inline(never)] +fn transform_large(mut s: LargeStruct) -> LargeStruct { + s.data[0] += 1; + s +} + +// CHECK-DAG: ![[#CALL1_ARG_LOC]] = !DILocation({{.*}}scope: ![[#CALL1_ARG_SCOPE:]] +// CHECK-DAG: ![[#CALL1_ARG_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy" +// CHECK-DAG: ![[#CALL1_LOC]] = !DILocation({{.*}}scope: ![[#CALL1_SCOPE:]] +// CHECK-DAG: ![[#CALL1_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "test_call_with_single_arg" + +// CHECK-DAG: ![[#CALL2_ARG1_LOC]] = !DILocation({{.*}}scope: ![[#CALL2_ARG1_SCOPE:]] +// CHECK-DAG: ![[#CALL2_ARG1_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy" +// CHECK-DAG: ![[#CALL2_ARG2_LOC]] = !DILocation({{.*}}scope: ![[#CALL2_ARG2_SCOPE:]] +// CHECK-DAG: ![[#CALL2_ARG2_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy" +// CHECK-DAG: ![[#CALL2_LOC]] = !DILocation({{.*}}scope: ![[#CALL2_SCOPE:]] +// CHECK-DAG: ![[#CALL2_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "test_call_with_multiple_args" + +// CHECK-DAG: ![[#CALL3_LOC]] = !DILocation({{.*}}scope: ![[#CALL3_SCOPE:]] +// CHECK-DAG: ![[#CALL3_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "test_call_returning_large" + +// CHECK-DAG: ![[#CALL4_LOC]] = !DILocation({{.*}}scope: ![[#CALL4_SCOPE:]] +// CHECK-DAG: ![[#CALL4_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "test_mixed_call" + +// CHECK-DAG: ![[#RET1_LOC]] = !DILocation({{.*}}scope: ![[#RET1_SCOPE:]] +// CHECK-DAG: ![[#RET1_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "test_return_large_value" diff --git a/tests/codegen-llvm/annotate-moves/disabled.rs b/tests/codegen-llvm/annotate-moves/disabled.rs new file mode 100644 index 0000000000000..2a0e786723183 --- /dev/null +++ b/tests/codegen-llvm/annotate-moves/disabled.rs @@ -0,0 +1,35 @@ +//@ compile-flags: -Zannotate-moves=no -Copt-level=0 -g +// Test that move/copy operations are NOT annotated when the flag is disabled + +#![crate_type = "lib"] + +struct LargeStruct { + data: [u64; 20], // 160 bytes - would normally trigger annotation +} + +impl Clone for LargeStruct { + // CHECK-LABEL: ::clone + fn clone(&self) -> Self { + // Should NOT be annotated when flag is disabled + // CHECK-NOT: compiler_copy + LargeStruct { data: self.data } + } +} + +// CHECK-LABEL: disabled::test_large_copy_no_annotation +pub fn test_large_copy_no_annotation() { + let large = LargeStruct { data: [42; 20] }; + // CHECK-NOT: compiler_copy + let _copy = large.clone(); +} + +// CHECK-LABEL: disabled::test_large_move_no_annotation +pub fn test_large_move_no_annotation() { + let large = LargeStruct { data: [42; 20] }; + // CHECK-NOT: compiler_move + let _moved = large; +} + +// Verify that no compiler_move or compiler_copy annotations exist anywhere +// CHECK-NOT: compiler_move +// CHECK-NOT: compiler_copy diff --git a/tests/codegen-llvm/annotate-moves/integration.rs b/tests/codegen-llvm/annotate-moves/integration.rs new file mode 100644 index 0000000000000..5e5c2e05879bb --- /dev/null +++ b/tests/codegen-llvm/annotate-moves/integration.rs @@ -0,0 +1,192 @@ +//@ compile-flags: -Z annotate-moves=1 -Copt-level=0 -g + +#![crate_type = "lib"] + +// Test with large array (non-struct type, Copy) +type LargeArray = [u64; 20]; // 160 bytes + +#[derive(Clone, Default)] +struct NonCopyU64(u64); + +// Test with Copy implementation +#[derive(Copy)] +struct ExplicitCopy { + data: [u64; 20], // 160 bytes +} + +impl Clone for ExplicitCopy { + // CHECK-LABEL: ::clone + fn clone(&self) -> Self { + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#EXPLICIT_COPY_LOC:]] + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#EXPLICIT_RETURN_LOC:]] + Self { data: self.data } + } +} + +// Test with hand-implemented Clone (non-Copy) +struct NonCopyStruct { + data: [u64; 20], // 160 bytes +} + +impl Clone for NonCopyStruct { + // CHECK-LABEL: ::clone + fn clone(&self) -> Self { + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CLONE_COPY_LOC:]] + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CLONE_RETURN_LOC:]] + NonCopyStruct { data: self.data } + } +} + +// CHECK-LABEL: integration::test_pure_assignment_move +pub fn test_pure_assignment_move() { + let arr: LargeArray = [42; 20]; + // Arrays are initialized with a loop + // CHECK-NOT: call void @llvm.memcpy{{.*}}, !dbg ![[#]] + let _moved = arr; +} + +// CHECK-LABEL: integration::test_pure_assignment_copy +pub fn test_pure_assignment_copy() { + let s = ExplicitCopy { data: [42; 20] }; + // Arrays are initialized with a loop + // CHECK-NOT: call void @llvm.memcpy{{.*}}, !dbg ![[#]] + let _copied = s; + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#ASSIGN_COPY2_LOC:]] + let _copied_2 = s; +} + +#[derive(Default)] +struct InitializeStruct { + field1: String, + field2: String, + field3: String, +} + +// CHECK-LABEL: integration::test_init_struct +pub fn test_init_struct() { + let mut s = InitializeStruct::default(); + + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#INIT_STRUCT_LOC:]] + s = InitializeStruct { + field1: String::from("Hello"), + field2: String::from("from"), + field3: String::from("Rust"), + }; +} + +// CHECK-LABEL: integration::test_tuple_of_scalars +pub fn test_tuple_of_scalars() { + // Tuple of scalars (even if large) may use scalar-pair repr, so may not be annotated + let t: (u64, u64, u64, u64) = (1, 2, 3, 4); // 32 bytes + // Copied with explicit stores + // CHECK-NOT: call void @llvm.memcpy{{.*}}, !dbg ![[#]] + let _moved = t; +} + +// CHECK-LABEL: integration::test_tuple_of_structs +pub fn test_tuple_of_structs() { + let s1 = NonCopyStruct { data: [1; 20] }; + let s2 = NonCopyStruct { data: [2; 20] }; + let tuple = (s1, s2); // Large tuple containing structs (320 bytes) + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#TUPLE_MOVE_LOC:]] + let _moved = tuple; +} + +// CHECK-LABEL: integration::test_tuple_mixed +pub fn test_tuple_mixed() { + let s = NonCopyStruct { data: [1; 20] }; + let tuple = (42u64, s); // Mixed tuple (168 bytes: 8 for u64 + 160 for struct) + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#MIXED_TUPLE_LOC:]] + let _moved = tuple; +} + +// CHECK-LABEL: integration::test_explicit_copy_assignment +pub fn test_explicit_copy_assignment() { + let c1 = ExplicitCopy { data: [1; 20] }; + // Initialized with loop + // CHECK-NOT: call void @llvm.memcpy{{.*}}, !dbg ![[#]] + let c2 = c1; + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#COPY2_LOC:]] + let _c3 = c1; // Can still use c1 (it was copied) + let _ = c2; +} + +// CHECK-LABEL: integration::test_array_move +pub fn test_array_move() { + let arr: [String; 20] = std::array::from_fn(|i| i.to_string()); + + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#ARRAY_MOVE_LOC:]] + let _moved = arr; +} + +// CHECK-LABEL: integration::test_array_in_struct_field +pub fn test_array_in_struct_field() { + let s = NonCopyStruct { data: [1; 20] }; + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#FIELD_MOVE_LOC:]] + let data = s.data; // Move array field out of struct + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#FIELD_MOVE2_LOC:]] + let _moved = data; +} + +// CHECK-LABEL: integration::test_clone_noncopy +pub fn test_clone_noncopy() { + let s = NonCopyStruct { data: [1; 20] }; + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CALL_CLONE_NONCOPY_LOC:]] + let _cloned = s.clone(); // The copy happens inside the clone() impl above +} + +// CHECK-LABEL: integration::test_clone_explicit_copy +pub fn test_clone_explicit_copy() { + let c = ExplicitCopy { data: [1; 20] }; + // Derived Clone on Copy type - the copy happens inside the generated clone impl + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CALL_CLONE_COPY_LOC:]] + let _cloned = c.clone(); +} + +// CHECK-LABEL: integration::test_copy_ref +pub fn test_copy_ref(x: &ExplicitCopy) { + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#LOCAL_COPY_LOC:]] + let _local = *x; +} + +// CHECK-DAG: ![[#EXPLICIT_COPY_LOC]] = !DILocation({{.*}}scope: ![[#EXPLICIT_COPY_SCOPE:]] +// CHECK-DAG: ![[#EXPLICIT_COPY_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy<[u64; 20], 160>" +// CHECK-DAG: ![[#EXPLICIT_RETURN_LOC]] = !DILocation({{.*}}scope: ![[#EXPLICIT_RETURN_SCOPE:]] +// CHECK-DAG: ![[#EXPLICIT_RETURN_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" + +// CHECK-DAG: ![[#CLONE_COPY_LOC]] = !DILocation({{.*}}scope: ![[#CLONE_COPY_SCOPE:]] +// CHECK-DAG: ![[#CLONE_COPY_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy<[u64; 20], 160>" +// CHECK-DAG: ![[#CLONE_RETURN_LOC]] = !DILocation({{.*}}scope: ![[#CLONE_RETURN_SCOPE:]] +// CHECK-DAG: ![[#CLONE_RETURN_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" + +// CHECK-DAG: ![[#ASSIGN_COPY2_LOC]] = !DILocation({{.*}}scope: ![[#ASSIGN_COPY2_SCOPE:]] +// CHECK-DAG: ![[#ASSIGN_COPY2_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" + +// CHECK-DAG: ![[#INIT_STRUCT_LOC]] = !DILocation({{.*}}scope: ![[#INIT_STRUCT_SCOPE:]] +// CHECK-DAG: ![[#INIT_STRUCT_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move" + +// CHECK-DAG: ![[#TUPLE_MOVE_LOC]] = !DILocation({{.*}}scope: ![[#TUPLE_MOVE_SCOPE:]] +// CHECK-DAG: ![[#TUPLE_MOVE_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" + +// CHECK-DAG: ![[#MIXED_TUPLE_LOC]] = !DILocation({{.*}}scope: ![[#MIXED_TUPLE_SCOPE:]] +// CHECK-DAG: ![[#MIXED_TUPLE_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" + +// CHECK-DAG: ![[#COPY2_LOC]] = !DILocation({{.*}}scope: ![[#COPY2_SCOPE:]] +// CHECK-DAG: ![[#COPY2_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" + +// CHECK-DAG: ![[#ARRAY_MOVE_LOC]] = !DILocation({{.*}}scope: ![[#ARRAY_MOVE_SCOPE:]] +// CHECK-DAG: ![[#ARRAY_MOVE_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[alloc::string::String; 20], 480>" + +// CHECK-DAG: ![[#FIELD_MOVE_LOC]] = !DILocation({{.*}}scope: ![[#FIELD_MOVE_SCOPE:]] +// CHECK-DAG: ![[#FIELD_MOVE_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" +// CHECK-DAG: ![[#FIELD_MOVE2_LOC]] = !DILocation({{.*}}scope: ![[#FIELD_MOVE2_SCOPE:]] +// CHECK-DAG: ![[#FIELD_MOVE2_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy<[u64; 20], 160>" + +// CHECK-DAG: ![[#CALL_CLONE_NONCOPY_LOC]] = !DILocation({{.*}}scope: ![[#CALL_CLONE_NONCOPY_SCOPE:]] +// CHECK-DAG: ![[#CALL_CLONE_NONCOPY_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" + +// CHECK-DAG: ![[#CALL_CLONE_COPY_LOC]] = !DILocation({{.*}}scope: ![[#CALL_CLONE_COPY_SCOPE:]] +// CHECK-DAG: ![[#CALL_CLONE_COPY_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" + +// CHECK-DAG: ![[#LOCAL_COPY_LOC]] = !DILocation({{.*}}scope: ![[#LOCAL_COPY_SCOPE:]] +// CHECK-DAG: ![[#LOCAL_COPY_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy" diff --git a/tests/codegen-llvm/annotate-moves/size-limit.rs b/tests/codegen-llvm/annotate-moves/size-limit.rs new file mode 100644 index 0000000000000..fbb412de99cd2 --- /dev/null +++ b/tests/codegen-llvm/annotate-moves/size-limit.rs @@ -0,0 +1,112 @@ +//@ compile-flags: -Z annotate-moves=100 -Copt-level=0 -g +// Test that custom size limits work correctly +#![crate_type = "lib"] + +struct Struct99 { + data: [u8; 99], // just below custom 100-byte threshold +} + +const _: () = { assert!(size_of::() == 99) }; + +impl Clone for Struct99 { + // CHECK-LABEL: ::clone + fn clone(&self) -> Self { + // Should NOT be annotated since 99 < 100 + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#SZ99_COPY_LOC:]] + Struct99 { data: self.data } + } +} + +// CHECK-LABEL: size_limit::test_99_copy +pub fn test_99_copy() { + let sz99 = Struct99 { data: [42; 99] }; + let _copy = sz99.clone(); +} + +// CHECK-LABEL: size_limit::test_99_move +pub fn test_99_move() { + let sz99 = Struct99 { data: [42; 99] }; + // Should NOT be annotated + // CHECK-NOT: compiler_move + let _moved = sz99; +} + +struct Struct100 { + data: [u8; 100], // 100 bytes - equal to custom 100-byte threshold +} + +const _: () = { assert!(size_of::() == 100) }; + +impl Clone for Struct100 { + // CHECK-LABEL: ::clone + fn clone(&self) -> Self { + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#SZ100_COPY_LOC:]] + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#SZ100_RETURN_LOC:]] + Struct100 { data: self.data } + } +} + +// CHECK-LABEL: size_limit::test_100_copy +pub fn test_100_copy() { + let sz100 = Struct100 { data: [42; 100] }; + let _copy = sz100.clone(); +} + +// CHECK-LABEL: size_limit::test_100_move +pub fn test_100_move() { + let sz100 = Struct100 { data: [42; 100] }; + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#SZ100_MOVE_LOC:]] + let _moved = sz100; +} + +struct Struct101 { + data: [u8; 101], // 101 bytes - above custom 100-byte threshold +} + +const _: () = { assert!(size_of::() == 101) }; + +impl Clone for Struct101 { + // CHECK-LABEL: ::clone + fn clone(&self) -> Self { + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#SZ101_COPY_LOC:]] + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#SZ101_RETURN_LOC:]] + Struct101 { data: self.data } + } +} + +// CHECK-LABEL: size_limit::test_101_copy +pub fn test_101_copy() { + let sz101 = Struct101 { data: [42; 101] }; + let _copy = sz101.clone(); +} + +// CHECK-LABEL: size_limit::test_101_move +pub fn test_101_move() { + let sz101 = Struct101 { data: [42; 101] }; + // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#SZ101_MOVE_LOC:]] + let _moved = sz101; +} + +// The scope for no-annotated is clone function itself +// CHECK-DAG: ![[#SZ99_COPY_LOC]] = !DILocation({{.*}}scope: ![[#SZ99_COPY_SCOPE:]] +// CHECK-DAG: ![[#SZ99_COPY_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "clone", + +// Clone itself is copy, but return is move. +// CHECK-DAG: ![[#SZ100_COPY_LOC]] = !DILocation({{.*}}scope: ![[#SZ100_COPY_SCOPE:]] +// CHECK-DAG: ![[#SZ100_COPY_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy<[u8; 100], 100>" +// CHECK-DAG: ![[#SZ100_RETURN_LOC]] = !DILocation({{.*}}scope: ![[#SZ100_RETURN_SCOPE:]] +// CHECK-DAG: ![[#SZ100_RETURN_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u8; 100], 100>" + +// Assignment is move +// CHECK-DAG: ![[#SZ100_MOVE_LOC]] = !DILocation({{.*}}scope: ![[#SZ100_MOVE_SCOPE:]] +// CHECK-DAG: ![[#SZ100_MOVE_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u8; 100], 100>" + +// Clone itself is copy, but return is move. +// CHECK-DAG: ![[#SZ101_COPY_LOC]] = !DILocation({{.*}}scope: ![[#SZ101_COPY_SCOPE:]] +// CHECK-DAG: ![[#SZ101_COPY_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_copy<[u8; 101], 101>" +// CHECK-DAG: ![[#SZ101_RETURN_LOC]] = !DILocation({{.*}}scope: ![[#SZ101_RETURN_SCOPE:]] +// CHECK-DAG: ![[#SZ101_RETURN_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u8; 101], 101>" + +// Assignment is move +// CHECK-DAG: ![[#SZ101_MOVE_LOC]] = !DILocation({{.*}}scope: ![[#SZ101_MOVE_SCOPE:]] +// CHECK-DAG: ![[#SZ101_MOVE_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u8; 101], 101>" diff --git a/tests/ui/annotate-moves/annotate-moves-basic.rs b/tests/ui/annotate-moves/annotate-moves-basic.rs new file mode 100644 index 0000000000000..645122113dab2 --- /dev/null +++ b/tests/ui/annotate-moves/annotate-moves-basic.rs @@ -0,0 +1,15 @@ +//@ check-pass +//@ compile-flags: -Z annotate-moves=100 + +// Test that valid annotate-moves flags are accepted + +#[derive(Clone)] +struct TestStruct { + data: [u64; 20], // 160 bytes +} + +fn main() { + let s = TestStruct { data: [42; 20] }; + let _copy = s.clone(); + let _moved = s; +} diff --git a/tests/ui/annotate-moves/annotate-moves-invalid-flag.rs b/tests/ui/annotate-moves/annotate-moves-invalid-flag.rs new file mode 100644 index 0000000000000..621b7861657ef --- /dev/null +++ b/tests/ui/annotate-moves/annotate-moves-invalid-flag.rs @@ -0,0 +1,10 @@ +//@ check-fail +//@ compile-flags: -Z annotate-moves=invalid + +// Test that invalid values for annotate-moves flag are rejected + +fn main() { + // This should fail at compile time due to invalid flag value +} + +//~? ERROR incorrect value `invalid` for unstable option `annotate-moves` diff --git a/tests/ui/annotate-moves/annotate-moves-invalid-flag.stderr b/tests/ui/annotate-moves/annotate-moves-invalid-flag.stderr new file mode 100644 index 0000000000000..5a323573a7770 --- /dev/null +++ b/tests/ui/annotate-moves/annotate-moves-invalid-flag.stderr @@ -0,0 +1,2 @@ +error: incorrect value `invalid` for unstable option `annotate-moves` - either a boolean (`yes`, `no`, `on`, `off`, etc.), or a size limit in bytes was expected + diff --git a/tests/ui/annotate-moves/annotate-moves-size-limit-invalid.rs b/tests/ui/annotate-moves/annotate-moves-size-limit-invalid.rs new file mode 100644 index 0000000000000..50a402102184a --- /dev/null +++ b/tests/ui/annotate-moves/annotate-moves-size-limit-invalid.rs @@ -0,0 +1,10 @@ +//@ check-fail +//@ compile-flags: -Z annotate-moves=-5 + +// Test that negative size limits are rejected + +fn main() { + // This should fail at compile time due to invalid negative size limit +} + +//~? ERROR incorrect value `-5` for unstable option `annotate-moves` diff --git a/tests/ui/annotate-moves/annotate-moves-size-limit-invalid.stderr b/tests/ui/annotate-moves/annotate-moves-size-limit-invalid.stderr new file mode 100644 index 0000000000000..24a3659a30a66 --- /dev/null +++ b/tests/ui/annotate-moves/annotate-moves-size-limit-invalid.stderr @@ -0,0 +1,2 @@ +error: incorrect value `-5` for unstable option `annotate-moves` - either a boolean (`yes`, `no`, `on`, `off`, etc.), or a size limit in bytes was expected + From 71e2e0cded7c5f54a4b39a27cdf1268a187e7572 Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 5 Nov 2025 11:29:12 -0700 Subject: [PATCH 05/14] Minor fixes to StdNonZeroNumberProvider for gdb While looking at the pretty-printers, I found a few minor oddities in StdNonZeroNumberProvider. First, gdb.Type.fields() already returns a sequence, so there's no need to call list(). Second, it's more idiomatic for the (somewhat misnamed) to_string method to simply return the underlying gdb.Value. This also lets gdb apply whatever formats were passed to `print`, as the new test shows. Third, there's no need to use the field's name when looking up a field in a value, the gdb.Field itself can be used. --- src/etc/gdb_providers.py | 8 ++++---- tests/debuginfo/numeric-types.rs | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index c8f4a32cb17e2..2c8959da957bd 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -252,15 +252,15 @@ class StdNonZeroNumberProvider(printer_base): def __init__(self, valobj): fields = valobj.type.fields() assert len(fields) == 1 - field = list(fields)[0] + field = fields[0] - inner_valobj = valobj[field.name] + inner_valobj = valobj[field] inner_fields = inner_valobj.type.fields() assert len(inner_fields) == 1 - inner_field = list(inner_fields)[0] + inner_field = inner_fields[0] - self._value = str(inner_valobj[inner_field.name]) + self._value = inner_valobj[inner_field] def to_string(self): return self._value diff --git a/tests/debuginfo/numeric-types.rs b/tests/debuginfo/numeric-types.rs index 9f7ef5c537d22..37b6abf921eaf 100644 --- a/tests/debuginfo/numeric-types.rs +++ b/tests/debuginfo/numeric-types.rs @@ -202,6 +202,8 @@ // gdb-command:print nz_usize // gdb-check:[...]$12 = 122 +// gdb-command:print/x nz_i8 +// gdb-check:[...]$13 = 0xb // === LLDB TESTS ================================================================================== From d2b021c340650061c7bd291d8a7e3f3d858ead3b Mon Sep 17 00:00:00 2001 From: Tom Tromey Date: Wed, 5 Nov 2025 11:12:05 -0700 Subject: [PATCH 06/14] Add num_children method to some gdb pretty-printers gdb doesn't have a way to know when an object hasn't yet been initialized, and in this case, if a pretty-printer returns an absurd number of children, this can result in apparent hangs in some modes. This came up specifically with DAP, see this bug report: https://sourceware.org/bugzilla/show_bug.cgi?id=33594 This patch (mostly) addresses this potential issue in the Rust pretty-printers, by adding 'num_children' methods. In particular a method like this is added when the number of children is variable and also relatively easy to compute. (I.e., I didn't attempt the btree printers.) Supplying num_children is good for DAP regardless of the initialization problem, because DAP requires a count of child objects and this is more efficient than enumerating the children, which is gdb's fallback approach. --- src/etc/gdb_providers.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index c8f4a32cb17e2..b5c2d26817cd1 100644 --- a/src/etc/gdb_providers.py +++ b/src/etc/gdb_providers.py @@ -128,6 +128,9 @@ def children(self): self._data_ptr + index for index in xrange(self._length) ) + def num_children(self): + return self._length + @staticmethod def display_hint(): return "array" @@ -149,6 +152,9 @@ def children(self): self._data_ptr + index for index in xrange(self._length) ) + def num_children(self): + return self._length + @staticmethod def display_hint(): return "array" @@ -177,6 +183,9 @@ def children(self): for index in xrange(self._size) ) + def num_children(self): + return self._size + @staticmethod def display_hint(): return "array" @@ -478,5 +487,11 @@ def children(self): else: yield "[{}]".format(index), element[ZERO_FIELD] + def num_children(self): + result = self._size + if self._show_values: + result *= 2 + return result + def display_hint(self): return "map" if self._show_values else "array" From 2c3c82c4c5a2e2b49d1bfac0ebeab6f5d14e5b8f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 3 Nov 2025 20:55:54 +0100 Subject: [PATCH 07/14] Add new `run_make_support::CompletedProcess::assert_ice` method --- src/tools/run-make-support/src/command.rs | 7 +++++++ .../diagnostics-traits-from-duplicate-crates/rmake.rs | 2 +- tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs | 2 +- tests/run-make/rustdoc-test-builder/rmake.rs | 7 +++---- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index b46ddd1d3154b..0aeb189bb6a5b 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -387,6 +387,13 @@ impl CompletedProcess { self } + /// Checks that `stderr` doesn't contain the Internal Compiler Error message. + #[track_caller] + pub fn assert_not_ice(&self) -> &Self { + self.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug"); + self + } + /// Checks that `stderr` does not contain the regex pattern `unexpected`. #[track_caller] pub fn assert_stderr_not_contains_regex>(&self, unexpected: S) -> &Self { diff --git a/tests/run-make/diagnostics-traits-from-duplicate-crates/rmake.rs b/tests/run-make/diagnostics-traits-from-duplicate-crates/rmake.rs index 5bc0a0c9519fd..abd7b8cc8a8a7 100644 --- a/tests/run-make/diagnostics-traits-from-duplicate-crates/rmake.rs +++ b/tests/run-make/diagnostics-traits-from-duplicate-crates/rmake.rs @@ -43,5 +43,5 @@ fn main() { .extern_("minibevy", "libminibevy-b.rmeta") .extern_("minirapier", "libminirapier.rmeta") .run_fail() - .assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug"); + .assert_not_ice(); } diff --git a/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs b/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs index 0b1e1948d5fcc..d750a36f44534 100644 --- a/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs +++ b/tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs @@ -24,5 +24,5 @@ fn main() { .arg(format!("--include-parts-dir={}", parts_out_dir.display())) .arg("--merge=finalize") .run(); - output.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); + output.assert_not_ice(); } diff --git a/tests/run-make/rustdoc-test-builder/rmake.rs b/tests/run-make/rustdoc-test-builder/rmake.rs index c243b784eb9b2..9aa8143dc1dc4 100644 --- a/tests/run-make/rustdoc-test-builder/rmake.rs +++ b/tests/run-make/rustdoc-test-builder/rmake.rs @@ -15,9 +15,8 @@ fn main() { .arg(&absolute_path) .run_fail(); - // We also double-check that we don't have the panic text in the output. + // We check that rustdoc outputs the error correctly... output.assert_stdout_contains("Failed to spawn "); - output.assert_stderr_not_contains("the compiler unexpectedly panicked. this is a bug."); - // Just in case... - output.assert_stdout_not_contains("the compiler unexpectedly panicked. this is a bug."); + // ... and that we didn't panic. + output.assert_not_ice(); } From 32372bf405a1959f7e17116cb04e5b3bbb8fad11 Mon Sep 17 00:00:00 2001 From: Jeremy Fitzhardinge Date: Wed, 5 Nov 2025 14:35:39 -0800 Subject: [PATCH 08/14] Update tests for wasm32 --- tests/codegen-llvm/annotate-moves/call-arg-scope.rs | 8 ++++---- tests/codegen-llvm/annotate-moves/integration.rs | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/codegen-llvm/annotate-moves/call-arg-scope.rs b/tests/codegen-llvm/annotate-moves/call-arg-scope.rs index 527ab0b09d7c8..eed02b070a20e 100644 --- a/tests/codegen-llvm/annotate-moves/call-arg-scope.rs +++ b/tests/codegen-llvm/annotate-moves/call-arg-scope.rs @@ -28,7 +28,7 @@ pub struct SmallStruct { // CHECK-LABEL: call_arg_scope::test_call_with_single_arg pub fn test_call_with_single_arg(s: LargeStruct) { // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CALL1_ARG_LOC:]] - // CHECK: call {{.*}}@{{.*}}helper_single{{.*}}({{.*}}), !dbg ![[#CALL1_LOC:]] + // CHECK: call {{.*}}@{{.*}}helper_single{{.*}}({{.*}}){{.*}}, !dbg ![[#CALL1_LOC:]] helper_single(s); } @@ -43,7 +43,7 @@ fn helper_single(_s: LargeStruct) {} pub fn test_call_with_multiple_args(large: LargeStruct, medium: MediumStruct, small: SmallStruct) { // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CALL2_ARG1_LOC:]] // CHECK: call void @llvm.memcpy{{.*}}, !dbg ![[#CALL2_ARG2_LOC:]] - // CHECK: call {{.*}}@{{.*}}helper_multiple{{.*}}({{.*}}), !dbg ![[#CALL2_LOC:]] + // CHECK: call {{.*}}@{{.*}}helper_multiple{{.*}}({{.*}}){{.*}}, !dbg ![[#CALL2_LOC:]] helper_multiple(large, medium, small); } @@ -67,7 +67,7 @@ pub fn test_return_large_value() -> LargeStruct { // CHECK-LABEL: call_arg_scope::test_call_returning_large pub fn test_call_returning_large() { - // CHECK: call {{.*}}@{{.*}}make_large_struct{{.*}}({{.*}}), !dbg ![[#CALL3_LOC:]] + // CHECK: call {{.*}}@{{.*}}make_large_struct{{.*}}({{.*}}){{.*}}, !dbg ![[#CALL3_LOC:]] let _result = make_large_struct(); } @@ -82,7 +82,7 @@ fn make_large_struct() -> LargeStruct { // CHECK-LABEL: call_arg_scope::test_mixed_call pub fn test_mixed_call(input: LargeStruct) -> LargeStruct { - // CHECK: call {{.*}}@{{.*}}transform_large{{.*}}({{.*}}), !dbg ![[#CALL4_LOC:]] + // CHECK: call {{.*}}@{{.*}}transform_large{{.*}}({{.*}}){{.*}}, !dbg ![[#CALL4_LOC:]] transform_large(input) } diff --git a/tests/codegen-llvm/annotate-moves/integration.rs b/tests/codegen-llvm/annotate-moves/integration.rs index 5e5c2e05879bb..489c0670c6338 100644 --- a/tests/codegen-llvm/annotate-moves/integration.rs +++ b/tests/codegen-llvm/annotate-moves/integration.rs @@ -163,7 +163,7 @@ pub fn test_copy_ref(x: &ExplicitCopy) { // CHECK-DAG: ![[#ASSIGN_COPY2_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" // CHECK-DAG: ![[#INIT_STRUCT_LOC]] = !DILocation({{.*}}scope: ![[#INIT_STRUCT_SCOPE:]] -// CHECK-DAG: ![[#INIT_STRUCT_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move" +// CHECK-DAG: ![[#INIT_STRUCT_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move" // CHECK-DAG: ![[#TUPLE_MOVE_LOC]] = !DILocation({{.*}}scope: ![[#TUPLE_MOVE_SCOPE:]] // CHECK-DAG: ![[#TUPLE_MOVE_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" @@ -175,7 +175,7 @@ pub fn test_copy_ref(x: &ExplicitCopy) { // CHECK-DAG: ![[#COPY2_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" // CHECK-DAG: ![[#ARRAY_MOVE_LOC]] = !DILocation({{.*}}scope: ![[#ARRAY_MOVE_SCOPE:]] -// CHECK-DAG: ![[#ARRAY_MOVE_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[alloc::string::String; 20], 480>" +// CHECK-DAG: ![[#ARRAY_MOVE_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[alloc::string::String; 20], [[#]]>" // CHECK-DAG: ![[#FIELD_MOVE_LOC]] = !DILocation({{.*}}scope: ![[#FIELD_MOVE_SCOPE:]] // CHECK-DAG: ![[#FIELD_MOVE_SCOPE]] = {{(distinct )?}}!DISubprogram(name: "compiler_move<[u64; 20], 160>" From 0717a3929fe7cb3e131380aaed0b0db29d3ddbf0 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 5 Nov 2025 14:37:38 -0800 Subject: [PATCH 09/14] Fix broken qemu-cskyv2 link The link had a stray character that generated an invalid link. --- .../rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md index e69d606ccd2fe..bd4cd3df7daea 100644 --- a/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md +++ b/src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md @@ -65,7 +65,7 @@ To test cross-compiled binaries on a `x86_64` system, you can use the `qemu-csky To use: -* Install `qemu-cskyv2` (If you don't already have a qemu, you can download from [here](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1689324918932/xuantie-qemu-x86_64-Ubuntu-18.04-20230714-0202.tar.gz"), and unpack it into a directory.) +* Install `qemu-cskyv2` (If you don't already have a qemu, you can download from [here](https://occ-oss-prod.oss-cn-hangzhou.aliyuncs.com/resource//1689324918932/xuantie-qemu-x86_64-Ubuntu-18.04-20230714-0202.tar.gz), and unpack it into a directory.) * Link your built toolchain via: * `rustup toolchain link stage2 ${RUST}/build/x86_64-unknown-linux-gnu/stage2` * Create a test program From dcc11ace133c74540a8c6442aa5d8e9377d9f895 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 20 Aug 2025 12:08:27 +0200 Subject: [PATCH 10/14] extract s390x `vector` and friends to their own rust feature --- compiler/rustc_feature/src/unstable.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/target_features.rs | 24 +++++++++---------- library/core/src/lib.rs | 1 + library/stdarch/crates/core_arch/src/lib.rs | 2 +- tests/assembly-llvm/s390x-vector-abi.rs | 2 +- tests/codegen-llvm/s390x-simd.rs | 2 +- tests/codegen-llvm/simd/extract-insert-dyn.rs | 2 +- tests/ui/abi/simd-abi-checks-s390x.rs | 2 +- tests/ui/target-feature/gate.rs | 1 + tests/ui/target-feature/gate.stderr | 2 +- 11 files changed, 22 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8397cd294e0a9..b4fc1e8d9c1c3 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -343,6 +343,7 @@ declare_features! ( (unstable, riscv_target_feature, "1.45.0", Some(44839)), (unstable, rtm_target_feature, "1.35.0", Some(44839)), (unstable, s390x_target_feature, "1.82.0", Some(44839)), + (unstable, s390x_target_feature_vector, "CURRENT_RUSTC_VERSION", Some(145649)), (unstable, sparc_target_feature, "1.84.0", Some(132783)), (unstable, wasm_target_feature, "1.30.0", Some(44839)), (unstable, x87_target_feature, "1.85.0", Some(44839)), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 38718bad9e57e..b7357b322ee87 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2000,6 +2000,7 @@ symbols! { s, s390x, s390x_target_feature, + s390x_target_feature_vector, safety, sanitize, sanitizer_cfi_generalize_pointers, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index fd95bd062be65..d2684183821f8 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -844,20 +844,20 @@ const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("message-security-assist-extension8", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3"]), ("message-security-assist-extension9", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3", "message-security-assist-extension4"]), ("message-security-assist-extension12", Unstable(sym::s390x_target_feature), &[]), - ("miscellaneous-extensions-2", Unstable(sym::s390x_target_feature), &[]), - ("miscellaneous-extensions-3", Unstable(sym::s390x_target_feature), &[]), - ("miscellaneous-extensions-4", Unstable(sym::s390x_target_feature), &[]), - ("nnp-assist", Unstable(sym::s390x_target_feature), &["vector"]), + ("miscellaneous-extensions-2", Unstable(sym::s390x_target_feature_vector), &[]), + ("miscellaneous-extensions-3", Unstable(sym::s390x_target_feature_vector), &[]), + ("miscellaneous-extensions-4", Unstable(sym::s390x_target_feature_vector), &[]), + ("nnp-assist", Unstable(sym::s390x_target_feature_vector), &["vector"]), ("soft-float", Forbidden { reason: "currently unsupported ABI-configuration feature" }, &[]), ("transactional-execution", Unstable(sym::s390x_target_feature), &[]), - ("vector", Unstable(sym::s390x_target_feature), &[]), - ("vector-enhancements-1", Unstable(sym::s390x_target_feature), &["vector"]), - ("vector-enhancements-2", Unstable(sym::s390x_target_feature), &["vector-enhancements-1"]), - ("vector-enhancements-3", Unstable(sym::s390x_target_feature), &["vector-enhancements-2"]), - ("vector-packed-decimal", Unstable(sym::s390x_target_feature), &["vector"]), - ("vector-packed-decimal-enhancement", Unstable(sym::s390x_target_feature), &["vector-packed-decimal"]), - ("vector-packed-decimal-enhancement-2", Unstable(sym::s390x_target_feature), &["vector-packed-decimal-enhancement"]), - ("vector-packed-decimal-enhancement-3", Unstable(sym::s390x_target_feature), &["vector-packed-decimal-enhancement-2"]), + ("vector", Unstable(sym::s390x_target_feature_vector), &[]), + ("vector-enhancements-1", Unstable(sym::s390x_target_feature_vector), &["vector"]), + ("vector-enhancements-2", Unstable(sym::s390x_target_feature_vector), &["vector-enhancements-1"]), + ("vector-enhancements-3", Unstable(sym::s390x_target_feature_vector), &["vector-enhancements-2"]), + ("vector-packed-decimal", Unstable(sym::s390x_target_feature_vector), &["vector"]), + ("vector-packed-decimal-enhancement", Unstable(sym::s390x_target_feature_vector), &["vector-packed-decimal"]), + ("vector-packed-decimal-enhancement-2", Unstable(sym::s390x_target_feature_vector), &["vector-packed-decimal-enhancement"]), + ("vector-packed-decimal-enhancement-3", Unstable(sym::s390x_target_feature_vector), &["vector-packed-decimal-enhancement-2"]), // tidy-alphabetical-end ]; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index f1948fc778ce2..1c0a5631665eb 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -204,6 +204,7 @@ #![feature(riscv_target_feature)] #![feature(rtm_target_feature)] #![feature(s390x_target_feature)] +#![feature(s390x_target_feature_vector)] #![feature(wasm_target_feature)] #![feature(x86_amx_intrinsics)] // tidy-alphabetical-end diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 26a9cb5899183..7aa71a49837ef 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -22,7 +22,7 @@ arm_target_feature, mips_target_feature, powerpc_target_feature, - s390x_target_feature, + s390x_target_feature_vector, loongarch_target_feature, wasm_target_feature, abi_unadjusted, diff --git a/tests/assembly-llvm/s390x-vector-abi.rs b/tests/assembly-llvm/s390x-vector-abi.rs index 9635bb6cb4407..0de5fb15eb4c7 100644 --- a/tests/assembly-llvm/s390x-vector-abi.rs +++ b/tests/assembly-llvm/s390x-vector-abi.rs @@ -12,7 +12,7 @@ //@[z13_no_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector --cfg no_vector //@[z13_no_vector] needs-llvm-components: systemz -#![feature(no_core, lang_items, repr_simd, s390x_target_feature)] +#![feature(no_core, lang_items, repr_simd, s390x_target_feature_vector)] #![no_core] #![crate_type = "lib"] #![allow(non_camel_case_types)] diff --git a/tests/codegen-llvm/s390x-simd.rs b/tests/codegen-llvm/s390x-simd.rs index 50df08524f526..83e9d274bb551 100644 --- a/tests/codegen-llvm/s390x-simd.rs +++ b/tests/codegen-llvm/s390x-simd.rs @@ -6,7 +6,7 @@ #![crate_type = "rlib"] #![feature(no_core, asm_experimental_arch)] -#![feature(s390x_target_feature, simd_ffi, intrinsics, repr_simd)] +#![feature(s390x_target_feature_vector, simd_ffi, intrinsics, repr_simd)] #![no_core] extern crate minicore; diff --git a/tests/codegen-llvm/simd/extract-insert-dyn.rs b/tests/codegen-llvm/simd/extract-insert-dyn.rs index 9c17b82e55352..019fa1d72e369 100644 --- a/tests/codegen-llvm/simd/extract-insert-dyn.rs +++ b/tests/codegen-llvm/simd/extract-insert-dyn.rs @@ -5,7 +5,7 @@ repr_simd, arm_target_feature, mips_target_feature, - s390x_target_feature, + s390x_target_feature_vector, riscv_target_feature )] #![no_std] diff --git a/tests/ui/abi/simd-abi-checks-s390x.rs b/tests/ui/abi/simd-abi-checks-s390x.rs index 6434dbea1106b..e5d737db21239 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.rs +++ b/tests/ui/abi/simd-abi-checks-s390x.rs @@ -14,7 +14,7 @@ //[z13_no_vector,z13_soft_float]~? WARN unstable feature specified for `-Ctarget-feature` //[z13_soft_float]~? WARN target feature `soft-float` cannot be enabled with `-Ctarget-feature` -#![feature(no_core, repr_simd, s390x_target_feature)] +#![feature(no_core, repr_simd, s390x_target_feature_vector)] #![no_core] #![crate_type = "lib"] #![allow(non_camel_case_types, improper_ctypes_definitions)] diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index fc3763820cbec..9afc6fb2b0f4a 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -17,6 +17,7 @@ // gate-test-lahfsahf_target_feature // gate-test-prfchw_target_feature // gate-test-s390x_target_feature +// gate-test-s390x_target_feature_vector // gate-test-sparc_target_feature // gate-test-x87_target_feature // gate-test-m68k_target_feature diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index 345dc2006d0bf..b3567c0091c60 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `x87` is currently unstable - --> $DIR/gate.rs:24:18 + --> $DIR/gate.rs:25:18 | LL | #[target_feature(enable = "x87")] | ^^^^^^^^^^^^^^ From 131b893840caade0867fb7997e4e6632ddf83504 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 20 Aug 2025 12:17:19 +0200 Subject: [PATCH 11/14] `std_detect`: remove unneeded stability lines from s390x features macro --- library/std_detect/src/detect/arch/s390x.rs | 23 --------------------- 1 file changed, 23 deletions(-) diff --git a/library/std_detect/src/detect/arch/s390x.rs b/library/std_detect/src/detect/arch/s390x.rs index 4c20d011680bc..c5d5af2a10edc 100644 --- a/library/std_detect/src/detect/arch/s390x.rs +++ b/library/std_detect/src/detect/arch/s390x.rs @@ -9,73 +9,50 @@ features! { #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] concurrent_functions: "concurrent-functions"; /// s390x concurrent-functions facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] deflate_conversion: "deflate-conversion"; /// s390x deflate-conversion facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] enhanced_sort: "enhanced-sort"; /// s390x enhanced-sort facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] guarded_storage: "guarded-storage"; /// s390x guarded-storage facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] high_word: "high-word"; /// s390x high-word facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension3: "message-security-assist-extension3"; /// s390x message-security-assist-extension3 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension4: "message-security-assist-extension4"; /// s390x message-security-assist-extension4 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension5: "message-security-assist-extension5"; /// s390x message-security-assist-extension5 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension8: "message-security-assist-extension8"; /// s390x message-security-assist-extension8 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension9: "message-security-assist-extension9"; /// s390x message-security-assist-extension9 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension12: "message-security-assist-extension12"; /// s390x message-security-assist-extension12 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] miscellaneous_extensions_2: "miscellaneous-extensions-2"; /// s390x miscellaneous-extensions-2 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] miscellaneous_extensions_3: "miscellaneous-extensions-3"; /// s390x miscellaneous-extensions-3 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] miscellaneous_extensions_4: "miscellaneous-extensions-4"; /// s390x miscellaneous-extensions-4 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] nnp_assist: "nnp-assist"; /// s390x nnp-assist facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] transactional_execution: "transactional-execution"; /// s390x transactional-execution facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector: "vector"; /// s390x vector facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_enhancements_1: "vector-enhancements-1"; /// s390x vector-enhancements-1 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_enhancements_2: "vector-enhancements-2"; /// s390x vector-enhancements-2 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_enhancements_3: "vector-enhancements-3"; /// s390x vector-enhancements-3 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_packed_decimal: "vector-packed-decimal"; /// s390x vector-packed-decimal facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_packed_decimal_enhancement: "vector-packed-decimal-enhancement"; /// s390x vector-packed-decimal-enhancement facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_packed_decimal_enhancement_2: "vector-packed-decimal-enhancement-2"; /// s390x vector-packed-decimal-enhancement-2 facility - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_packed_decimal_enhancement_3: "vector-packed-decimal-enhancement-3"; /// s390x vector-packed-decimal-enhancement-3 facility } From 0965df70c4cf2ca9b4599493f91ccab763caf8cc Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 20 Aug 2025 12:23:22 +0200 Subject: [PATCH 12/14] `std_detect`: give s390x features more accurate features / tracking issues --- library/std_detect/src/detect/arch/s390x.rs | 48 ++++++++++----------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/library/std_detect/src/detect/arch/s390x.rs b/library/std_detect/src/detect/arch/s390x.rs index c5d5af2a10edc..0b3e785bfb47f 100644 --- a/library/std_detect/src/detect/arch/s390x.rs +++ b/library/std_detect/src/detect/arch/s390x.rs @@ -7,52 +7,52 @@ features! { @MACRO_ATTRS: /// Checks if `s390x` feature is enabled. #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] concurrent_functions: "concurrent-functions"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] concurrent_functions: "concurrent-functions"; /// s390x concurrent-functions facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] deflate_conversion: "deflate-conversion"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] deflate_conversion: "deflate-conversion"; /// s390x deflate-conversion facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] enhanced_sort: "enhanced-sort"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] enhanced_sort: "enhanced-sort"; /// s390x enhanced-sort facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] guarded_storage: "guarded-storage"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] guarded_storage: "guarded-storage"; /// s390x guarded-storage facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] high_word: "high-word"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] high_word: "high-word"; /// s390x high-word facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension3: "message-security-assist-extension3"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] message_security_assist_extension3: "message-security-assist-extension3"; /// s390x message-security-assist-extension3 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension4: "message-security-assist-extension4"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] message_security_assist_extension4: "message-security-assist-extension4"; /// s390x message-security-assist-extension4 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension5: "message-security-assist-extension5"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] message_security_assist_extension5: "message-security-assist-extension5"; /// s390x message-security-assist-extension5 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension8: "message-security-assist-extension8"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] message_security_assist_extension8: "message-security-assist-extension8"; /// s390x message-security-assist-extension8 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension9: "message-security-assist-extension9"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] message_security_assist_extension9: "message-security-assist-extension9"; /// s390x message-security-assist-extension9 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] message_security_assist_extension12: "message-security-assist-extension12"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] message_security_assist_extension12: "message-security-assist-extension12"; /// s390x message-security-assist-extension12 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] miscellaneous_extensions_2: "miscellaneous-extensions-2"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] miscellaneous_extensions_2: "miscellaneous-extensions-2"; /// s390x miscellaneous-extensions-2 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] miscellaneous_extensions_3: "miscellaneous-extensions-3"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] miscellaneous_extensions_3: "miscellaneous-extensions-3"; /// s390x miscellaneous-extensions-3 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] miscellaneous_extensions_4: "miscellaneous-extensions-4"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] miscellaneous_extensions_4: "miscellaneous-extensions-4"; /// s390x miscellaneous-extensions-4 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] nnp_assist: "nnp-assist"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] nnp_assist: "nnp-assist"; /// s390x nnp-assist facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] transactional_execution: "transactional-execution"; + @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] transactional_execution: "transactional-execution"; /// s390x transactional-execution facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector: "vector"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector: "vector"; /// s390x vector facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_enhancements_1: "vector-enhancements-1"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_enhancements_1: "vector-enhancements-1"; /// s390x vector-enhancements-1 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_enhancements_2: "vector-enhancements-2"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_enhancements_2: "vector-enhancements-2"; /// s390x vector-enhancements-2 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_enhancements_3: "vector-enhancements-3"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_enhancements_3: "vector-enhancements-3"; /// s390x vector-enhancements-3 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_packed_decimal: "vector-packed-decimal"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_packed_decimal: "vector-packed-decimal"; /// s390x vector-packed-decimal facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_packed_decimal_enhancement: "vector-packed-decimal-enhancement"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_packed_decimal_enhancement: "vector-packed-decimal-enhancement"; /// s390x vector-packed-decimal-enhancement facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_packed_decimal_enhancement_2: "vector-packed-decimal-enhancement-2"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_packed_decimal_enhancement_2: "vector-packed-decimal-enhancement-2"; /// s390x vector-packed-decimal-enhancement-2 facility - @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] vector_packed_decimal_enhancement_3: "vector-packed-decimal-enhancement-3"; + @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_packed_decimal_enhancement_3: "vector-packed-decimal-enhancement-3"; /// s390x vector-packed-decimal-enhancement-3 facility } From 785110265481b56e65423602e66a7f7803e69a28 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 20 Aug 2025 12:41:19 +0200 Subject: [PATCH 13/14] stabilize `stdarch_s390x_feature_detection` --- library/std/src/lib.rs | 2 +- library/std/tests/run-time-detect.rs | 4 ---- library/std_detect/src/detect/arch/mod.rs | 2 +- library/std_detect/src/detect/arch/s390x.rs | 2 +- library/std_detect/tests/cpu-detection.rs | 1 - library/std_detect/tests/macro_trailing_commas.rs | 1 - library/stdarch/crates/core_arch/src/lib.rs | 6 +----- 7 files changed, 4 insertions(+), 14 deletions(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index a8c50cec01e0b..7b6cfbfe0f259 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -672,7 +672,7 @@ pub mod arch { pub use std_detect::is_loongarch_feature_detected; #[unstable(feature = "is_riscv_feature_detected", issue = "111192")] pub use std_detect::is_riscv_feature_detected; - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] + #[stable(feature = "stdarch_s390x_feature_detection", since = "CURRENT_RUSTC_VERSION")] pub use std_detect::is_s390x_feature_detected; #[stable(feature = "simd_x86", since = "1.27.0")] pub use std_detect::is_x86_feature_detected; diff --git a/library/std/tests/run-time-detect.rs b/library/std/tests/run-time-detect.rs index ae0c3385d2ad9..b2c3d0d3f9f8b 100644 --- a/library/std/tests/run-time-detect.rs +++ b/library/std/tests/run-time-detect.rs @@ -8,10 +8,6 @@ all(target_arch = "aarch64", any(target_os = "linux", target_os = "android")), feature(stdarch_aarch64_feature_detection) )] -#![cfg_attr( - all(target_arch = "s390x", target_os = "linux"), - feature(stdarch_s390x_feature_detection) -)] #![cfg_attr( all(target_arch = "powerpc", target_os = "linux"), feature(stdarch_powerpc_feature_detection) diff --git a/library/std_detect/src/detect/arch/mod.rs b/library/std_detect/src/detect/arch/mod.rs index c066b9cc68155..23e7a30b985bf 100644 --- a/library/std_detect/src/detect/arch/mod.rs +++ b/library/std_detect/src/detect/arch/mod.rs @@ -60,7 +60,7 @@ cfg_select! { pub use loongarch::*; } target_arch = "s390x" => { - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] + #[stable(feature = "stdarch_s390x_feature_detection", since = "CURRENT_RUSTC_VERSION")] pub use s390x::*; } _ => { diff --git a/library/std_detect/src/detect/arch/s390x.rs b/library/std_detect/src/detect/arch/s390x.rs index 0b3e785bfb47f..d9026873c4b54 100644 --- a/library/std_detect/src/detect/arch/s390x.rs +++ b/library/std_detect/src/detect/arch/s390x.rs @@ -6,7 +6,7 @@ features! { @MACRO_NAME: is_s390x_feature_detected; @MACRO_ATTRS: /// Checks if `s390x` feature is enabled. - #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] + #[stable(feature = "stdarch_s390x_feature_detection", since = "CURRENT_RUSTC_VERSION")] @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] concurrent_functions: "concurrent-functions"; /// s390x concurrent-functions facility @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] deflate_conversion: "deflate-conversion"; diff --git a/library/std_detect/tests/cpu-detection.rs b/library/std_detect/tests/cpu-detection.rs index 0c4fa57f2b465..3e36abda97dfa 100644 --- a/library/std_detect/tests/cpu-detection.rs +++ b/library/std_detect/tests/cpu-detection.rs @@ -11,7 +11,6 @@ )] #![cfg_attr(target_arch = "powerpc", feature(stdarch_powerpc_feature_detection))] #![cfg_attr(target_arch = "powerpc64", feature(stdarch_powerpc_feature_detection))] -#![cfg_attr(target_arch = "s390x", feature(stdarch_s390x_feature_detection))] #![allow(clippy::unwrap_used, clippy::use_debug, clippy::print_stdout)] #[cfg_attr( diff --git a/library/std_detect/tests/macro_trailing_commas.rs b/library/std_detect/tests/macro_trailing_commas.rs index 6072ddf5ac45e..29bd3f1162a42 100644 --- a/library/std_detect/tests/macro_trailing_commas.rs +++ b/library/std_detect/tests/macro_trailing_commas.rs @@ -25,7 +25,6 @@ any(target_arch = "powerpc", target_arch = "powerpc64"), feature(stdarch_powerpc_feature_detection) )] -#![cfg_attr(target_arch = "s390x", feature(stdarch_s390x_feature_detection))] #![cfg_attr( any(target_arch = "riscv32", target_arch = "riscv64"), feature(stdarch_riscv_feature_detection) diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 7aa71a49837ef..ed9138f343a18 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -64,11 +64,7 @@ )] #![cfg_attr( test, - feature( - stdarch_arm_feature_detection, - stdarch_powerpc_feature_detection, - stdarch_s390x_feature_detection - ) + feature(stdarch_arm_feature_detection, stdarch_powerpc_feature_detection,) )] #[cfg(test)] From b32c425e696b67a28d0c969177e088a147bdabb2 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 20 Aug 2025 13:04:58 +0200 Subject: [PATCH 14/14] stabilize `s390x_target_feature_vector` --- compiler/rustc_feature/src/accepted.rs | 2 ++ compiler/rustc_feature/src/unstable.rs | 1 - compiler/rustc_target/src/target_features.rs | 24 ++++++++--------- library/core/src/lib.rs | 1 - library/std_detect/src/detect/arch/s390x.rs | 24 ++++++++--------- library/stdarch/crates/core_arch/src/lib.rs | 1 - tests/assembly-llvm/s390x-vector-abi.rs | 2 +- tests/codegen-llvm/s390x-simd.rs | 2 +- tests/codegen-llvm/simd/extract-insert-dyn.rs | 1 - tests/ui/abi/simd-abi-checks-s390x.rs | 4 +-- tests/ui/abi/simd-abi-checks-s390x.z10.stderr | 20 +++++++------- ...simd-abi-checks-s390x.z13_no_vector.stderr | 26 ++++++++----------- ...imd-abi-checks-s390x.z13_soft_float.stderr | 26 ++++++++----------- tests/ui/target-feature/gate.rs | 1 - tests/ui/target-feature/gate.stderr | 2 +- 15 files changed, 62 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 364a1202b05c2..0ee4ad409e4bd 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -387,6 +387,8 @@ declare_features! ( (accepted, return_position_impl_trait_in_trait, "1.75.0", Some(91611)), /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414). (accepted, rvalue_static_promotion, "1.21.0", Some(38865)), + /// Allows use of the `vector` and related s390x target features. + (accepted, s390x_target_feature_vector, "CURRENT_RUSTC_VERSION", Some(145649)), /// Allows `Self` in type definitions (RFC 2300). (accepted, self_in_typedefs, "1.32.0", Some(49303)), /// Allows `Self` struct constructor (RFC 2302). diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index b4fc1e8d9c1c3..8397cd294e0a9 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -343,7 +343,6 @@ declare_features! ( (unstable, riscv_target_feature, "1.45.0", Some(44839)), (unstable, rtm_target_feature, "1.35.0", Some(44839)), (unstable, s390x_target_feature, "1.82.0", Some(44839)), - (unstable, s390x_target_feature_vector, "CURRENT_RUSTC_VERSION", Some(145649)), (unstable, sparc_target_feature, "1.84.0", Some(132783)), (unstable, wasm_target_feature, "1.30.0", Some(44839)), (unstable, x87_target_feature, "1.85.0", Some(44839)), diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index d2684183821f8..1789e52ed26ff 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -844,20 +844,20 @@ const IBMZ_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("message-security-assist-extension8", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3"]), ("message-security-assist-extension9", Unstable(sym::s390x_target_feature), &["message-security-assist-extension3", "message-security-assist-extension4"]), ("message-security-assist-extension12", Unstable(sym::s390x_target_feature), &[]), - ("miscellaneous-extensions-2", Unstable(sym::s390x_target_feature_vector), &[]), - ("miscellaneous-extensions-3", Unstable(sym::s390x_target_feature_vector), &[]), - ("miscellaneous-extensions-4", Unstable(sym::s390x_target_feature_vector), &[]), - ("nnp-assist", Unstable(sym::s390x_target_feature_vector), &["vector"]), + ("miscellaneous-extensions-2", Stable, &[]), + ("miscellaneous-extensions-3", Stable, &[]), + ("miscellaneous-extensions-4", Stable, &[]), + ("nnp-assist", Stable, &["vector"]), ("soft-float", Forbidden { reason: "currently unsupported ABI-configuration feature" }, &[]), ("transactional-execution", Unstable(sym::s390x_target_feature), &[]), - ("vector", Unstable(sym::s390x_target_feature_vector), &[]), - ("vector-enhancements-1", Unstable(sym::s390x_target_feature_vector), &["vector"]), - ("vector-enhancements-2", Unstable(sym::s390x_target_feature_vector), &["vector-enhancements-1"]), - ("vector-enhancements-3", Unstable(sym::s390x_target_feature_vector), &["vector-enhancements-2"]), - ("vector-packed-decimal", Unstable(sym::s390x_target_feature_vector), &["vector"]), - ("vector-packed-decimal-enhancement", Unstable(sym::s390x_target_feature_vector), &["vector-packed-decimal"]), - ("vector-packed-decimal-enhancement-2", Unstable(sym::s390x_target_feature_vector), &["vector-packed-decimal-enhancement"]), - ("vector-packed-decimal-enhancement-3", Unstable(sym::s390x_target_feature_vector), &["vector-packed-decimal-enhancement-2"]), + ("vector", Stable, &[]), + ("vector-enhancements-1", Stable, &["vector"]), + ("vector-enhancements-2", Stable, &["vector-enhancements-1"]), + ("vector-enhancements-3", Stable, &["vector-enhancements-2"]), + ("vector-packed-decimal", Stable, &["vector"]), + ("vector-packed-decimal-enhancement", Stable, &["vector-packed-decimal"]), + ("vector-packed-decimal-enhancement-2", Stable, &["vector-packed-decimal-enhancement"]), + ("vector-packed-decimal-enhancement-3", Stable, &["vector-packed-decimal-enhancement-2"]), // tidy-alphabetical-end ]; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 1c0a5631665eb..f1948fc778ce2 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -204,7 +204,6 @@ #![feature(riscv_target_feature)] #![feature(rtm_target_feature)] #![feature(s390x_target_feature)] -#![feature(s390x_target_feature_vector)] #![feature(wasm_target_feature)] #![feature(x86_amx_intrinsics)] // tidy-alphabetical-end diff --git a/library/std_detect/src/detect/arch/s390x.rs b/library/std_detect/src/detect/arch/s390x.rs index d9026873c4b54..b56112831caaf 100644 --- a/library/std_detect/src/detect/arch/s390x.rs +++ b/library/std_detect/src/detect/arch/s390x.rs @@ -29,30 +29,30 @@ features! { /// s390x message-security-assist-extension9 facility @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] message_security_assist_extension12: "message-security-assist-extension12"; /// s390x message-security-assist-extension12 facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] miscellaneous_extensions_2: "miscellaneous-extensions-2"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] miscellaneous_extensions_2: "miscellaneous-extensions-2"; /// s390x miscellaneous-extensions-2 facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] miscellaneous_extensions_3: "miscellaneous-extensions-3"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] miscellaneous_extensions_3: "miscellaneous-extensions-3"; /// s390x miscellaneous-extensions-3 facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] miscellaneous_extensions_4: "miscellaneous-extensions-4"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] miscellaneous_extensions_4: "miscellaneous-extensions-4"; /// s390x miscellaneous-extensions-4 facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] nnp_assist: "nnp-assist"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] nnp_assist: "nnp-assist"; /// s390x nnp-assist facility @FEATURE: #[unstable(feature = "s390x_target_feature", issue = "44839")] transactional_execution: "transactional-execution"; /// s390x transactional-execution facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector: "vector"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] vector: "vector"; /// s390x vector facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_enhancements_1: "vector-enhancements-1"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] vector_enhancements_1: "vector-enhancements-1"; /// s390x vector-enhancements-1 facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_enhancements_2: "vector-enhancements-2"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] vector_enhancements_2: "vector-enhancements-2"; /// s390x vector-enhancements-2 facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_enhancements_3: "vector-enhancements-3"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] vector_enhancements_3: "vector-enhancements-3"; /// s390x vector-enhancements-3 facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_packed_decimal: "vector-packed-decimal"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] vector_packed_decimal: "vector-packed-decimal"; /// s390x vector-packed-decimal facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_packed_decimal_enhancement: "vector-packed-decimal-enhancement"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] vector_packed_decimal_enhancement: "vector-packed-decimal-enhancement"; /// s390x vector-packed-decimal-enhancement facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_packed_decimal_enhancement_2: "vector-packed-decimal-enhancement-2"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] vector_packed_decimal_enhancement_2: "vector-packed-decimal-enhancement-2"; /// s390x vector-packed-decimal-enhancement-2 facility - @FEATURE: #[unstable(feature = "s390x_target_feature_vector", issue = "145649")] vector_packed_decimal_enhancement_3: "vector-packed-decimal-enhancement-3"; + @FEATURE: #[stable(feature = "s390x_target_feature_vector", since = "CURRENT_RUSTC_VERSION")] vector_packed_decimal_enhancement_3: "vector-packed-decimal-enhancement-3"; /// s390x vector-packed-decimal-enhancement-3 facility } diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index ed9138f343a18..06cbd32d67729 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -22,7 +22,6 @@ arm_target_feature, mips_target_feature, powerpc_target_feature, - s390x_target_feature_vector, loongarch_target_feature, wasm_target_feature, abi_unadjusted, diff --git a/tests/assembly-llvm/s390x-vector-abi.rs b/tests/assembly-llvm/s390x-vector-abi.rs index 0de5fb15eb4c7..90139df17ca1a 100644 --- a/tests/assembly-llvm/s390x-vector-abi.rs +++ b/tests/assembly-llvm/s390x-vector-abi.rs @@ -12,7 +12,7 @@ //@[z13_no_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector --cfg no_vector //@[z13_no_vector] needs-llvm-components: systemz -#![feature(no_core, lang_items, repr_simd, s390x_target_feature_vector)] +#![feature(no_core, lang_items, repr_simd)] #![no_core] #![crate_type = "lib"] #![allow(non_camel_case_types)] diff --git a/tests/codegen-llvm/s390x-simd.rs b/tests/codegen-llvm/s390x-simd.rs index 83e9d274bb551..8439e79716746 100644 --- a/tests/codegen-llvm/s390x-simd.rs +++ b/tests/codegen-llvm/s390x-simd.rs @@ -6,7 +6,7 @@ #![crate_type = "rlib"] #![feature(no_core, asm_experimental_arch)] -#![feature(s390x_target_feature_vector, simd_ffi, intrinsics, repr_simd)] +#![feature(simd_ffi, intrinsics, repr_simd)] #![no_core] extern crate minicore; diff --git a/tests/codegen-llvm/simd/extract-insert-dyn.rs b/tests/codegen-llvm/simd/extract-insert-dyn.rs index 019fa1d72e369..e634841fae79d 100644 --- a/tests/codegen-llvm/simd/extract-insert-dyn.rs +++ b/tests/codegen-llvm/simd/extract-insert-dyn.rs @@ -5,7 +5,6 @@ repr_simd, arm_target_feature, mips_target_feature, - s390x_target_feature_vector, riscv_target_feature )] #![no_std] diff --git a/tests/ui/abi/simd-abi-checks-s390x.rs b/tests/ui/abi/simd-abi-checks-s390x.rs index e5d737db21239..c8f4483650ccd 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.rs +++ b/tests/ui/abi/simd-abi-checks-s390x.rs @@ -10,11 +10,9 @@ //@[z13_soft_float] needs-llvm-components: systemz //@ ignore-backends: gcc //[z13_soft_float]~? WARN must be disabled to ensure that the ABI of the current target can be implemented correctly - -//[z13_no_vector,z13_soft_float]~? WARN unstable feature specified for `-Ctarget-feature` //[z13_soft_float]~? WARN target feature `soft-float` cannot be enabled with `-Ctarget-feature` -#![feature(no_core, repr_simd, s390x_target_feature_vector)] +#![feature(no_core, repr_simd)] #![no_core] #![crate_type = "lib"] #![allow(non_camel_case_types, improper_ctypes_definitions)] diff --git a/tests/ui/abi/simd-abi-checks-s390x.z10.stderr b/tests/ui/abi/simd-abi-checks-s390x.z10.stderr index 769f8a0b19114..0a40658fa66bf 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.z10.stderr +++ b/tests/ui/abi/simd-abi-checks-s390x.z10.stderr @@ -1,5 +1,5 @@ error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:43:1 + --> $DIR/simd-abi-checks-s390x.rs:41:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -7,7 +7,7 @@ LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:48:1 + --> $DIR/simd-abi-checks-s390x.rs:46:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -15,7 +15,7 @@ LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:94:1 + --> $DIR/simd-abi-checks-s390x.rs:92:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -25,7 +25,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:101:1 + --> $DIR/simd-abi-checks-s390x.rs:99:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -35,7 +35,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:116:1 + --> $DIR/simd-abi-checks-s390x.rs:114:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -43,7 +43,7 @@ LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:121:1 + --> $DIR/simd-abi-checks-s390x.rs:119:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -51,7 +51,7 @@ LL | extern "C" fn vector_arg(x: i8x16) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:132:1 + --> $DIR/simd-abi-checks-s390x.rs:130:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -59,7 +59,7 @@ LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:137:1 + --> $DIR/simd-abi-checks-s390x.rs:135:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -67,7 +67,7 @@ LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:148:1 + --> $DIR/simd-abi-checks-s390x.rs:146:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -75,7 +75,7 @@ LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:153:1 + --> $DIR/simd-abi-checks-s390x.rs:151:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here diff --git a/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr b/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr index 7709c396605e9..0a40658fa66bf 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr +++ b/tests/ui/abi/simd-abi-checks-s390x.z13_no_vector.stderr @@ -1,9 +1,5 @@ -warning: unstable feature specified for `-Ctarget-feature`: `vector` - | - = note: this feature is not stably supported; its behavior can change in the future - error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:43:1 + --> $DIR/simd-abi-checks-s390x.rs:41:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -11,7 +7,7 @@ LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:48:1 + --> $DIR/simd-abi-checks-s390x.rs:46:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -19,7 +15,7 @@ LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:94:1 + --> $DIR/simd-abi-checks-s390x.rs:92:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -29,7 +25,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:101:1 + --> $DIR/simd-abi-checks-s390x.rs:99:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -39,7 +35,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:116:1 + --> $DIR/simd-abi-checks-s390x.rs:114:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -47,7 +43,7 @@ LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:121:1 + --> $DIR/simd-abi-checks-s390x.rs:119:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -55,7 +51,7 @@ LL | extern "C" fn vector_arg(x: i8x16) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:132:1 + --> $DIR/simd-abi-checks-s390x.rs:130:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -63,7 +59,7 @@ LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:137:1 + --> $DIR/simd-abi-checks-s390x.rs:135:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -71,7 +67,7 @@ LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:148:1 + --> $DIR/simd-abi-checks-s390x.rs:146:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -79,12 +75,12 @@ LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:153:1 + --> $DIR/simd-abi-checks-s390x.rs:151:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: aborting due to 10 previous errors; 1 warning emitted +error: aborting due to 10 previous errors diff --git a/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr b/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr index 6a202eac7e1e5..0e8e6637507d5 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr +++ b/tests/ui/abi/simd-abi-checks-s390x.z13_soft_float.stderr @@ -1,7 +1,3 @@ -warning: unstable feature specified for `-Ctarget-feature`: `vector` - | - = note: this feature is not stably supported; its behavior can change in the future - warning: target feature `soft-float` cannot be enabled with `-Ctarget-feature`: currently unsupported ABI-configuration feature | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! @@ -13,7 +9,7 @@ warning: target feature `soft-float` must be disabled to ensure that the ABI of = note: for more information, see issue #116344 error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:43:1 + --> $DIR/simd-abi-checks-s390x.rs:41:1 | LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -21,7 +17,7 @@ LL | extern "C" fn vector_ret_small(x: &i8x8) -> i8x8 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:48:1 + --> $DIR/simd-abi-checks-s390x.rs:46:1 | LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -29,7 +25,7 @@ LL | extern "C" fn vector_ret(x: &i8x16) -> i8x16 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:94:1 + --> $DIR/simd-abi-checks-s390x.rs:92:1 | LL | / extern "C" fn vector_transparent_wrapper_ret_small( LL | | x: &TransparentWrapper, @@ -39,7 +35,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:101:1 + --> $DIR/simd-abi-checks-s390x.rs:99:1 | LL | / extern "C" fn vector_transparent_wrapper_ret( LL | | x: &TransparentWrapper, @@ -49,7 +45,7 @@ LL | | ) -> TransparentWrapper { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x8` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:116:1 + --> $DIR/simd-abi-checks-s390x.rs:114:1 | LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -57,7 +53,7 @@ LL | extern "C" fn vector_arg_small(x: i8x8) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `i8x16` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:121:1 + --> $DIR/simd-abi-checks-s390x.rs:119:1 | LL | extern "C" fn vector_arg(x: i8x16) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -65,7 +61,7 @@ LL | extern "C" fn vector_arg(x: i8x16) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:132:1 + --> $DIR/simd-abi-checks-s390x.rs:130:1 | LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -73,7 +69,7 @@ LL | extern "C" fn vector_wrapper_arg_small(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:137:1 + --> $DIR/simd-abi-checks-s390x.rs:135:1 | LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -81,7 +77,7 @@ LL | extern "C" fn vector_wrapper_arg(x: Wrapper) -> i64 { = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) error: this function definition uses SIMD vector type `TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:148:1 + --> $DIR/simd-abi-checks-s390x.rs:146:1 | LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -89,12 +85,12 @@ LL | extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper` which (with the chosen ABI) requires the `vector` target feature, which is not enabled - --> $DIR/simd-abi-checks-s390x.rs:153:1 + --> $DIR/simd-abi-checks-s390x.rs:151:1 | LL | extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper) -> i64 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here | = help: consider enabling it globally (`-C target-feature=+vector`) or locally (`#[target_feature(enable="vector")]`) -error: aborting due to 10 previous errors; 3 warnings emitted +error: aborting due to 10 previous errors; 2 warnings emitted diff --git a/tests/ui/target-feature/gate.rs b/tests/ui/target-feature/gate.rs index 9afc6fb2b0f4a..fc3763820cbec 100644 --- a/tests/ui/target-feature/gate.rs +++ b/tests/ui/target-feature/gate.rs @@ -17,7 +17,6 @@ // gate-test-lahfsahf_target_feature // gate-test-prfchw_target_feature // gate-test-s390x_target_feature -// gate-test-s390x_target_feature_vector // gate-test-sparc_target_feature // gate-test-x87_target_feature // gate-test-m68k_target_feature diff --git a/tests/ui/target-feature/gate.stderr b/tests/ui/target-feature/gate.stderr index b3567c0091c60..345dc2006d0bf 100644 --- a/tests/ui/target-feature/gate.stderr +++ b/tests/ui/target-feature/gate.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `x87` is currently unstable - --> $DIR/gate.rs:25:18 + --> $DIR/gate.rs:24:18 | LL | #[target_feature(enable = "x87")] | ^^^^^^^^^^^^^^