diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index e6b76f74158b8..8b7aa1d6b4e97 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 ff9607e715ec2..96af90cd272b2 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 1124b0ac1aee5..fa730bae610cd 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1227,7 +1227,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"); } @@ -2497,11 +2497,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_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index d3468499b4b3a..83de7d3892314 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2875,6 +2875,71 @@ enum AsmLabelKind { Binary, } +/// Checks if a potential label is actually a Hexagon register span notation. +/// +/// Hexagon assembly uses register span notation like `r1:0`, `V5:4.w`, `p1:0` etc. +/// These follow the pattern: `[letter][digit(s)]:[digit(s)][optional_suffix]` +/// +/// Returns `true` if the string matches a valid Hexagon register span pattern. +pub fn is_hexagon_register_span(possible_label: &str) -> bool { + // Extract the full register span from the context + if let Some(colon_idx) = possible_label.find(':') { + let after_colon = &possible_label[colon_idx + 1..]; + is_hexagon_register_span_impl(&possible_label[..colon_idx], after_colon) + } else { + false + } +} + +/// Helper function for use within the lint when we have statement context. +fn is_hexagon_register_span_context( + possible_label: &str, + statement: &str, + colon_idx: usize, +) -> bool { + // Extract what comes after the colon in the statement + let after_colon_start = colon_idx + 1; + if after_colon_start >= statement.len() { + return false; + } + + // Get the part after the colon, up to the next whitespace or special character + let after_colon_full = &statement[after_colon_start..]; + let after_colon = after_colon_full + .chars() + .take_while(|&c| c.is_ascii_alphanumeric() || c == '.') + .collect::(); + + is_hexagon_register_span_impl(possible_label, &after_colon) +} + +/// Core implementation for checking hexagon register spans. +fn is_hexagon_register_span_impl(before_colon: &str, after_colon: &str) -> bool { + if before_colon.len() < 1 || after_colon.is_empty() { + return false; + } + + let mut chars = before_colon.chars(); + let start = chars.next().unwrap(); + + // Must start with a letter (r, V, p, etc.) + if !start.is_ascii_alphabetic() { + return false; + } + + let rest = &before_colon[1..]; + + // Check if the part after the first letter is all digits and non-empty + if rest.is_empty() || !rest.chars().all(|c| c.is_ascii_digit()) { + return false; + } + + // Check if after colon starts with digits (may have suffix like .w, .h) + let digits_after = after_colon.chars().take_while(|c| c.is_ascii_digit()).collect::(); + + !digits_after.is_empty() +} + impl<'tcx> LateLintPass<'tcx> for AsmLabels { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { if let hir::Expr { @@ -2957,6 +3022,14 @@ impl<'tcx> LateLintPass<'tcx> for AsmLabels { break 'label_loop; } + // Check for Hexagon register span notation (e.g., "r1:0", "V5:4", "V3:2.w") + // This is valid Hexagon assembly syntax, not a label + if matches!(cx.tcx.sess.asm_arch, Some(InlineAsmArch::Hexagon)) + && is_hexagon_register_span_context(possible_label, statement, idx) + { + break 'label_loop; + } + for c in chars { // Inside a template format arg, any character is permitted for the // purposes of label detection because we assume that it can be diff --git a/compiler/rustc_lint/src/tests.rs b/compiler/rustc_lint/src/tests.rs index f49301b0215db..b3c91583914a1 100644 --- a/compiler/rustc_lint/src/tests.rs +++ b/compiler/rustc_lint/src/tests.rs @@ -2,6 +2,7 @@ use rustc_span::{Symbol, create_default_session_globals_then}; +use crate::builtin::is_hexagon_register_span; use crate::levels::parse_lint_and_tool_name; #[test] @@ -27,3 +28,29 @@ fn parse_lint_multiple_path() { ) }); } + +#[test] +fn test_hexagon_register_span_patterns() { + // Valid Hexagon register span patterns + assert!(is_hexagon_register_span("r1:0")); + assert!(is_hexagon_register_span("r15:14")); + assert!(is_hexagon_register_span("V5:4")); + assert!(is_hexagon_register_span("V3:2")); + assert!(is_hexagon_register_span("V5:4.w")); + assert!(is_hexagon_register_span("V3:2.h")); + assert!(is_hexagon_register_span("r99:98")); + assert!(is_hexagon_register_span("V123:122.whatever")); + + // Invalid patterns - these should be treated as potential labels + assert!(!is_hexagon_register_span("label1")); + assert!(!is_hexagon_register_span("foo:")); + assert!(!is_hexagon_register_span(":0")); + assert!(!is_hexagon_register_span("r:0")); // missing digits before colon + assert!(!is_hexagon_register_span("r1:")); // missing digits after colon + assert!(!is_hexagon_register_span("r1:a")); // non-digit after colon + assert!(!is_hexagon_register_span("1:0")); // starts with digit, not letter + assert!(!is_hexagon_register_span("r1")); // no colon + assert!(!is_hexagon_register_span("r")); // too short + assert!(!is_hexagon_register_span("")); // empty + assert!(!is_hexagon_register_span("ra:0")); // letter in first digit group +} 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 8f51cbe0217cb..2d2eedd2ba5a0 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 4654527490245..26ff87417ab0d 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 c9d73adf31d49..b49194b82f3a8 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 16f9774554e1b..0f8f260cb820f 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 c25628c3939db..9f9c8d5221df2 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 74048d351802a..023c62812c865 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2410,6 +2410,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, @@ -2658,6 +2665,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 b5907c6b1af2e..6489e2bda8091 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 c3a45254b712c..212704832e55d 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 { diff --git a/library/std_detect/src/detect/arch/aarch64.rs b/library/std_detect/src/detect/arch/aarch64.rs index 13570a25c1cfe..5e85e96374eda 100644 --- a/library/std_detect/src/detect/arch/aarch64.rs +++ b/library/std_detect/src/detect/arch/aarch64.rs @@ -5,13 +5,18 @@ features! { @CFG: any(target_arch = "aarch64", target_arch = "arm64ec"); @MACRO_NAME: is_aarch64_feature_detected; @MACRO_ATTRS: - /// This macro tests, at runtime, whether an `aarch64` feature is enabled on aarch64 platforms. - /// Currently most features are only supported on linux-based platforms. + /// Check for the presence of a CPU feature at runtime. + /// + /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) + /// the macro expands to `true`. /// /// This macro takes one argument which is a string literal of the feature being tested for. /// The feature names are mostly taken from their FEAT_* definitions in the [ARM Architecture /// Reference Manual][docs]. /// + /// Currently most features are only supported on linux-based platforms: on other platforms the + /// runtime check will always return `false`. + /// /// ## Supported arguments /// /// * `"aes"` - FEAT_AES & FEAT_PMULL diff --git a/library/std_detect/src/detect/arch/arm.rs b/library/std_detect/src/detect/arch/arm.rs index c3c8883ce3153..75b8ca9a1e880 100644 --- a/library/std_detect/src/detect/arch/arm.rs +++ b/library/std_detect/src/detect/arch/arm.rs @@ -5,7 +5,10 @@ features! { @CFG: target_arch = "arm"; @MACRO_NAME: is_arm_feature_detected; @MACRO_ATTRS: - /// Checks if `arm` feature is enabled. + /// Check for the presence of a CPU feature at runtime. + /// + /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) + /// the macro expands to `true`. #[unstable(feature = "stdarch_arm_feature_detection", issue = "111190")] @NO_RUNTIME_DETECTION: "v7"; @NO_RUNTIME_DETECTION: "vfp2"; diff --git a/library/std_detect/src/detect/arch/loongarch.rs b/library/std_detect/src/detect/arch/loongarch.rs index d5a442fbbb8a4..6299627738111 100644 --- a/library/std_detect/src/detect/arch/loongarch.rs +++ b/library/std_detect/src/detect/arch/loongarch.rs @@ -5,7 +5,11 @@ features! { @CFG: any(target_arch = "loongarch32", target_arch = "loongarch64"); @MACRO_NAME: is_loongarch_feature_detected; @MACRO_ATTRS: - /// Checks if `loongarch` feature is enabled. + /// Check for the presence of a CPU feature at runtime. + /// + /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) + /// the macro expands to `true`. + /// /// Supported arguments are: /// /// * `"32s"` diff --git a/library/std_detect/src/detect/arch/mips.rs b/library/std_detect/src/detect/arch/mips.rs index e185fdfcaac6c..9e1960eb96da5 100644 --- a/library/std_detect/src/detect/arch/mips.rs +++ b/library/std_detect/src/detect/arch/mips.rs @@ -5,7 +5,10 @@ features! { @CFG: target_arch = "mips"; @MACRO_NAME: is_mips_feature_detected; @MACRO_ATTRS: - /// Checks if `mips` feature is enabled. + /// Check for the presence of a CPU feature at runtime. + /// + /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) + /// the macro expands to `true`. #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] @FEATURE: #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] msa: "msa"; /// MIPS SIMD Architecture (MSA) diff --git a/library/std_detect/src/detect/arch/mips64.rs b/library/std_detect/src/detect/arch/mips64.rs index 69fe4869d30eb..2bb44ba6e2b39 100644 --- a/library/std_detect/src/detect/arch/mips64.rs +++ b/library/std_detect/src/detect/arch/mips64.rs @@ -5,7 +5,10 @@ features! { @CFG: target_arch = "mips64"; @MACRO_NAME: is_mips64_feature_detected; @MACRO_ATTRS: - /// Checks if `mips64` feature is enabled. + /// Check for the presence of a CPU feature at runtime. + /// + /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) + /// the macro expands to `true`. #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] @FEATURE: #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] msa: "msa"; /// MIPS SIMD Architecture (MSA) diff --git a/library/std_detect/src/detect/arch/powerpc.rs b/library/std_detect/src/detect/arch/powerpc.rs index c390993a48a69..be2db0b81c2fc 100644 --- a/library/std_detect/src/detect/arch/powerpc.rs +++ b/library/std_detect/src/detect/arch/powerpc.rs @@ -5,7 +5,10 @@ features! { @CFG: target_arch = "powerpc"; @MACRO_NAME: is_powerpc_feature_detected; @MACRO_ATTRS: - /// Checks if `powerpc` feature is enabled. + /// Check for the presence of a CPU feature at runtime. + /// + /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) + /// the macro expands to `true`. #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] @FEATURE: #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] altivec: "altivec"; /// Altivec diff --git a/library/std_detect/src/detect/arch/powerpc64.rs b/library/std_detect/src/detect/arch/powerpc64.rs index cf05baa6f799e..98e8d5f32b75c 100644 --- a/library/std_detect/src/detect/arch/powerpc64.rs +++ b/library/std_detect/src/detect/arch/powerpc64.rs @@ -5,7 +5,10 @@ features! { @CFG: target_arch = "powerpc64"; @MACRO_NAME: is_powerpc64_feature_detected; @MACRO_ATTRS: - /// Checks if `powerpc` feature is enabled. + /// Check for the presence of a CPU feature at runtime. + /// + /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) + /// the macro expands to `true`. #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] @FEATURE: #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] altivec: "altivec"; /// Altivec diff --git a/library/std_detect/src/detect/arch/riscv.rs b/library/std_detect/src/detect/arch/riscv.rs index 1e57d09edb143..846d7f10d68fc 100644 --- a/library/std_detect/src/detect/arch/riscv.rs +++ b/library/std_detect/src/detect/arch/riscv.rs @@ -5,8 +5,10 @@ features! { @CFG: any(target_arch = "riscv32", target_arch = "riscv64"); @MACRO_NAME: is_riscv_feature_detected; @MACRO_ATTRS: - /// A macro to test at *runtime* whether instruction sets are available on - /// RISC-V platforms. + /// Check for the presence of a CPU feature at runtime. + /// + /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) + /// the macro expands to `true`. /// /// RISC-V standard defined the base sets and the extension sets. /// The base sets are RV32I, RV64I, RV32E or RV128I. Any RISC-V platform diff --git a/library/std_detect/src/detect/arch/s390x.rs b/library/std_detect/src/detect/arch/s390x.rs index 4c20d011680bc..d59fbc7de3bd6 100644 --- a/library/std_detect/src/detect/arch/s390x.rs +++ b/library/std_detect/src/detect/arch/s390x.rs @@ -5,7 +5,10 @@ features! { @CFG: target_arch = "s390x"; @MACRO_NAME: is_s390x_feature_detected; @MACRO_ATTRS: - /// Checks if `s390x` feature is enabled. + /// Check for the presence of a CPU feature at runtime. + /// + /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) + /// the macro expands to `true`. #[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 diff --git a/library/std_detect/src/detect/arch/x86.rs b/library/std_detect/src/detect/arch/x86.rs index e4318bedb2a6f..4c3a71ebc5ee7 100644 --- a/library/std_detect/src/detect/arch/x86.rs +++ b/library/std_detect/src/detect/arch/x86.rs @@ -20,13 +20,12 @@ features! { @CFG: any(target_arch = "x86", target_arch = "x86_64"); @MACRO_NAME: is_x86_feature_detected; @MACRO_ATTRS: - /// A macro to test at *runtime* whether a CPU feature is available on - /// x86/x86-64 platforms. + /// Check for the presence of a CPU feature at runtime. /// - /// This macro is provided in the standard library and will detect at runtime - /// whether the specified CPU feature is detected. This does **not** resolve at - /// compile time unless the specified feature is already enabled for the entire - /// crate. Runtime detection currently relies mostly on the `cpuid` instruction. + /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) + /// the macro expands to `true`. + /// + /// Runtime detection currently relies mostly on the `cpuid` instruction. /// /// This macro only takes one argument which is a string literal of the feature /// being tested for. The feature names supported are the lowercase versions of 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 diff --git a/src/etc/gdb_providers.py b/src/etc/gdb_providers.py index c8f4a32cb17e2..676842f66240d 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" @@ -252,15 +261,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 @@ -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" diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 631c48a4fdb85..a8d5ed9fa7361 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -671,7 +671,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 {:?}: {error:?}", compiler.get_program()); + 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"); @@ -733,7 +739,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 {:?}: {error:?}", runner_compiler.get_program()); + return (Duration::default(), Err(TestFailure::CompileError)); + } + }; child_runner.wait().expect("Failed to wait") }; 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/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 ================================================================================== 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/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..9aa8143dc1dc4 --- /dev/null +++ b/tests/run-make/rustdoc-test-builder/rmake.rs @@ -0,0 +1,22 @@ +// 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 check that rustdoc outputs the error correctly... + output.assert_stdout_contains("Failed to spawn "); + // ... and that we didn't panic. + output.assert_not_ice(); +} diff --git a/tests/ui/asm/hexagon-register-pairs.rs b/tests/ui/asm/hexagon-register-pairs.rs new file mode 100644 index 0000000000000..75f2960778455 --- /dev/null +++ b/tests/ui/asm/hexagon-register-pairs.rs @@ -0,0 +1,37 @@ +//@ add-minicore +//@ compile-flags: --target hexagon-unknown-linux-musl -C target-feature=+hvx-length128b +//@ needs-llvm-components: hexagon +//@ ignore-backends: gcc + +#![feature(no_core, asm_experimental_arch)] +#![crate_type = "lib"] +#![no_core] + +//~? WARN unstable feature specified for `-Ctarget-feature`: `hvx-length128b` + +extern crate minicore; +use minicore::*; + +fn test_register_spans() { + unsafe { + // These are valid Hexagon register span notations, not labels + // Should NOT trigger the named labels lint + + // General register pairs + asm!("r1:0 = memd(r29+#0)", lateout("r0") _, lateout("r1") _); + asm!("r3:2 = combine(#1, #0)", lateout("r2") _, lateout("r3") _); + asm!("r15:14 = memd(r30+#8)", lateout("r14") _, lateout("r15") _); + asm!("memd(r29+#0) = r5:4", in("r4") 0u32, in("r5") 0u32); + + // These patterns look like register spans but test different edge cases + // All should NOT trigger the lint as they match valid hexagon register syntax patterns + asm!("V5:4 = vaddw(v1:0, v1:0)", options(nostack)); // Uppercase V register pair + asm!("v1:0.w = vsub(v1:0.w,v1:0.w):sat", options(nostack)); // Lowercase v with suffix + + // Mixed with actual labels should still trigger for the labels + asm!("label1: r7:6 = combine(#2, #3)"); //~ ERROR avoid using named labels + + // Regular labels should still trigger + asm!("hexagon_label: nop"); //~ ERROR avoid using named labels + } +} diff --git a/tests/ui/asm/hexagon-register-pairs.stderr b/tests/ui/asm/hexagon-register-pairs.stderr new file mode 100644 index 0000000000000..c5974ba01f176 --- /dev/null +++ b/tests/ui/asm/hexagon-register-pairs.stderr @@ -0,0 +1,25 @@ +warning: unstable feature specified for `-Ctarget-feature`: `hvx-length128b` + | + = note: this feature is not stably supported; its behavior can change in the future + +error: avoid using named labels in inline assembly + --> $DIR/hexagon-register-pairs.rs:32:15 + | +LL | asm!("label1: r7:6 = combine(#2, #3)"); + | ^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + = note: `#[deny(named_asm_labels)]` on by default + +error: avoid using named labels in inline assembly + --> $DIR/hexagon-register-pairs.rs:35:15 + | +LL | asm!("hexagon_label: nop"); + | ^^^^^^^^^^^^^ + | + = help: only local labels of the form `:` should be used in inline asm + = note: see the asm section of Rust By Example for more information + +error: aborting due to 2 previous errors; 1 warning emitted +