@@ -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,83 @@ 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 bar() {
5159+ /// unsafe { foo() }
5160+ /// }
5161+ /// #
5162+ /// # fn main() {
5163+ /// # bar();
5164+ /// # }
5165+ /// ```
5166+ ///
5167+ /// {{produces}}
5168+ ///
5169+ /// ### Explanation
5170+ ///
5171+ /// Linking to an unknown LLVM intrinsic may cause linker errors (in general it's UB),
5172+ /// so this lint captures those undesirable scenarios.
5173+ pub UNKNOWN_LLVM_INTRINSIC ,
5174+ Deny ,
5175+ "detects uses of unknown LLVM intrinsics" ,
5176+ @feature_gate = link_llvm_intrinsics;
5177+ }
5178+
5179+ declare_lint ! {
5180+ /// The `deprecated_llvm_intrinsic` lint detects usage of deprecated LLVM intrinsics.
5181+ ///
5182+ /// ### Example
5183+ ///
5184+ /// ```rust,ignore (fails on non-x86)
5185+ /// #![cfg(any(target_arch = "x86", target_arch = "x86_64"))]
5186+ /// #![feature(link_llvm_intrinsics, abi_unadjusted)]
5187+ /// #![deny(deprecated_llvm_intrinsic)]
5188+ ///
5189+ /// unsafe extern "unadjusted" {
5190+ /// #[link_name = "llvm.x86.addcarryx.u32"]
5191+ /// fn foo(a: u8, b: u32, c: u32, d: &mut u32) -> u8;
5192+ /// }
5193+ ///
5194+ /// #[inline(never)]
5195+ /// #[target_feature(enable = "adx")]
5196+ /// pub fn bar(a: u8, b: u32, c: u32, d: &mut u32) -> u8 {
5197+ /// unsafe { foo(a, b, c, d) }
5198+ /// }
5199+ /// ```
5200+ ///
5201+ /// This will produce:
5202+ ///
5203+ /// ```text
5204+ /// error: Using deprecated intrinsic `llvm.x86.addcarryx.u32`
5205+ /// --> example.rs:7:5
5206+ /// |
5207+ /// 7 | fn foo(a: u8, b: u32, c: u32, d: &mut u32) -> u8;
5208+ /// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5209+ /// |
5210+ /// ```
5211+ ///
5212+ /// ### Explanation
5213+ ///
5214+ /// LLVM periodically updates its list of intrinsics. Removed intrinsics are unlikely
5215+ /// to be removed, but they may optimize less well than their new versions, so it's
5216+ /// best to use the new version. Also, some deprecated intrinsics might have buggy
5217+ /// behavior
5218+ pub DEPRECATED_LLVM_INTRINSIC ,
5219+ Allow ,
5220+ "detects uses of deprecated LLVM intrinsics" ,
5221+ @feature_gate = link_llvm_intrinsics;
5222+ }
0 commit comments