@@ -35,6 +35,7 @@ declare_lint_pass! {
3535 DEPENDENCY_ON_UNIT_NEVER_TYPE_FALLBACK ,
3636 DEPRECATED ,
3737 DEPRECATED_IN_FUTURE ,
38+ DEPRECATED_LLVM_INTRINSIC ,
3839 DEPRECATED_SAFE_2024 ,
3940 DEPRECATED_WHERE_CLAUSE_LOCATION ,
4041 DUPLICATE_MACRO_ATTRIBUTES ,
@@ -117,6 +118,7 @@ declare_lint_pass! {
117118 UNKNOWN_CRATE_TYPES ,
118119 UNKNOWN_DIAGNOSTIC_ATTRIBUTES ,
119120 UNKNOWN_LINTS ,
121+ UNKNOWN_LLVM_INTRINSIC ,
120122 UNNAMEABLE_TEST_ITEMS ,
121123 UNNAMEABLE_TYPES ,
122124 UNREACHABLE_CODE ,
@@ -5138,3 +5140,79 @@ declare_lint! {
51385140 "detects tail calls of functions marked with `#[track_caller]`" ,
51395141 @feature_gate = explicit_tail_calls;
51405142}
5143+
5144+ declare_lint ! {
5145+ /// The `unknown_llvm_intrinsic` lint detects usage of unknown LLVM intrinsics.
5146+ ///
5147+ /// ### Example
5148+ ///
5149+ /// ```rust,compile_fail
5150+ /// #![feature(link_llvm_intrinsics, abi_unadjusted)]
5151+ ///
5152+ /// unsafe extern "unadjusted" {
5153+ /// #[link_name = "llvm.abcde"]
5154+ /// fn foo();
5155+ /// }
5156+ ///
5157+ /// #[inline(never)]
5158+ /// pub fn main() {
5159+ /// unsafe { foo() }
5160+ /// }
5161+ /// ```
5162+ ///
5163+ /// {{produces}}
5164+ ///
5165+ /// ### Explanation
5166+ ///
5167+ /// Linking to an unknown LLVM intrinsic may cause linker errors (in general it's UB),
5168+ /// so this lint captures those undesirable scenarios.
5169+ pub UNKNOWN_LLVM_INTRINSIC ,
5170+ Deny ,
5171+ "detects uses of unknown LLVM intrinsics" ,
5172+ @feature_gate = link_llvm_intrinsics;
5173+ }
5174+
5175+ declare_lint ! {
5176+ /// The `deprecated_llvm_intrinsic` lint detects usage of deprecated LLVM intrinsics.
5177+ ///
5178+ /// ### Example
5179+ ///
5180+ /// ```rust,ignore (requires x86)
5181+ /// #![cfg(any(target_arch = "x86", target_arch = "x86_64"))]
5182+ /// #![feature(link_llvm_intrinsics, abi_unadjusted)]
5183+ /// #![deny(deprecated_llvm_intrinsic)]
5184+ ///
5185+ /// unsafe extern "unadjusted" {
5186+ /// #[link_name = "llvm.x86.addcarryx.u32"]
5187+ /// fn foo(a: u8, b: u32, c: u32, d: &mut u32) -> u8;
5188+ /// }
5189+ ///
5190+ /// #[inline(never)]
5191+ /// #[target_feature(enable = "adx")]
5192+ /// pub fn bar(a: u8, b: u32, c: u32, d: &mut u32) -> u8 {
5193+ /// unsafe { foo(a, b, c, d) }
5194+ /// }
5195+ /// ```
5196+ ///
5197+ /// This will produce:
5198+ ///
5199+ /// ```text
5200+ /// error: Using deprecated intrinsic `llvm.x86.addcarryx.u32`
5201+ /// --> example.rs:7:5
5202+ /// |
5203+ /// 7 | fn foo(a: u8, b: u32, c: u32, d: &mut u32) -> u8;
5204+ /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5205+ /// |
5206+ /// ```
5207+ ///
5208+ /// ### Explanation
5209+ ///
5210+ /// LLVM periodically updates its list of intrinsics. Removed intrinsics are unlikely
5211+ /// to be removed, but they may optimize less well than their new versions, so it's
5212+ /// best to use the new version. Also, some deprecated intrinsics might have buggy
5213+ /// behavior
5214+ pub DEPRECATED_LLVM_INTRINSIC ,
5215+ Allow ,
5216+ "detects uses of deprecated LLVM intrinsics" ,
5217+ @feature_gate = link_llvm_intrinsics;
5218+ }
0 commit comments