@@ -18,6 +18,7 @@ use rustc_codegen_ssa::traits::TypeMembershipCodegenMethods;
1818use rustc_data_structures:: fx:: FxIndexSet ;
1919use rustc_middle:: ty:: { Instance , Ty } ;
2020use rustc_sanitizers:: { cfi, kcfi} ;
21+ use rustc_session:: lint:: builtin:: { DEPRECATED_LLVM_INTRINSIC , UNKNOWN_LLVM_INTRINSIC } ;
2122use rustc_target:: callconv:: FnAbi ;
2223use smallvec:: SmallVec ;
2324use tracing:: debug;
@@ -156,31 +157,63 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
156157 // check if the intrinsic signatures match
157158 if !fn_abi. verify_intrinsic_signature ( self , llvm_fn_ty) {
158159 self . tcx . dcx ( ) . emit_fatal ( errors:: IntrinsicSignatureMismatch {
159- name,
160+ name,
160161 llvm_fn_ty : & format ! ( "{llvm_fn_ty:?}" ) ,
161162 rust_fn_ty : & format ! ( "{:?}" , fn_abi. rust_signature( self ) ) ,
162163 span : span ( ) ,
163164 } ) ;
164165 }
165166 }
166167
167- // Function addresses in Rust are never significant, allowing functions to
168- // be merged.
168+ // Function addresses in Rust are never significant, allowing functions to
169+ // be merged.
169170 let llfn = declare_raw_fn (
170- self ,
171- name,
172- fn_abi. llvm_cconv ( self ) ,
173- llvm:: UnnamedAddr :: Global ,
174- llvm:: Visibility :: Default ,
175- signature. fn_ty ( ) ,
176- ) ;
171+ self ,
172+ name,
173+ fn_abi. llvm_cconv ( self ) ,
174+ llvm:: UnnamedAddr :: Global ,
175+ llvm:: Visibility :: Default ,
176+ signature. fn_ty ( ) ,
177+ ) ;
177178
178179 if signature. intrinsic ( ) . is_none ( ) {
179180 // Don't apply any attributes to intrinsics, they will be applied by AutoUpgrade
180181 fn_abi. apply_attrs_llfn ( self , llfn, instance) ;
181182 }
182183
183- // todo: check for upgrades, and emit error if not upgradable
184+ if let FunctionSignature :: MaybeInvalid ( ..) = signature {
185+ let mut new_llfn = None ;
186+ let can_upgrade =
187+ unsafe { llvm:: LLVMRustUpgradeIntrinsicFunction ( llfn, & mut new_llfn, false ) } ;
188+
189+ // we can emit diagnostics for local crates only
190+ if let Some ( instance) = instance
191+ && let Some ( local_def_id) = instance. def_id ( ) . as_local ( )
192+ {
193+ let hir_id = self . tcx . local_def_id_to_hir_id ( local_def_id) ;
194+ let span = self . tcx . def_span ( local_def_id) ;
195+
196+ if can_upgrade {
197+ // not all intrinsics are upgraded to some other intrinsics, most are upgraded to instruction sequences
198+ let msg = if let Some ( new_llfn) = new_llfn {
199+ format ! (
200+ "using deprecated intrinsic `{name}`, `{}` can be used instead" ,
201+ str :: from_utf8( & llvm:: get_value_name( new_llfn) ) . unwrap( )
202+ )
203+ } else {
204+ format ! ( "using deprecated intrinsic `{name}`" )
205+ } ;
206+ self . tcx . node_lint ( DEPRECATED_LLVM_INTRINSIC , hir_id, |d| {
207+ d. primary_message ( msg) . span ( span) ;
208+ } ) ;
209+ } else {
210+ // This is either plain wrong, or this can be caused by incompatible LLVM versions, we let the user decide
211+ self . tcx . node_lint ( UNKNOWN_LLVM_INTRINSIC , hir_id, |d| {
212+ d. primary_message ( format ! ( "invalid LLVM Intrinsic `{name}`" ) ) . span ( span) ;
213+ } ) ;
214+ }
215+ }
216+ }
184217
185218 if self . tcx . sess . is_sanitizer_cfi_enabled ( ) {
186219 if let Some ( instance) = instance {
0 commit comments