Skip to content

Commit f09cc54

Browse files
committed
Make named asm_labels lint not trigger on hexagon register spans
Fixes #143021
1 parent 5c7ae0c commit f09cc54

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

compiler/rustc_lint/src/builtin.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2874,6 +2874,77 @@ enum AsmLabelKind {
28742874
Binary,
28752875
}
28762876

2877+
/// Checks if a potential label is actually a Hexagon register span notation.
2878+
///
2879+
/// Hexagon assembly uses register span notation like `r1:0`, `V5:4.w`, `p1:0` etc.
2880+
/// These follow the pattern: `[letter][digit(s)]:[digit(s)][optional_suffix]`
2881+
///
2882+
/// Returns `true` if the string matches a valid Hexagon register span pattern.
2883+
fn is_hexagon_register_span(possible_label: &str) -> bool {
2884+
if possible_label.len() < 3 {
2885+
return false;
2886+
}
2887+
2888+
let mut chars = possible_label.chars();
2889+
let start = chars.next().unwrap();
2890+
2891+
// Must start with a letter (r, V, p, etc.)
2892+
if !start.is_ascii_alphabetic() {
2893+
return false;
2894+
}
2895+
2896+
let rest = &possible_label[1..];
2897+
let Some(colon_idx) = rest.find(':') else {
2898+
return false;
2899+
};
2900+
2901+
let (before_colon, after_colon_with_colon) = rest.split_at(colon_idx);
2902+
let after_colon = &after_colon_with_colon[1..]; // Skip the ':'
2903+
2904+
// Check if before colon is all digits and non-empty
2905+
if before_colon.is_empty() || !before_colon.chars().all(|c| c.is_ascii_digit()) {
2906+
return false;
2907+
}
2908+
2909+
// Check if after colon starts with digits (may have suffix like .w, .h)
2910+
let digits_after = after_colon.chars().take_while(|c| c.is_ascii_digit()).collect::<String>();
2911+
2912+
!digits_after.is_empty()
2913+
}
2914+
2915+
#[cfg(test)]
2916+
mod tests {
2917+
use super::is_hexagon_register_span;
2918+
2919+
#[test]
2920+
fn test_hexagon_register_span_patterns() {
2921+
// Valid Hexagon register span patterns
2922+
assert!(is_hexagon_register_span("r1:0"));
2923+
assert!(is_hexagon_register_span("r15:14"));
2924+
assert!(is_hexagon_register_span("V5:4"));
2925+
assert!(is_hexagon_register_span("V3:2"));
2926+
assert!(is_hexagon_register_span("V5:4.w"));
2927+
assert!(is_hexagon_register_span("V3:2.h"));
2928+
assert!(is_hexagon_register_span("p1:0"));
2929+
assert!(is_hexagon_register_span("p3:2"));
2930+
assert!(is_hexagon_register_span("r99:98"));
2931+
assert!(is_hexagon_register_span("V123:122.whatever"));
2932+
2933+
// Invalid patterns - these should be treated as potential labels
2934+
assert!(!is_hexagon_register_span("label1"));
2935+
assert!(!is_hexagon_register_span("foo:"));
2936+
assert!(!is_hexagon_register_span(":0"));
2937+
assert!(!is_hexagon_register_span("r:0")); // missing digits before colon
2938+
assert!(!is_hexagon_register_span("r1:")); // missing digits after colon
2939+
assert!(!is_hexagon_register_span("r1:a")); // non-digit after colon
2940+
assert!(!is_hexagon_register_span("1:0")); // starts with digit, not letter
2941+
assert!(!is_hexagon_register_span("r1")); // no colon
2942+
assert!(!is_hexagon_register_span("r")); // too short
2943+
assert!(!is_hexagon_register_span("")); // empty
2944+
assert!(!is_hexagon_register_span("ra:0")); // letter in first digit group
2945+
}
2946+
}
2947+
28772948
impl<'tcx> LateLintPass<'tcx> for AsmLabels {
28782949
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
28792950
if let hir::Expr {
@@ -2956,6 +3027,14 @@ impl<'tcx> LateLintPass<'tcx> for AsmLabels {
29563027
break 'label_loop;
29573028
}
29583029

3030+
// Check for Hexagon register span notation (e.g., "r1:0", "V5:4", "V3:2.w")
3031+
// This is valid Hexagon assembly syntax, not a label
3032+
if matches!(cx.tcx.sess.asm_arch, Some(InlineAsmArch::Hexagon))
3033+
&& is_hexagon_register_span(possible_label)
3034+
{
3035+
break 'label_loop;
3036+
}
3037+
29593038
for c in chars {
29603039
// Inside a template format arg, any character is permitted for the
29613040
// puproses of label detection because we assume that it can be
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//@ add-core-stubs
2+
//@ compile-flags: --target hexagon-unknown-linux-musl
3+
//@ needs-llvm-components: hexagon
4+
5+
#![feature(no_core, asm_experimental_arch)]
6+
#![crate_type = "lib"]
7+
#![no_core]
8+
9+
extern crate minicore;
10+
use minicore::*;
11+
12+
fn test_register_spans() {
13+
unsafe {
14+
// These are valid Hexagon register span notations, not labels
15+
// Should NOT trigger the named labels lint
16+
17+
// General register pairs
18+
asm!("r1:0 = memd(r29+#0)", lateout("r0") _, lateout("r1") _);
19+
asm!("r3:2 = combine(#1, #0)", lateout("r2") _, lateout("r3") _);
20+
asm!("r15:14 = memd(r30+#8)", lateout("r14") _, lateout("r15") _);
21+
asm!("memd(r29+#0) = r5:4", in("r4") 0u32, in("r5") 0u32);
22+
23+
// Vector register pairs (hypothetical since we can't actually use them without HVX)
24+
asm!("nop // V5:4 = vadd(V3:2, V1:0)"); // Comment form to avoid actual instruction issues
25+
asm!("nop // V7:6.w = vadd(V5:4.w, V3:2.w)"); // With type suffixes
26+
27+
// Predicate register pairs
28+
asm!("nop // p1:0 = vcmpb.eq(V1:0, V3:2)"); // Comment form
29+
30+
// Mixed with actual labels should still trigger for the labels
31+
asm!("label1: r7:6 = combine(#2, #3)"); //~ ERROR avoid using named labels
32+
33+
// Regular labels should still trigger
34+
asm!("hexagon_label: nop"); //~ ERROR avoid using named labels
35+
}
36+
}

0 commit comments

Comments
 (0)