Skip to content

Commit 18a091e

Browse files
committed
Make named asm_labels lint not trigger on hexagon register spans
Fixes #143021
1 parent d14d202 commit 18a091e

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
@@ -2867,6 +2867,77 @@ enum AsmLabelKind {
28672867
Binary,
28682868
}
28692869

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

3014+
// Check for Hexagon register span notation (e.g., "r1:0", "V5:4", "V3:2.w")
3015+
// This is valid Hexagon assembly syntax, not a label
3016+
if matches!(cx.tcx.sess.asm_arch, Some(InlineAsmArch::Hexagon))
3017+
&& is_hexagon_register_span(possible_label)
3018+
{
3019+
break 'label_loop;
3020+
}
3021+
29433022
for c in chars {
29443023
// Inside a template format arg, any character is permitted for the
29453024
// 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)