]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | use std::fmt; |
2 | ||
cdc7bbd5 | 3 | use clippy_utils::diagnostics::span_lint_and_help; |
f20569fa | 4 | use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions}; |
c620b35d FG |
5 | use rustc_ast::{InlineAsm, Item, ItemKind}; |
6 | use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext}; | |
4b012472 | 7 | use rustc_session::declare_lint_pass; |
c620b35d FG |
8 | use rustc_span::Span; |
9 | use rustc_target::asm::InlineAsmArch; | |
f20569fa XL |
10 | |
11 | #[derive(Clone, Copy, PartialEq, Eq)] | |
12 | enum AsmStyle { | |
13 | Intel, | |
14 | Att, | |
15 | } | |
16 | ||
17 | impl fmt::Display for AsmStyle { | |
18 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
19 | match self { | |
20 | AsmStyle::Intel => f.write_str("Intel"), | |
21 | AsmStyle::Att => f.write_str("AT&T"), | |
22 | } | |
23 | } | |
24 | } | |
25 | ||
26 | impl std::ops::Not for AsmStyle { | |
27 | type Output = AsmStyle; | |
28 | ||
29 | fn not(self) -> AsmStyle { | |
30 | match self { | |
31 | AsmStyle::Intel => AsmStyle::Att, | |
32 | AsmStyle::Att => AsmStyle::Intel, | |
33 | } | |
34 | } | |
35 | } | |
36 | ||
c620b35d FG |
37 | fn check_asm_syntax( |
38 | lint: &'static Lint, | |
39 | cx: &EarlyContext<'_>, | |
40 | inline_asm: &InlineAsm, | |
41 | span: Span, | |
42 | check_for: AsmStyle, | |
43 | ) { | |
44 | if matches!(cx.sess().asm_arch, Some(InlineAsmArch::X86 | InlineAsmArch::X86_64)) { | |
f20569fa XL |
45 | let style = if inline_asm.options.contains(InlineAsmOptions::ATT_SYNTAX) { |
46 | AsmStyle::Att | |
47 | } else { | |
48 | AsmStyle::Intel | |
49 | }; | |
50 | ||
51 | if style == check_for { | |
52 | span_lint_and_help( | |
53 | cx, | |
54 | lint, | |
c620b35d | 55 | span, |
e8be2606 | 56 | format!("{style} x86 assembly syntax used"), |
f20569fa | 57 | None, |
e8be2606 | 58 | format!("use {} x86 assembly syntax", !style), |
f20569fa XL |
59 | ); |
60 | } | |
61 | } | |
62 | } | |
63 | ||
64 | declare_clippy_lint! { | |
94222f64 XL |
65 | /// ### What it does |
66 | /// Checks for usage of Intel x86 assembly syntax. | |
f20569fa | 67 | /// |
31ef2f64 FG |
68 | /// ### Why restrict this? |
69 | /// To enforce consistent use of AT&T x86 assembly syntax. | |
f20569fa | 70 | /// |
94222f64 | 71 | /// ### Example |
f20569fa XL |
72 | /// |
73 | /// ```rust,no_run | |
74 | /// # #![feature(asm)] | |
2b03887a | 75 | /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] |
f20569fa | 76 | /// # unsafe { let ptr = "".as_ptr(); |
a2a8927a | 77 | /// # use std::arch::asm; |
f20569fa XL |
78 | /// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr); |
79 | /// # } | |
80 | /// ``` | |
81 | /// Use instead: | |
82 | /// ```rust,no_run | |
83 | /// # #![feature(asm)] | |
2b03887a | 84 | /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] |
f20569fa | 85 | /// # unsafe { let ptr = "".as_ptr(); |
a2a8927a | 86 | /// # use std::arch::asm; |
f20569fa XL |
87 | /// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax)); |
88 | /// # } | |
89 | /// ``` | |
a2a8927a | 90 | #[clippy::version = "1.49.0"] |
f20569fa XL |
91 | pub INLINE_ASM_X86_INTEL_SYNTAX, |
92 | restriction, | |
93 | "prefer AT&T x86 assembly syntax" | |
94 | } | |
95 | ||
96 | declare_lint_pass!(InlineAsmX86IntelSyntax => [INLINE_ASM_X86_INTEL_SYNTAX]); | |
97 | ||
98 | impl EarlyLintPass for InlineAsmX86IntelSyntax { | |
99 | fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { | |
c620b35d FG |
100 | if let ExprKind::InlineAsm(inline_asm) = &expr.kind { |
101 | check_asm_syntax(Self::get_lints()[0], cx, inline_asm, expr.span, AsmStyle::Intel); | |
102 | } | |
103 | } | |
104 | ||
105 | fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { | |
106 | if let ItemKind::GlobalAsm(inline_asm) = &item.kind { | |
107 | check_asm_syntax(Self::get_lints()[0], cx, inline_asm, item.span, AsmStyle::Intel); | |
108 | } | |
f20569fa XL |
109 | } |
110 | } | |
111 | ||
112 | declare_clippy_lint! { | |
94222f64 XL |
113 | /// ### What it does |
114 | /// Checks for usage of AT&T x86 assembly syntax. | |
f20569fa | 115 | /// |
31ef2f64 FG |
116 | /// ### Why restrict this? |
117 | /// To enforce consistent use of Intel x86 assembly syntax. | |
f20569fa | 118 | /// |
94222f64 | 119 | /// ### Example |
f20569fa XL |
120 | /// |
121 | /// ```rust,no_run | |
122 | /// # #![feature(asm)] | |
2b03887a | 123 | /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] |
f20569fa | 124 | /// # unsafe { let ptr = "".as_ptr(); |
a2a8927a | 125 | /// # use std::arch::asm; |
f20569fa XL |
126 | /// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax)); |
127 | /// # } | |
128 | /// ``` | |
129 | /// Use instead: | |
130 | /// ```rust,no_run | |
131 | /// # #![feature(asm)] | |
2b03887a | 132 | /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] |
f20569fa | 133 | /// # unsafe { let ptr = "".as_ptr(); |
a2a8927a | 134 | /// # use std::arch::asm; |
f20569fa XL |
135 | /// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr); |
136 | /// # } | |
137 | /// ``` | |
a2a8927a | 138 | #[clippy::version = "1.49.0"] |
f20569fa XL |
139 | pub INLINE_ASM_X86_ATT_SYNTAX, |
140 | restriction, | |
141 | "prefer Intel x86 assembly syntax" | |
142 | } | |
143 | ||
144 | declare_lint_pass!(InlineAsmX86AttSyntax => [INLINE_ASM_X86_ATT_SYNTAX]); | |
145 | ||
146 | impl EarlyLintPass for InlineAsmX86AttSyntax { | |
147 | fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { | |
c620b35d FG |
148 | if let ExprKind::InlineAsm(inline_asm) = &expr.kind { |
149 | check_asm_syntax(Self::get_lints()[0], cx, inline_asm, expr.span, AsmStyle::Att); | |
150 | } | |
151 | } | |
152 | ||
153 | fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { | |
154 | if let ItemKind::GlobalAsm(inline_asm) = &item.kind { | |
155 | check_asm_syntax(Self::get_lints()[0], cx, inline_asm, item.span, AsmStyle::Att); | |
156 | } | |
f20569fa XL |
157 | } |
158 | } |