1
1
//! This module ensures that if a function's ABI requires a particular target feature,
2
2
//! that target feature is enabled both on the callee and all callers.
3
3
use 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} ;
6
6
use rustc_middle:: ty:: layout:: LayoutCx ;
7
7
use rustc_middle:: ty:: { self , Instance , InstanceKind , Ty , TyCtxt , TypingEnv } ;
8
8
use rustc_session:: lint:: builtin:: { ABI_UNSUPPORTED_VECTOR_TYPES , WASM_C_ABI } ;
@@ -33,7 +33,7 @@ fn do_check_simd_vector_abi<'tcx>(
33
33
abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
34
34
def_id : DefId ,
35
35
is_call : bool ,
36
- span : impl Fn ( ) -> Span ,
36
+ loc : impl Fn ( ) -> ( Span , HirId ) ,
37
37
) {
38
38
// We check this on all functions, including those using the "Rust" ABI.
39
39
// 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>(
50
50
let feature = match feature_def. iter ( ) . find ( |( bits, _) | size. bits ( ) <= * bits) {
51
51
Some ( ( _, feature) ) => feature,
52
52
None => {
53
- let span = span ( ) ;
53
+ let ( span, hir_id ) = loc ( ) ;
54
54
tcx. emit_node_span_lint (
55
55
ABI_UNSUPPORTED_VECTOR_TYPES ,
56
- CRATE_HIR_ID ,
56
+ hir_id ,
57
57
span,
58
58
errors:: AbiErrorUnsupportedVectorType {
59
59
span,
@@ -66,10 +66,10 @@ fn do_check_simd_vector_abi<'tcx>(
66
66
} ;
67
67
if !have_feature ( Symbol :: intern ( feature) ) {
68
68
// Emit error.
69
- let span = span ( ) ;
69
+ let ( span, hir_id ) = loc ( ) ;
70
70
tcx. emit_node_span_lint (
71
71
ABI_UNSUPPORTED_VECTOR_TYPES ,
72
- CRATE_HIR_ID ,
72
+ hir_id ,
73
73
span,
74
74
errors:: AbiErrorDisabledVectorType {
75
75
span,
@@ -83,8 +83,9 @@ fn do_check_simd_vector_abi<'tcx>(
83
83
}
84
84
// The `vectorcall` ABI is special in that it requires SSE2 no matter which types are being passed.
85
85
if abi. conv == Conv :: X86VectorCall && !have_feature ( sym:: sse2) {
86
+ let ( span, _hir_id) = loc ( ) ;
86
87
tcx. dcx ( ) . emit_err ( errors:: AbiRequiredTargetFeature {
87
- span : span ( ) ,
88
+ span,
88
89
required_feature : "sse2" ,
89
90
abi : "vectorcall" ,
90
91
is_call,
@@ -119,7 +120,7 @@ fn do_check_wasm_abi<'tcx>(
119
120
tcx : TyCtxt < ' tcx > ,
120
121
abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
121
122
is_call : bool ,
122
- span : impl Fn ( ) -> Span ,
123
+ loc : impl Fn ( ) -> ( Span , HirId ) ,
123
124
) {
124
125
// 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`),
125
126
// and only proceed if `wasm_c_abi_opt` indicates we should emit the lint.
@@ -135,10 +136,10 @@ fn do_check_wasm_abi<'tcx>(
135
136
if wasm_abi_safe ( tcx, arg_abi) {
136
137
continue ;
137
138
}
138
- let span = span ( ) ;
139
+ let ( span, hir_id ) = loc ( ) ;
139
140
tcx. emit_node_span_lint (
140
141
WASM_C_ABI ,
141
- CRATE_HIR_ID ,
142
+ hir_id ,
142
143
span,
143
144
errors:: WasmCAbiTransition { ty : arg_abi. layout . ty , is_call } ,
144
145
) ;
@@ -157,19 +158,24 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
157
158
// function.
158
159
return ;
159
160
} ;
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) ;
164
170
}
165
171
166
172
/// Checks that a call expression does not try to pass a vector-passed argument which requires a
167
173
/// target feature that the caller does not have, as doing so causes UB because of ABI mismatch.
168
174
fn check_call_site_abi < ' tcx > (
169
175
tcx : TyCtxt < ' tcx > ,
170
176
callee : Ty < ' tcx > ,
171
- span : Span ,
172
177
caller : InstanceKind < ' tcx > ,
178
+ loc : impl Fn ( ) -> ( Span , HirId ) ,
173
179
) {
174
180
if callee. fn_sig ( tcx) . abi ( ) . is_rustic_abi ( ) {
175
181
// we directly handle the soundness of Rust ABIs
@@ -197,8 +203,8 @@ fn check_call_site_abi<'tcx>(
197
203
// ABI failed to compute; this will not get through codegen.
198
204
return ;
199
205
} ;
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 ) ;
202
208
}
203
209
204
210
fn 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
214
220
ty:: TypingEnv :: fully_monomorphized ( ) ,
215
221
ty:: EarlyBinder :: bind ( callee_ty) ,
216
222
) ;
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
+ } ) ;
218
236
}
219
237
_ => { }
220
238
}
0 commit comments