1 use std::fmt;
2
3 use clippy_utils::diagnostics::span_lint_and_help;
4 use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions};
5 use rustc_lint::{EarlyContext, EarlyLintPass, Lint};
6 use rustc_session::{declare_lint_pass, declare_tool_lint};
7
8 #[derive(Clone, Copy, PartialEq, Eq)]
9 enum AsmStyle {
10 Intel,
11 Att,
12 }
13
14 impl fmt::Display for AsmStyle {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result15 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
16 match self {
17 AsmStyle::Intel => f.write_str("Intel"),
18 AsmStyle::Att => f.write_str("AT&T"),
19 }
20 }
21 }
22
23 impl std::ops::Not for AsmStyle {
24 type Output = AsmStyle;
25
not(self) -> AsmStyle26 fn not(self) -> AsmStyle {
27 match self {
28 AsmStyle::Intel => AsmStyle::Att,
29 AsmStyle::Att => AsmStyle::Intel,
30 }
31 }
32 }
33
check_expr_asm_syntax(lint: &'static Lint, cx: &EarlyContext<'_>, expr: &Expr, check_for: AsmStyle)34 fn check_expr_asm_syntax(lint: &'static Lint, cx: &EarlyContext<'_>, expr: &Expr, check_for: AsmStyle) {
35 if let ExprKind::InlineAsm(ref inline_asm) = expr.kind {
36 let style = if inline_asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
37 AsmStyle::Att
38 } else {
39 AsmStyle::Intel
40 };
41
42 if style == check_for {
43 span_lint_and_help(
44 cx,
45 lint,
46 expr.span,
47 &format!("{style} x86 assembly syntax used"),
48 None,
49 &format!("use {} x86 assembly syntax", !style),
50 );
51 }
52 }
53 }
54
55 declare_clippy_lint! {
56 /// ### What it does
57 /// Checks for usage of Intel x86 assembly syntax.
58 ///
59 /// ### Why is this bad?
60 /// The lint has been enabled to indicate a preference
61 /// for AT&T x86 assembly syntax.
62 ///
63 /// ### Example
64 ///
65 /// ```rust,no_run
66 /// # #![feature(asm)]
67 /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
68 /// # unsafe { let ptr = "".as_ptr();
69 /// # use std::arch::asm;
70 /// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);
71 /// # }
72 /// ```
73 /// Use instead:
74 /// ```rust,no_run
75 /// # #![feature(asm)]
76 /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
77 /// # unsafe { let ptr = "".as_ptr();
78 /// # use std::arch::asm;
79 /// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
80 /// # }
81 /// ```
82 #[clippy::version = "1.49.0"]
83 pub INLINE_ASM_X86_INTEL_SYNTAX,
84 restriction,
85 "prefer AT&T x86 assembly syntax"
86 }
87
88 declare_lint_pass!(InlineAsmX86IntelSyntax => [INLINE_ASM_X86_INTEL_SYNTAX]);
89
90 impl EarlyLintPass for InlineAsmX86IntelSyntax {
check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr)91 fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
92 check_expr_asm_syntax(Self::get_lints()[0], cx, expr, AsmStyle::Intel);
93 }
94 }
95
96 declare_clippy_lint! {
97 /// ### What it does
98 /// Checks for usage of AT&T x86 assembly syntax.
99 ///
100 /// ### Why is this bad?
101 /// The lint has been enabled to indicate a preference
102 /// for Intel x86 assembly syntax.
103 ///
104 /// ### Example
105 ///
106 /// ```rust,no_run
107 /// # #![feature(asm)]
108 /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
109 /// # unsafe { let ptr = "".as_ptr();
110 /// # use std::arch::asm;
111 /// asm!("lea ({}), {}", in(reg) ptr, lateout(reg) _, options(att_syntax));
112 /// # }
113 /// ```
114 /// Use instead:
115 /// ```rust,no_run
116 /// # #![feature(asm)]
117 /// # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
118 /// # unsafe { let ptr = "".as_ptr();
119 /// # use std::arch::asm;
120 /// asm!("lea {}, [{}]", lateout(reg) _, in(reg) ptr);
121 /// # }
122 /// ```
123 #[clippy::version = "1.49.0"]
124 pub INLINE_ASM_X86_ATT_SYNTAX,
125 restriction,
126 "prefer Intel x86 assembly syntax"
127 }
128
129 declare_lint_pass!(InlineAsmX86AttSyntax => [INLINE_ASM_X86_ATT_SYNTAX]);
130
131 impl EarlyLintPass for InlineAsmX86AttSyntax {
check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr)132 fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
133 check_expr_asm_syntax(Self::get_lints()[0], cx, expr, AsmStyle::Att);
134 }
135 }
136