11//! This module ensures that if a function's ABI requires a particular target feature,
22//! that target feature is enabled both on the callee and all callers.
33use rustc_abi:: { BackendRepr , RegKind } ;
4- use rustc_hir:: CRATE_HIR_ID ;
5- use rustc_middle:: mir:: { self , traversal} ;
4+ use rustc_hir:: { CRATE_HIR_ID , HirId } ;
5+ use rustc_middle:: mir:: { self , Location , traversal} ;
66use rustc_middle:: ty:: layout:: LayoutCx ;
77use rustc_middle:: ty:: { self , Instance , InstanceKind , Ty , TyCtxt , TypingEnv } ;
88use rustc_session:: lint:: builtin:: { ABI_UNSUPPORTED_VECTOR_TYPES , WASM_C_ABI } ;
@@ -33,7 +33,7 @@ fn do_check_simd_vector_abi<'tcx>(
3333 abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
3434 def_id : DefId ,
3535 is_call : bool ,
36- span : impl Fn ( ) -> Span ,
36+ loc : impl Fn ( ) -> ( Span , HirId ) ,
3737) {
3838 // We check this on all functions, including those using the "Rust" ABI.
3939 // For the "Rust" ABI it would be a bug if the lint ever triggered, but better safe than sorry.
@@ -50,10 +50,10 @@ fn do_check_simd_vector_abi<'tcx>(
5050 let feature = match feature_def. iter ( ) . find ( |( bits, _) | size. bits ( ) <= * bits) {
5151 Some ( ( _, feature) ) => feature,
5252 None => {
53- let span = span ( ) ;
53+ let ( span, hir_id ) = loc ( ) ;
5454 tcx. emit_node_span_lint (
5555 ABI_UNSUPPORTED_VECTOR_TYPES ,
56- CRATE_HIR_ID ,
56+ hir_id ,
5757 span,
5858 errors:: AbiErrorUnsupportedVectorType {
5959 span,
@@ -66,10 +66,10 @@ fn do_check_simd_vector_abi<'tcx>(
6666 } ;
6767 if !have_feature ( Symbol :: intern ( feature) ) {
6868 // Emit error.
69- let span = span ( ) ;
69+ let ( span, hir_id ) = loc ( ) ;
7070 tcx. emit_node_span_lint (
7171 ABI_UNSUPPORTED_VECTOR_TYPES ,
72- CRATE_HIR_ID ,
72+ hir_id ,
7373 span,
7474 errors:: AbiErrorDisabledVectorType {
7575 span,
@@ -83,8 +83,9 @@ fn do_check_simd_vector_abi<'tcx>(
8383 }
8484 // The `vectorcall` ABI is special in that it requires SSE2 no matter which types are being passed.
8585 if abi. conv == Conv :: X86VectorCall && !have_feature ( sym:: sse2) {
86+ let ( span, _hir_id) = loc ( ) ;
8687 tcx. dcx ( ) . emit_err ( errors:: AbiRequiredTargetFeature {
87- span : span ( ) ,
88+ span,
8889 required_feature : "sse2" ,
8990 abi : "vectorcall" ,
9091 is_call,
@@ -119,7 +120,7 @@ fn do_check_wasm_abi<'tcx>(
119120 tcx : TyCtxt < ' tcx > ,
120121 abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
121122 is_call : bool ,
122- span : impl Fn ( ) -> Span ,
123+ loc : impl Fn ( ) -> ( Span , HirId ) ,
123124) {
124125 // Only proceed for `extern "C" fn` on wasm32-unknown-unknown (same check as what `adjust_for_foreign_abi` uses to call `compute_wasm_abi_info`),
125126 // and only proceed if `wasm_c_abi_opt` indicates we should emit the lint.
@@ -135,10 +136,10 @@ fn do_check_wasm_abi<'tcx>(
135136 if wasm_abi_safe ( tcx, arg_abi) {
136137 continue ;
137138 }
138- let span = span ( ) ;
139+ let ( span, hir_id ) = loc ( ) ;
139140 tcx. emit_node_span_lint (
140141 WASM_C_ABI ,
141- CRATE_HIR_ID ,
142+ hir_id ,
142143 span,
143144 errors:: WasmCAbiTransition { ty : arg_abi. layout . ty , is_call } ,
144145 ) ;
@@ -157,19 +158,24 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
157158 // function.
158159 return ;
159160 } ;
160- do_check_simd_vector_abi ( tcx, abi, instance. def_id ( ) , /*is_call*/ false , || {
161- tcx. def_span ( instance. def_id ( ) )
162- } ) ;
163- do_check_wasm_abi ( tcx, abi, /*is_call*/ false , || tcx. def_span ( instance. def_id ( ) ) ) ;
161+ let loc = || {
162+ let def_id = instance. def_id ( ) ;
163+ (
164+ tcx. def_span ( def_id) ,
165+ def_id. as_local ( ) . map ( |did| tcx. local_def_id_to_hir_id ( did) ) . unwrap_or ( CRATE_HIR_ID ) ,
166+ )
167+ } ;
168+ do_check_simd_vector_abi ( tcx, abi, instance. def_id ( ) , /*is_call*/ false , loc) ;
169+ do_check_wasm_abi ( tcx, abi, /*is_call*/ false , loc) ;
164170}
165171
166172/// Checks that a call expression does not try to pass a vector-passed argument which requires a
167173/// target feature that the caller does not have, as doing so causes UB because of ABI mismatch.
168174fn check_call_site_abi < ' tcx > (
169175 tcx : TyCtxt < ' tcx > ,
170176 callee : Ty < ' tcx > ,
171- span : Span ,
172177 caller : InstanceKind < ' tcx > ,
178+ loc : impl Fn ( ) -> ( Span , HirId ) ,
173179) {
174180 if callee. fn_sig ( tcx) . abi ( ) . is_rustic_abi ( ) {
175181 // we directly handle the soundness of Rust ABIs
@@ -197,8 +203,8 @@ fn check_call_site_abi<'tcx>(
197203 // ABI failed to compute; this will not get through codegen.
198204 return ;
199205 } ;
200- do_check_simd_vector_abi ( tcx, callee_abi, caller. def_id ( ) , /*is_call*/ true , || span ) ;
201- do_check_wasm_abi ( tcx, callee_abi, /*is_call*/ true , || span ) ;
206+ do_check_simd_vector_abi ( tcx, callee_abi, caller. def_id ( ) , /*is_call*/ true , & loc ) ;
207+ do_check_wasm_abi ( tcx, callee_abi, /*is_call*/ true , & loc ) ;
202208}
203209
204210fn check_callees_abi < ' tcx > ( tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > , body : & mir:: Body < ' tcx > ) {
@@ -214,7 +220,19 @@ fn check_callees_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>, body: &m
214220 ty:: TypingEnv :: fully_monomorphized ( ) ,
215221 ty:: EarlyBinder :: bind ( callee_ty) ,
216222 ) ;
217- check_call_site_abi ( tcx, callee_ty, * fn_span, body. source . instance ) ;
223+ check_call_site_abi ( tcx, callee_ty, body. source . instance , || {
224+ let loc = Location {
225+ block : bb,
226+ statement_index : body. basic_blocks [ bb] . statements . len ( ) ,
227+ } ;
228+ (
229+ * fn_span,
230+ body. source_info ( loc)
231+ . scope
232+ . lint_root ( & body. source_scopes )
233+ . unwrap_or ( CRATE_HIR_ID ) ,
234+ )
235+ } ) ;
218236 }
219237 _ => { }
220238 }
0 commit comments