| author | bors <bors@rust-lang.org> 2025-11-06 08:39:07 UTC |
| committer | bors <bors@rust-lang.org> 2025-11-06 08:39:07 UTC |
| log | 642c19bfc3a5c1de985bf5d0cc8207ac9d22708a |
| tree | c007e53a7c68a0ac9fed825f6b0801b160d80316 |
| parent | 401ae55427522984e4a89c37cff6562a4ddcf6b7 |
| parent | 7c58e15300c3c175be8c3a23ba20e6b4579c003a |
Rollup of 7 pull requests
Successful merges:
- rust-lang/rust#143037 (Make named asm_labels lint not trigger on hexagon register spans)
- rust-lang/rust#147043 (Add default sanitizers to TargetOptions)
- rust-lang/rust#147586 (std-detect: improve detect macro docs)
- rust-lang/rust#147912 ([rustdoc] Gracefully handle error in case we cannot run the compiler in doctests)
- rust-lang/rust#148540 (Minor fixes to StdNonZeroNumberProvider for gdb)
- rust-lang/rust#148541 (Add num_children method to some gdb pretty-printers)
- rust-lang/rust#148549 (Fix broken qemu-cskyv2 link)
Failed merges:
- rust-lang/rust#147935 (Add LLVM realtime sanitizer)
r? `@ghost`
`@rustbot` modify labels: rollup36 files changed, 320 insertions(+), 57 deletions(-)
compiler/rustc_codegen_llvm/src/abi.rs+1-1| ... | ... | @@ -96,7 +96,7 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&' |
| 96 | 96 | } |
| 97 | 97 | } |
| 98 | 98 | } |
| 99 | } else if cx.tcx.sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::MEMORY) { | |
| 99 | } else if cx.tcx.sess.sanitizers().contains(SanitizerSet::MEMORY) { | |
| 100 | 100 | // If we're not optimising, *but* memory sanitizer is on, emit noundef, since it affects |
| 101 | 101 | // memory sanitizer's behavior. |
| 102 | 102 |
compiler/rustc_codegen_llvm/src/attributes.rs+2-8| ... | ... | @@ -101,7 +101,7 @@ pub(crate) fn sanitize_attrs<'ll, 'tcx>( |
| 101 | 101 | no_sanitize: SanitizerSet, |
| 102 | 102 | ) -> SmallVec<[&'ll Attribute; 4]> { |
| 103 | 103 | let mut attrs = SmallVec::new(); |
| 104 | let enabled = tcx.sess.opts.unstable_opts.sanitizer - no_sanitize; | |
| 104 | let enabled = tcx.sess.sanitizers() - no_sanitize; | |
| 105 | 105 | if enabled.contains(SanitizerSet::ADDRESS) || enabled.contains(SanitizerSet::KERNELADDRESS) { |
| 106 | 106 | attrs.push(llvm::AttributeKind::SanitizeAddress.create_attr(cx.llcx)); |
| 107 | 107 | } |
| ... | ... | @@ -240,13 +240,7 @@ fn probestack_attr<'ll, 'tcx>(cx: &SimpleCx<'ll>, tcx: TyCtxt<'tcx>) -> Option<& |
| 240 | 240 | // Currently stack probes seem somewhat incompatible with the address |
| 241 | 241 | // sanitizer and thread sanitizer. With asan we're already protected from |
| 242 | 242 | // stack overflow anyway so we don't really need stack probes regardless. |
| 243 | if tcx | |
| 244 | .sess | |
| 245 | .opts | |
| 246 | .unstable_opts | |
| 247 | .sanitizer | |
| 248 | .intersects(SanitizerSet::ADDRESS | SanitizerSet::THREAD) | |
| 249 | { | |
| 243 | if tcx.sess.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::THREAD) { | |
| 250 | 244 | return None; |
| 251 | 245 | } |
| 252 | 246 |
compiler/rustc_codegen_ssa/src/back/link.rs+2-6| ... | ... | @@ -1227,7 +1227,7 @@ fn add_sanitizer_libraries( |
| 1227 | 1227 | return; |
| 1228 | 1228 | } |
| 1229 | 1229 | |
| 1230 | let sanitizer = sess.opts.unstable_opts.sanitizer; | |
| 1230 | let sanitizer = sess.sanitizers(); | |
| 1231 | 1231 | if sanitizer.contains(SanitizerSet::ADDRESS) { |
| 1232 | 1232 | link_sanitizer_runtime(sess, flavor, linker, "asan"); |
| 1233 | 1233 | } |
| ... | ... | @@ -2497,11 +2497,7 @@ fn add_order_independent_options( |
| 2497 | 2497 | && crate_type == CrateType::Executable |
| 2498 | 2498 | && !matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _)) |
| 2499 | 2499 | { |
| 2500 | let prefix = if sess.opts.unstable_opts.sanitizer.contains(SanitizerSet::ADDRESS) { | |
| 2501 | "asan/" | |
| 2502 | } else { | |
| 2503 | "" | |
| 2504 | }; | |
| 2500 | let prefix = if sess.sanitizers().contains(SanitizerSet::ADDRESS) { "asan/" } else { "" }; | |
| 2505 | 2501 | cmd.link_arg(format!("--dynamic-linker={prefix}ld.so.1")); |
| 2506 | 2502 | } |
| 2507 | 2503 |
compiler/rustc_codegen_ssa/src/back/write.rs+1-1| ... | ... | @@ -176,7 +176,7 @@ impl ModuleConfig { |
| 176 | 176 | debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling, |
| 177 | 177 | instrument_coverage: if_regular!(sess.instrument_coverage(), false), |
| 178 | 178 | |
| 179 | sanitizer: if_regular!(sess.opts.unstable_opts.sanitizer, SanitizerSet::empty()), | |
| 179 | sanitizer: if_regular!(sess.sanitizers(), SanitizerSet::empty()), | |
| 180 | 180 | sanitizer_dataflow_abilist: if_regular!( |
| 181 | 181 | sess.opts.unstable_opts.sanitizer_dataflow_abilist.clone(), |
| 182 | 182 | Vec::new() |
compiler/rustc_lint/src/builtin.rs+73| ... | ... | @@ -2875,6 +2875,71 @@ enum AsmLabelKind { |
| 2875 | 2875 | Binary, |
| 2876 | 2876 | } |
| 2877 | 2877 | |
| 2878 | /// Checks if a potential label is actually a Hexagon register span notation. | |
| 2879 | /// | |
| 2880 | /// Hexagon assembly uses register span notation like `r1:0`, `V5:4.w`, `p1:0` etc. | |
| 2881 | /// These follow the pattern: `[letter][digit(s)]:[digit(s)][optional_suffix]` | |
| 2882 | /// | |
| 2883 | /// Returns `true` if the string matches a valid Hexagon register span pattern. | |
| 2884 | pub fn is_hexagon_register_span(possible_label: &str) -> bool { | |
| 2885 | // Extract the full register span from the context | |
| 2886 | if let Some(colon_idx) = possible_label.find(':') { | |
| 2887 | let after_colon = &possible_label[colon_idx + 1..]; | |
| 2888 | is_hexagon_register_span_impl(&possible_label[..colon_idx], after_colon) | |
| 2889 | } else { | |
| 2890 | false | |
| 2891 | } | |
| 2892 | } | |
| 2893 | ||
| 2894 | /// Helper function for use within the lint when we have statement context. | |
| 2895 | fn is_hexagon_register_span_context( | |
| 2896 | possible_label: &str, | |
| 2897 | statement: &str, | |
| 2898 | colon_idx: usize, | |
| 2899 | ) -> bool { | |
| 2900 | // Extract what comes after the colon in the statement | |
| 2901 | let after_colon_start = colon_idx + 1; | |
| 2902 | if after_colon_start >= statement.len() { | |
| 2903 | return false; | |
| 2904 | } | |
| 2905 | ||
| 2906 | // Get the part after the colon, up to the next whitespace or special character | |
| 2907 | let after_colon_full = &statement[after_colon_start..]; | |
| 2908 | let after_colon = after_colon_full | |
| 2909 | .chars() | |
| 2910 | .take_while(|&c| c.is_ascii_alphanumeric() || c == '.') | |
| 2911 | .collect::<String>(); | |
| 2912 | ||
| 2913 | is_hexagon_register_span_impl(possible_label, &after_colon) | |
| 2914 | } | |
| 2915 | ||
| 2916 | /// Core implementation for checking hexagon register spans. | |
| 2917 | fn is_hexagon_register_span_impl(before_colon: &str, after_colon: &str) -> bool { | |
| 2918 | if before_colon.len() < 1 || after_colon.is_empty() { | |
| 2919 | return false; | |
| 2920 | } | |
| 2921 | ||
| 2922 | let mut chars = before_colon.chars(); | |
| 2923 | let start = chars.next().unwrap(); | |
| 2924 | ||
| 2925 | // Must start with a letter (r, V, p, etc.) | |
| 2926 | if !start.is_ascii_alphabetic() { | |
| 2927 | return false; | |
| 2928 | } | |
| 2929 | ||
| 2930 | let rest = &before_colon[1..]; | |
| 2931 | ||
| 2932 | // Check if the part after the first letter is all digits and non-empty | |
| 2933 | if rest.is_empty() || !rest.chars().all(|c| c.is_ascii_digit()) { | |
| 2934 | return false; | |
| 2935 | } | |
| 2936 | ||
| 2937 | // Check if after colon starts with digits (may have suffix like .w, .h) | |
| 2938 | let digits_after = after_colon.chars().take_while(|c| c.is_ascii_digit()).collect::<String>(); | |
| 2939 | ||
| 2940 | !digits_after.is_empty() | |
| 2941 | } | |
| 2942 | ||
| 2878 | 2943 | impl<'tcx> LateLintPass<'tcx> for AsmLabels { |
| 2879 | 2944 | fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { |
| 2880 | 2945 | if let hir::Expr { |
| ... | ... | @@ -2957,6 +3022,14 @@ impl<'tcx> LateLintPass<'tcx> for AsmLabels { |
| 2957 | 3022 | break 'label_loop; |
| 2958 | 3023 | } |
| 2959 | 3024 | |
| 3025 | // Check for Hexagon register span notation (e.g., "r1:0", "V5:4", "V3:2.w") | |
| 3026 | // This is valid Hexagon assembly syntax, not a label | |
| 3027 | if matches!(cx.tcx.sess.asm_arch, Some(InlineAsmArch::Hexagon)) | |
| 3028 | && is_hexagon_register_span_context(possible_label, statement, idx) | |
| 3029 | { | |
| 3030 | break 'label_loop; | |
| 3031 | } | |
| 3032 | ||
| 2960 | 3033 | for c in chars { |
| 2961 | 3034 | // Inside a template format arg, any character is permitted for the |
| 2962 | 3035 | // purposes of label detection because we assume that it can be |
compiler/rustc_lint/src/tests.rs+27| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | use rustc_span::{Symbol, create_default_session_globals_then}; |
| 4 | 4 | |
| 5 | use crate::builtin::is_hexagon_register_span; | |
| 5 | 6 | use crate::levels::parse_lint_and_tool_name; |
| 6 | 7 | |
| 7 | 8 | #[test] |
| ... | ... | @@ -27,3 +28,29 @@ fn parse_lint_multiple_path() { |
| 27 | 28 | ) |
| 28 | 29 | }); |
| 29 | 30 | } |
| 31 | ||
| 32 | #[test] | |
| 33 | fn test_hexagon_register_span_patterns() { | |
| 34 | // Valid Hexagon register span patterns | |
| 35 | assert!(is_hexagon_register_span("r1:0")); | |
| 36 | assert!(is_hexagon_register_span("r15:14")); | |
| 37 | assert!(is_hexagon_register_span("V5:4")); | |
| 38 | assert!(is_hexagon_register_span("V3:2")); | |
| 39 | assert!(is_hexagon_register_span("V5:4.w")); | |
| 40 | assert!(is_hexagon_register_span("V3:2.h")); | |
| 41 | assert!(is_hexagon_register_span("r99:98")); | |
| 42 | assert!(is_hexagon_register_span("V123:122.whatever")); | |
| 43 | ||
| 44 | // Invalid patterns - these should be treated as potential labels | |
| 45 | assert!(!is_hexagon_register_span("label1")); | |
| 46 | assert!(!is_hexagon_register_span("foo:")); | |
| 47 | assert!(!is_hexagon_register_span(":0")); | |
| 48 | assert!(!is_hexagon_register_span("r:0")); // missing digits before colon | |
| 49 | assert!(!is_hexagon_register_span("r1:")); // missing digits after colon | |
| 50 | assert!(!is_hexagon_register_span("r1:a")); // non-digit after colon | |
| 51 | assert!(!is_hexagon_register_span("1:0")); // starts with digit, not letter | |
| 52 | assert!(!is_hexagon_register_span("r1")); // no colon | |
| 53 | assert!(!is_hexagon_register_span("r")); // too short | |
| 54 | assert!(!is_hexagon_register_span("")); // empty | |
| 55 | assert!(!is_hexagon_register_span("ra:0")); // letter in first digit group | |
| 56 | } |
compiler/rustc_metadata/src/creader.rs+5-5| ... | ... | @@ -412,7 +412,7 @@ impl CStore { |
| 412 | 412 | match (&left_name_val, &right_name_val) { |
| 413 | 413 | (Some(l), Some(r)) => match l.1.opt.cmp(&r.1.opt) { |
| 414 | 414 | cmp::Ordering::Equal => { |
| 415 | if !l.1.consistent(&tcx.sess.opts, Some(&r.1)) { | |
| 415 | if !l.1.consistent(&tcx.sess, Some(&r.1)) { | |
| 416 | 416 | report_diff( |
| 417 | 417 | &l.0.prefix, |
| 418 | 418 | &l.0.name, |
| ... | ... | @@ -424,26 +424,26 @@ impl CStore { |
| 424 | 424 | right_name_val = None; |
| 425 | 425 | } |
| 426 | 426 | cmp::Ordering::Greater => { |
| 427 | if !r.1.consistent(&tcx.sess.opts, None) { | |
| 427 | if !r.1.consistent(&tcx.sess, None) { | |
| 428 | 428 | report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name)); |
| 429 | 429 | } |
| 430 | 430 | right_name_val = None; |
| 431 | 431 | } |
| 432 | 432 | cmp::Ordering::Less => { |
| 433 | if !l.1.consistent(&tcx.sess.opts, None) { | |
| 433 | if !l.1.consistent(&tcx.sess, None) { | |
| 434 | 434 | report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None); |
| 435 | 435 | } |
| 436 | 436 | left_name_val = None; |
| 437 | 437 | } |
| 438 | 438 | }, |
| 439 | 439 | (Some(l), None) => { |
| 440 | if !l.1.consistent(&tcx.sess.opts, None) { | |
| 440 | if !l.1.consistent(&tcx.sess, None) { | |
| 441 | 441 | report_diff(&l.0.prefix, &l.0.name, Some(&l.1.value_name), None); |
| 442 | 442 | } |
| 443 | 443 | left_name_val = None; |
| 444 | 444 | } |
| 445 | 445 | (None, Some(r)) => { |
| 446 | if !r.1.consistent(&tcx.sess.opts, None) { | |
| 446 | if !r.1.consistent(&tcx.sess, None) { | |
| 447 | 447 | report_diff(&r.0.prefix, &r.0.name, None, Some(&r.1.value_name)); |
| 448 | 448 | } |
| 449 | 449 | right_name_val = None; |
compiler/rustc_metadata/src/native_libs.rs+1-1| ... | ... | @@ -71,7 +71,7 @@ pub fn walk_native_lib_search_dirs<R>( |
| 71 | 71 | || sess.target.os == "linux" |
| 72 | 72 | || sess.target.os == "fuchsia" |
| 73 | 73 | || sess.target.is_like_aix |
| 74 | || sess.target.is_like_darwin && !sess.opts.unstable_opts.sanitizer.is_empty() | |
| 74 | || sess.target.is_like_darwin && !sess.sanitizers().is_empty() | |
| 75 | 75 | { |
| 76 | 76 | f(&sess.target_tlib_path.dir, false)?; |
| 77 | 77 | } |
compiler/rustc_session/src/config/cfg.rs+1-1| ... | ... | @@ -224,7 +224,7 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { |
| 224 | 224 | ins_sym!(sym::relocation_model, sess.target.relocation_model.desc_symbol()); |
| 225 | 225 | } |
| 226 | 226 | |
| 227 | for mut s in sess.opts.unstable_opts.sanitizer { | |
| 227 | for mut s in sess.sanitizers() { | |
| 228 | 228 | // KASAN is still ASAN under the hood, so it uses the same attribute. |
| 229 | 229 | if s == SanitizerSet::KERNELADDRESS { |
| 230 | 230 | s = SanitizerSet::ADDRESS; |
compiler/rustc_session/src/options.rs+6-5| ... | ... | @@ -22,7 +22,7 @@ use rustc_target::spec::{ |
| 22 | 22 | use crate::config::*; |
| 23 | 23 | use crate::search_paths::SearchPath; |
| 24 | 24 | use crate::utils::NativeLib; |
| 25 | use crate::{EarlyDiagCtxt, lint}; | |
| 25 | use crate::{EarlyDiagCtxt, Session, lint}; | |
| 26 | 26 | |
| 27 | 27 | macro_rules! insert { |
| 28 | 28 | ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr) => { |
| ... | ... | @@ -111,12 +111,12 @@ mod target_modifier_consistency_check { |
| 111 | 111 | lparsed & tmod_sanitizers == rparsed & tmod_sanitizers |
| 112 | 112 | } |
| 113 | 113 | pub(super) fn sanitizer_cfi_normalize_integers( |
| 114 | opts: &Options, | |
| 114 | sess: &Session, | |
| 115 | 115 | l: &TargetModifier, |
| 116 | 116 | r: Option<&TargetModifier>, |
| 117 | 117 | ) -> bool { |
| 118 | 118 | // For kCFI, the helper flag -Zsanitizer-cfi-normalize-integers should also be a target modifier |
| 119 | if opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI) { | |
| 119 | if sess.sanitizers().contains(SanitizerSet::KCFI) { | |
| 120 | 120 | if let Some(r) = r { |
| 121 | 121 | return l.extend().tech_value == r.extend().tech_value; |
| 122 | 122 | } else { |
| ... | ... | @@ -133,7 +133,7 @@ impl TargetModifier { |
| 133 | 133 | } |
| 134 | 134 | // Custom consistency check for target modifiers (or default `l.tech_value == r.tech_value`) |
| 135 | 135 | // When other is None, consistency with default value is checked |
| 136 | pub fn consistent(&self, opts: &Options, other: Option<&TargetModifier>) -> bool { | |
| 136 | pub fn consistent(&self, sess: &Session, other: Option<&TargetModifier>) -> bool { | |
| 137 | 137 | assert!(other.is_none() || self.opt == other.unwrap().opt); |
| 138 | 138 | match self.opt { |
| 139 | 139 | OptionsTargetModifiers::UnstableOptions(unstable) => match unstable { |
| ... | ... | @@ -142,7 +142,7 @@ impl TargetModifier { |
| 142 | 142 | } |
| 143 | 143 | UnstableOptionsTargetModifiers::sanitizer_cfi_normalize_integers => { |
| 144 | 144 | return target_modifier_consistency_check::sanitizer_cfi_normalize_integers( |
| 145 | opts, self, other, | |
| 145 | sess, self, other, | |
| 146 | 146 | ); |
| 147 | 147 | } |
| 148 | 148 | _ => {} |
| ... | ... | @@ -2575,6 +2575,7 @@ written to standard error output)"), |
| 2575 | 2575 | retpoline_external_thunk: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER], |
| 2576 | 2576 | "enables retpoline-external-thunk, retpoline-indirect-branches and retpoline-indirect-calls \ |
| 2577 | 2577 | target features (default: no)"), |
| 2578 | #[rustc_lint_opt_deny_field_access("use `Session::sanitizers()` instead of this field")] | |
| 2578 | 2579 | sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED TARGET_MODIFIER], |
| 2579 | 2580 | "use a sanitizer"), |
| 2580 | 2581 | sanitizer_cfi_canonical_jump_tables: Option<bool> = (Some(true), parse_opt_bool, [TRACKED], |
compiler/rustc_session/src/session.rs+7-3| ... | ... | @@ -323,7 +323,7 @@ impl Session { |
| 323 | 323 | } |
| 324 | 324 | |
| 325 | 325 | pub fn is_sanitizer_cfi_enabled(&self) -> bool { |
| 326 | self.opts.unstable_opts.sanitizer.contains(SanitizerSet::CFI) | |
| 326 | self.sanitizers().contains(SanitizerSet::CFI) | |
| 327 | 327 | } |
| 328 | 328 | |
| 329 | 329 | pub fn is_sanitizer_cfi_canonical_jump_tables_disabled(&self) -> bool { |
| ... | ... | @@ -347,7 +347,7 @@ impl Session { |
| 347 | 347 | } |
| 348 | 348 | |
| 349 | 349 | pub fn is_sanitizer_kcfi_enabled(&self) -> bool { |
| 350 | self.opts.unstable_opts.sanitizer.contains(SanitizerSet::KCFI) | |
| 350 | self.sanitizers().contains(SanitizerSet::KCFI) | |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | 353 | pub fn is_split_lto_unit_enabled(&self) -> bool { |
| ... | ... | @@ -527,7 +527,7 @@ impl Session { |
| 527 | 527 | // AddressSanitizer and KernelAddressSanitizer uses lifetimes to detect use after scope bugs. |
| 528 | 528 | // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables. |
| 529 | 529 | // HWAddressSanitizer will use lifetimes to detect use after scope bugs in the future. |
| 530 | || self.opts.unstable_opts.sanitizer.intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS) | |
| 530 | || self.sanitizers().intersects(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS | SanitizerSet::MEMORY | SanitizerSet::HWADDRESS) | |
| 531 | 531 | } |
| 532 | 532 | |
| 533 | 533 | pub fn diagnostic_width(&self) -> usize { |
| ... | ... | @@ -922,6 +922,10 @@ impl Session { |
| 922 | 922 | min |
| 923 | 923 | } |
| 924 | 924 | } |
| 925 | ||
| 926 | pub fn sanitizers(&self) -> SanitizerSet { | |
| 927 | return self.opts.unstable_opts.sanitizer | self.target.options.default_sanitizers; | |
| 928 | } | |
| 925 | 929 | } |
| 926 | 930 | |
| 927 | 931 | // JUSTIFICATION: part of session construction |
compiler/rustc_target/src/spec/json.rs+7| ... | ... | @@ -214,6 +214,11 @@ impl Target { |
| 214 | 214 | supported_sanitizers.into_iter().fold(SanitizerSet::empty(), |a, b| a | b); |
| 215 | 215 | } |
| 216 | 216 | |
| 217 | if let Some(default_sanitizers) = json.default_sanitizers { | |
| 218 | base.default_sanitizers = | |
| 219 | default_sanitizers.into_iter().fold(SanitizerSet::empty(), |a, b| a | b); | |
| 220 | } | |
| 221 | ||
| 217 | 222 | forward!(generate_arange_section); |
| 218 | 223 | forward!(supports_stack_protector); |
| 219 | 224 | forward!(small_data_threshold_support); |
| ... | ... | @@ -392,6 +397,7 @@ impl ToJson for Target { |
| 392 | 397 | target_option_val!(split_debuginfo); |
| 393 | 398 | target_option_val!(supported_split_debuginfo); |
| 394 | 399 | target_option_val!(supported_sanitizers); |
| 400 | target_option_val!(default_sanitizers); | |
| 395 | 401 | target_option_val!(c_enum_min_bits); |
| 396 | 402 | target_option_val!(generate_arange_section); |
| 397 | 403 | target_option_val!(supports_stack_protector); |
| ... | ... | @@ -612,6 +618,7 @@ struct TargetSpecJson { |
| 612 | 618 | split_debuginfo: Option<SplitDebuginfo>, |
| 613 | 619 | supported_split_debuginfo: Option<StaticCow<[SplitDebuginfo]>>, |
| 614 | 620 | supported_sanitizers: Option<Vec<SanitizerSet>>, |
| 621 | default_sanitizers: Option<Vec<SanitizerSet>>, | |
| 615 | 622 | generate_arange_section: Option<bool>, |
| 616 | 623 | supports_stack_protector: Option<bool>, |
| 617 | 624 | small_data_threshold_support: Option<SmallDataThresholdSupport>, |
compiler/rustc_target/src/spec/mod.rs+8| ... | ... | @@ -2410,6 +2410,13 @@ pub struct TargetOptions { |
| 2410 | 2410 | /// distributed with the target, the sanitizer should still appear in this list for the target. |
| 2411 | 2411 | pub supported_sanitizers: SanitizerSet, |
| 2412 | 2412 | |
| 2413 | /// The sanitizers that are enabled by default on this target. | |
| 2414 | /// | |
| 2415 | /// Note that the support here is at a codegen level. If the machine code with sanitizer | |
| 2416 | /// enabled can generated on this target, but the necessary supporting libraries are not | |
| 2417 | /// distributed with the target, the sanitizer should still appear in this list for the target. | |
| 2418 | pub default_sanitizers: SanitizerSet, | |
| 2419 | ||
| 2413 | 2420 | /// Minimum number of bits in #[repr(C)] enum. Defaults to the size of c_int |
| 2414 | 2421 | pub c_enum_min_bits: Option<u64>, |
| 2415 | 2422 | |
| ... | ... | @@ -2658,6 +2665,7 @@ impl Default for TargetOptions { |
| 2658 | 2665 | // `Off` is supported by default, but targets can remove this manually, e.g. Windows. |
| 2659 | 2666 | supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]), |
| 2660 | 2667 | supported_sanitizers: SanitizerSet::empty(), |
| 2668 | default_sanitizers: SanitizerSet::empty(), | |
| 2661 | 2669 | c_enum_min_bits: None, |
| 2662 | 2670 | generate_arange_section: true, |
| 2663 | 2671 | supports_stack_protector: true, |
compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs+1| ... | ... | @@ -12,6 +12,7 @@ pub(crate) fn target() -> Target { |
| 12 | 12 | | SanitizerSet::CFI |
| 13 | 13 | | SanitizerSet::LEAK |
| 14 | 14 | | SanitizerSet::SHADOWCALLSTACK; |
| 15 | base.default_sanitizers = SanitizerSet::SHADOWCALLSTACK; | |
| 15 | 16 | base.supports_xray = true; |
| 16 | 17 | |
| 17 | 18 | base.add_pre_link_args( |
compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs+1| ... | ... | @@ -9,6 +9,7 @@ pub(crate) fn target() -> Target { |
| 9 | 9 | base.max_atomic_width = Some(64); |
| 10 | 10 | base.stack_probes = StackProbeType::Inline; |
| 11 | 11 | base.supported_sanitizers = SanitizerSet::SHADOWCALLSTACK; |
| 12 | base.default_sanitizers = SanitizerSet::SHADOWCALLSTACK; | |
| 12 | 13 | base.supports_xray = true; |
| 13 | 14 | |
| 14 | 15 | Target { |
library/std_detect/src/detect/arch/aarch64.rs+7-2| ... | ... | @@ -5,13 +5,18 @@ features! { |
| 5 | 5 | @CFG: any(target_arch = "aarch64", target_arch = "arm64ec"); |
| 6 | 6 | @MACRO_NAME: is_aarch64_feature_detected; |
| 7 | 7 | @MACRO_ATTRS: |
| 8 | /// This macro tests, at runtime, whether an `aarch64` feature is enabled on aarch64 platforms. | |
| 9 | /// Currently most features are only supported on linux-based platforms. | |
| 8 | /// Check for the presence of a CPU feature at runtime. | |
| 9 | /// | |
| 10 | /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) | |
| 11 | /// the macro expands to `true`. | |
| 10 | 12 | /// |
| 11 | 13 | /// This macro takes one argument which is a string literal of the feature being tested for. |
| 12 | 14 | /// The feature names are mostly taken from their FEAT_* definitions in the [ARM Architecture |
| 13 | 15 | /// Reference Manual][docs]. |
| 14 | 16 | /// |
| 17 | /// Currently most features are only supported on linux-based platforms: on other platforms the | |
| 18 | /// runtime check will always return `false`. | |
| 19 | /// | |
| 15 | 20 | /// ## Supported arguments |
| 16 | 21 | /// |
| 17 | 22 | /// * `"aes"` - FEAT_AES & FEAT_PMULL |
library/std_detect/src/detect/arch/arm.rs+4-1| ... | ... | @@ -5,7 +5,10 @@ features! { |
| 5 | 5 | @CFG: target_arch = "arm"; |
| 6 | 6 | @MACRO_NAME: is_arm_feature_detected; |
| 7 | 7 | @MACRO_ATTRS: |
| 8 | /// Checks if `arm` feature is enabled. | |
| 8 | /// Check for the presence of a CPU feature at runtime. | |
| 9 | /// | |
| 10 | /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) | |
| 11 | /// the macro expands to `true`. | |
| 9 | 12 | #[unstable(feature = "stdarch_arm_feature_detection", issue = "111190")] |
| 10 | 13 | @NO_RUNTIME_DETECTION: "v7"; |
| 11 | 14 | @NO_RUNTIME_DETECTION: "vfp2"; |
library/std_detect/src/detect/arch/loongarch.rs+5-1| ... | ... | @@ -5,7 +5,11 @@ features! { |
| 5 | 5 | @CFG: any(target_arch = "loongarch32", target_arch = "loongarch64"); |
| 6 | 6 | @MACRO_NAME: is_loongarch_feature_detected; |
| 7 | 7 | @MACRO_ATTRS: |
| 8 | /// Checks if `loongarch` feature is enabled. | |
| 8 | /// Check for the presence of a CPU feature at runtime. | |
| 9 | /// | |
| 10 | /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) | |
| 11 | /// the macro expands to `true`. | |
| 12 | /// | |
| 9 | 13 | /// Supported arguments are: |
| 10 | 14 | /// |
| 11 | 15 | /// * `"32s"` |
library/std_detect/src/detect/arch/mips.rs+4-1| ... | ... | @@ -5,7 +5,10 @@ features! { |
| 5 | 5 | @CFG: target_arch = "mips"; |
| 6 | 6 | @MACRO_NAME: is_mips_feature_detected; |
| 7 | 7 | @MACRO_ATTRS: |
| 8 | /// Checks if `mips` feature is enabled. | |
| 8 | /// Check for the presence of a CPU feature at runtime. | |
| 9 | /// | |
| 10 | /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) | |
| 11 | /// the macro expands to `true`. | |
| 9 | 12 | #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] |
| 10 | 13 | @FEATURE: #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] msa: "msa"; |
| 11 | 14 | /// MIPS SIMD Architecture (MSA) |
library/std_detect/src/detect/arch/mips64.rs+4-1| ... | ... | @@ -5,7 +5,10 @@ features! { |
| 5 | 5 | @CFG: target_arch = "mips64"; |
| 6 | 6 | @MACRO_NAME: is_mips64_feature_detected; |
| 7 | 7 | @MACRO_ATTRS: |
| 8 | /// Checks if `mips64` feature is enabled. | |
| 8 | /// Check for the presence of a CPU feature at runtime. | |
| 9 | /// | |
| 10 | /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) | |
| 11 | /// the macro expands to `true`. | |
| 9 | 12 | #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] |
| 10 | 13 | @FEATURE: #[unstable(feature = "stdarch_mips_feature_detection", issue = "111188")] msa: "msa"; |
| 11 | 14 | /// MIPS SIMD Architecture (MSA) |
library/std_detect/src/detect/arch/powerpc.rs+4-1| ... | ... | @@ -5,7 +5,10 @@ features! { |
| 5 | 5 | @CFG: target_arch = "powerpc"; |
| 6 | 6 | @MACRO_NAME: is_powerpc_feature_detected; |
| 7 | 7 | @MACRO_ATTRS: |
| 8 | /// Checks if `powerpc` feature is enabled. | |
| 8 | /// Check for the presence of a CPU feature at runtime. | |
| 9 | /// | |
| 10 | /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) | |
| 11 | /// the macro expands to `true`. | |
| 9 | 12 | #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] |
| 10 | 13 | @FEATURE: #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] altivec: "altivec"; |
| 11 | 14 | /// Altivec |
library/std_detect/src/detect/arch/powerpc64.rs+4-1| ... | ... | @@ -5,7 +5,10 @@ features! { |
| 5 | 5 | @CFG: target_arch = "powerpc64"; |
| 6 | 6 | @MACRO_NAME: is_powerpc64_feature_detected; |
| 7 | 7 | @MACRO_ATTRS: |
| 8 | /// Checks if `powerpc` feature is enabled. | |
| 8 | /// Check for the presence of a CPU feature at runtime. | |
| 9 | /// | |
| 10 | /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) | |
| 11 | /// the macro expands to `true`. | |
| 9 | 12 | #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] |
| 10 | 13 | @FEATURE: #[unstable(feature = "stdarch_powerpc_feature_detection", issue = "111191")] altivec: "altivec"; |
| 11 | 14 | /// Altivec |
library/std_detect/src/detect/arch/riscv.rs+4-2| ... | ... | @@ -5,8 +5,10 @@ features! { |
| 5 | 5 | @CFG: any(target_arch = "riscv32", target_arch = "riscv64"); |
| 6 | 6 | @MACRO_NAME: is_riscv_feature_detected; |
| 7 | 7 | @MACRO_ATTRS: |
| 8 | /// A macro to test at *runtime* whether instruction sets are available on | |
| 9 | /// RISC-V platforms. | |
| 8 | /// Check for the presence of a CPU feature at runtime. | |
| 9 | /// | |
| 10 | /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) | |
| 11 | /// the macro expands to `true`. | |
| 10 | 12 | /// |
| 11 | 13 | /// RISC-V standard defined the base sets and the extension sets. |
| 12 | 14 | /// The base sets are RV32I, RV64I, RV32E or RV128I. Any RISC-V platform |
library/std_detect/src/detect/arch/s390x.rs+4-1| ... | ... | @@ -5,7 +5,10 @@ features! { |
| 5 | 5 | @CFG: target_arch = "s390x"; |
| 6 | 6 | @MACRO_NAME: is_s390x_feature_detected; |
| 7 | 7 | @MACRO_ATTRS: |
| 8 | /// Checks if `s390x` feature is enabled. | |
| 8 | /// Check for the presence of a CPU feature at runtime. | |
| 9 | /// | |
| 10 | /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) | |
| 11 | /// the macro expands to `true`. | |
| 9 | 12 | #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] |
| 10 | 13 | @FEATURE: #[unstable(feature = "stdarch_s390x_feature_detection", issue = "135413")] concurrent_functions: "concurrent-functions"; |
| 11 | 14 | /// s390x concurrent-functions facility |
library/std_detect/src/detect/arch/x86.rs+5-6| ... | ... | @@ -20,13 +20,12 @@ features! { |
| 20 | 20 | @CFG: any(target_arch = "x86", target_arch = "x86_64"); |
| 21 | 21 | @MACRO_NAME: is_x86_feature_detected; |
| 22 | 22 | @MACRO_ATTRS: |
| 23 | /// A macro to test at *runtime* whether a CPU feature is available on | |
| 24 | /// x86/x86-64 platforms. | |
| 23 | /// Check for the presence of a CPU feature at runtime. | |
| 25 | 24 | /// |
| 26 | /// This macro is provided in the standard library and will detect at runtime | |
| 27 | /// whether the specified CPU feature is detected. This does **not** resolve at | |
| 28 | /// compile time unless the specified feature is already enabled for the entire | |
| 29 | /// crate. Runtime detection currently relies mostly on the `cpuid` instruction. | |
| 25 | /// When the feature is known to be enabled at compile time (e.g. via `-Ctarget-feature`) | |
| 26 | /// the macro expands to `true`. | |
| 27 | /// | |
| 28 | /// Runtime detection currently relies mostly on the `cpuid` instruction. | |
| 30 | 29 | /// |
| 31 | 30 | /// This macro only takes one argument which is a string literal of the feature |
| 32 | 31 | /// being tested for. The feature names supported are the lowercase versions of |
src/doc/rustc/src/platform-support/csky-unknown-linux-gnuabiv2.md+1-1| ... | ... | @@ -65,7 +65,7 @@ To test cross-compiled binaries on a `x86_64` system, you can use the `qemu-csky |
| 65 | 65 | |
| 66 | 66 | To use: |
| 67 | 67 | |
| 68 | * 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.) | |
| 68 | * 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.) | |
| 69 | 69 | * Link your built toolchain via: |
| 70 | 70 | * `rustup toolchain link stage2 ${RUST}/build/x86_64-unknown-linux-gnu/stage2` |
| 71 | 71 | * Create a test program |
src/etc/gdb_providers.py+19-4| ... | ... | @@ -128,6 +128,9 @@ class StdSliceProvider(printer_base): |
| 128 | 128 | self._data_ptr + index for index in xrange(self._length) |
| 129 | 129 | ) |
| 130 | 130 | |
| 131 | def num_children(self): | |
| 132 | return self._length | |
| 133 | ||
| 131 | 134 | @staticmethod |
| 132 | 135 | def display_hint(): |
| 133 | 136 | return "array" |
| ... | ... | @@ -149,6 +152,9 @@ class StdVecProvider(printer_base): |
| 149 | 152 | self._data_ptr + index for index in xrange(self._length) |
| 150 | 153 | ) |
| 151 | 154 | |
| 155 | def num_children(self): | |
| 156 | return self._length | |
| 157 | ||
| 152 | 158 | @staticmethod |
| 153 | 159 | def display_hint(): |
| 154 | 160 | return "array" |
| ... | ... | @@ -177,6 +183,9 @@ class StdVecDequeProvider(printer_base): |
| 177 | 183 | for index in xrange(self._size) |
| 178 | 184 | ) |
| 179 | 185 | |
| 186 | def num_children(self): | |
| 187 | return self._size | |
| 188 | ||
| 180 | 189 | @staticmethod |
| 181 | 190 | def display_hint(): |
| 182 | 191 | return "array" |
| ... | ... | @@ -252,15 +261,15 @@ class StdNonZeroNumberProvider(printer_base): |
| 252 | 261 | def __init__(self, valobj): |
| 253 | 262 | fields = valobj.type.fields() |
| 254 | 263 | assert len(fields) == 1 |
| 255 | field = list(fields)[0] | |
| 264 | field = fields[0] | |
| 256 | 265 | |
| 257 | inner_valobj = valobj[field.name] | |
| 266 | inner_valobj = valobj[field] | |
| 258 | 267 | |
| 259 | 268 | inner_fields = inner_valobj.type.fields() |
| 260 | 269 | assert len(inner_fields) == 1 |
| 261 | inner_field = list(inner_fields)[0] | |
| 270 | inner_field = inner_fields[0] | |
| 262 | 271 | |
| 263 | self._value = str(inner_valobj[inner_field.name]) | |
| 272 | self._value = inner_valobj[inner_field] | |
| 264 | 273 | |
| 265 | 274 | def to_string(self): |
| 266 | 275 | return self._value |
| ... | ... | @@ -478,5 +487,11 @@ class StdHashMapProvider(printer_base): |
| 478 | 487 | else: |
| 479 | 488 | yield "[{}]".format(index), element[ZERO_FIELD] |
| 480 | 489 | |
| 490 | def num_children(self): | |
| 491 | result = self._size | |
| 492 | if self._show_values: | |
| 493 | result *= 2 | |
| 494 | return result | |
| 495 | ||
| 481 | 496 | def display_hint(self): |
| 482 | 497 | return "map" if self._show_values else "array" |
src/librustdoc/doctest.rs+14-2| ... | ... | @@ -671,7 +671,13 @@ fn run_test( |
| 671 | 671 | |
| 672 | 672 | debug!("compiler invocation for doctest: {compiler:?}"); |
| 673 | 673 | |
| 674 | let mut child = compiler.spawn().expect("Failed to spawn rustc process"); | |
| 674 | let mut child = match compiler.spawn() { | |
| 675 | Ok(child) => child, | |
| 676 | Err(error) => { | |
| 677 | eprintln!("Failed to spawn {:?}: {error:?}", compiler.get_program()); | |
| 678 | return (Duration::default(), Err(TestFailure::CompileError)); | |
| 679 | } | |
| 680 | }; | |
| 675 | 681 | let output = if let Some(merged_test_code) = &doctest.merged_test_code { |
| 676 | 682 | // compile-fail tests never get merged, so this should always pass |
| 677 | 683 | let status = child.wait().expect("Failed to wait"); |
| ... | ... | @@ -733,7 +739,13 @@ fn run_test( |
| 733 | 739 | let status = if !status.success() { |
| 734 | 740 | status |
| 735 | 741 | } else { |
| 736 | let mut child_runner = runner_compiler.spawn().expect("Failed to spawn rustc process"); | |
| 742 | let mut child_runner = match runner_compiler.spawn() { | |
| 743 | Ok(child) => child, | |
| 744 | Err(error) => { | |
| 745 | eprintln!("Failed to spawn {:?}: {error:?}", runner_compiler.get_program()); | |
| 746 | return (Duration::default(), Err(TestFailure::CompileError)); | |
| 747 | } | |
| 748 | }; | |
| 737 | 749 | child_runner.wait().expect("Failed to wait") |
| 738 | 750 | }; |
| 739 | 751 |
src/tools/run-make-support/src/command.rs+7| ... | ... | @@ -387,6 +387,13 @@ impl CompletedProcess { |
| 387 | 387 | self |
| 388 | 388 | } |
| 389 | 389 | |
| 390 | /// Checks that `stderr` doesn't contain the Internal Compiler Error message. | |
| 391 | #[track_caller] | |
| 392 | pub fn assert_not_ice(&self) -> &Self { | |
| 393 | self.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug"); | |
| 394 | self | |
| 395 | } | |
| 396 | ||
| 390 | 397 | /// Checks that `stderr` does not contain the regex pattern `unexpected`. |
| 391 | 398 | #[track_caller] |
| 392 | 399 | pub fn assert_stderr_not_contains_regex<S: AsRef<str>>(&self, unexpected: S) -> &Self { |
tests/debuginfo/numeric-types.rs+2| ... | ... | @@ -202,6 +202,8 @@ |
| 202 | 202 | // gdb-command:print nz_usize |
| 203 | 203 | // gdb-check:[...]$12 = 122 |
| 204 | 204 | |
| 205 | // gdb-command:print/x nz_i8 | |
| 206 | // gdb-check:[...]$13 = 0xb | |
| 205 | 207 | |
| 206 | 208 | |
| 207 | 209 | // === LLDB TESTS ================================================================================== |
tests/run-make/diagnostics-traits-from-duplicate-crates/rmake.rs+1-1| ... | ... | @@ -43,5 +43,5 @@ fn main() { |
| 43 | 43 | .extern_("minibevy", "libminibevy-b.rmeta") |
| 44 | 44 | .extern_("minirapier", "libminirapier.rmeta") |
| 45 | 45 | .run_fail() |
| 46 | .assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug"); | |
| 46 | .assert_not_ice(); | |
| 47 | 47 | } |
tests/run-make/rustdoc-merge-no-input-finalize/rmake.rs+1-1| ... | ... | @@ -24,5 +24,5 @@ fn main() { |
| 24 | 24 | .arg(format!("--include-parts-dir={}", parts_out_dir.display())) |
| 25 | 25 | .arg("--merge=finalize") |
| 26 | 26 | .run(); |
| 27 | output.assert_stderr_not_contains("error: the compiler unexpectedly panicked. this is a bug."); | |
| 27 | output.assert_not_ice(); | |
| 28 | 28 | } |
tests/run-make/rustdoc-test-builder/foo.rs created+3| ... | ... | @@ -0,0 +1,3 @@ |
| 1 | //! ``` | |
| 2 | //! let x = 12; | |
| 3 | //! ``` |
tests/run-make/rustdoc-test-builder/rmake.rs created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | // This test ensures that if the rustdoc test binary is not executable, it will | |
| 2 | // gracefully fail and not panic. | |
| 3 | ||
| 4 | //@ needs-target-std | |
| 5 | ||
| 6 | use run_make_support::{path, rfs, rustdoc}; | |
| 7 | ||
| 8 | fn main() { | |
| 9 | let absolute_path = path("foo.rs").canonicalize().expect("failed to get absolute path"); | |
| 10 | let output = rustdoc() | |
| 11 | .input("foo.rs") | |
| 12 | .arg("--test") | |
| 13 | .arg("-Zunstable-options") | |
| 14 | .arg("--test-builder") | |
| 15 | .arg(&absolute_path) | |
| 16 | .run_fail(); | |
| 17 | ||
| 18 | // We check that rustdoc outputs the error correctly... | |
| 19 | output.assert_stdout_contains("Failed to spawn "); | |
| 20 | // ... and that we didn't panic. | |
| 21 | output.assert_not_ice(); | |
| 22 | } |
tests/ui/asm/hexagon-register-pairs.rs created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | //@ add-minicore | |
| 2 | //@ compile-flags: --target hexagon-unknown-linux-musl -C target-feature=+hvx-length128b | |
| 3 | //@ needs-llvm-components: hexagon | |
| 4 | //@ ignore-backends: gcc | |
| 5 | ||
| 6 | #![feature(no_core, asm_experimental_arch)] | |
| 7 | #![crate_type = "lib"] | |
| 8 | #![no_core] | |
| 9 | ||
| 10 | //~? WARN unstable feature specified for `-Ctarget-feature`: `hvx-length128b` | |
| 11 | ||
| 12 | extern crate minicore; | |
| 13 | use minicore::*; | |
| 14 | ||
| 15 | fn test_register_spans() { | |
| 16 | unsafe { | |
| 17 | // These are valid Hexagon register span notations, not labels | |
| 18 | // Should NOT trigger the named labels lint | |
| 19 | ||
| 20 | // General register pairs | |
| 21 | asm!("r1:0 = memd(r29+#0)", lateout("r0") _, lateout("r1") _); | |
| 22 | asm!("r3:2 = combine(#1, #0)", lateout("r2") _, lateout("r3") _); | |
| 23 | asm!("r15:14 = memd(r30+#8)", lateout("r14") _, lateout("r15") _); | |
| 24 | asm!("memd(r29+#0) = r5:4", in("r4") 0u32, in("r5") 0u32); | |
| 25 | ||
| 26 | // These patterns look like register spans but test different edge cases | |
| 27 | // All should NOT trigger the lint as they match valid hexagon register syntax patterns | |
| 28 | asm!("V5:4 = vaddw(v1:0, v1:0)", options(nostack)); // Uppercase V register pair | |
| 29 | asm!("v1:0.w = vsub(v1:0.w,v1:0.w):sat", options(nostack)); // Lowercase v with suffix | |
| 30 | ||
| 31 | // Mixed with actual labels should still trigger for the labels | |
| 32 | asm!("label1: r7:6 = combine(#2, #3)"); //~ ERROR avoid using named labels | |
| 33 | ||
| 34 | // Regular labels should still trigger | |
| 35 | asm!("hexagon_label: nop"); //~ ERROR avoid using named labels | |
| 36 | } | |
| 37 | } |
tests/ui/asm/hexagon-register-pairs.stderr created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | warning: unstable feature specified for `-Ctarget-feature`: `hvx-length128b` | |
| 2 | | | |
| 3 | = note: this feature is not stably supported; its behavior can change in the future | |
| 4 | ||
| 5 | error: avoid using named labels in inline assembly | |
| 6 | --> $DIR/hexagon-register-pairs.rs:32:15 | |
| 7 | | | |
| 8 | LL | asm!("label1: r7:6 = combine(#2, #3)"); | |
| 9 | | ^^^^^^ | |
| 10 | | | |
| 11 | = help: only local labels of the form `<number>:` should be used in inline asm | |
| 12 | = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information | |
| 13 | = note: `#[deny(named_asm_labels)]` on by default | |
| 14 | ||
| 15 | error: avoid using named labels in inline assembly | |
| 16 | --> $DIR/hexagon-register-pairs.rs:35:15 | |
| 17 | | | |
| 18 | LL | asm!("hexagon_label: nop"); | |
| 19 | | ^^^^^^^^^^^^^ | |
| 20 | | | |
| 21 | = help: only local labels of the form `<number>:` should be used in inline asm | |
| 22 | = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information | |
| 23 | ||
| 24 | error: aborting due to 2 previous errors; 1 warning emitted | |
| 25 |