@@ -4,10 +4,11 @@ use rustc_abi::{BackendRepr, RegKind};
44use rustc_hir:: CRATE_HIR_ID ;
55use rustc_middle:: mir:: { self , traversal} ;
66use rustc_middle:: ty:: { self , Instance , InstanceKind , Ty , TyCtxt } ;
7- use rustc_session:: lint:: builtin:: ABI_UNSUPPORTED_VECTOR_TYPES ;
7+ use rustc_session:: lint:: builtin:: { ABI_UNSUPPORTED_VECTOR_TYPES , WASM_C_ABI } ;
88use rustc_span:: def_id:: DefId ;
99use rustc_span:: { DUMMY_SP , Span , Symbol , sym} ;
1010use rustc_target:: callconv:: { Conv , FnAbi , PassMode } ;
11+ use rustc_target:: spec:: { HasWasmCAbiOpt , WasmCAbi } ;
1112
1213use crate :: errors;
1314
@@ -26,13 +27,15 @@ fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
2627/// for a certain function.
2728/// `is_call` indicates whether this is a call-site check or a definition-site check;
2829/// this is only relevant for the wording in the emitted error.
29- fn do_check_abi < ' tcx > (
30+ fn do_check_simd_vector_abi < ' tcx > (
3031 tcx : TyCtxt < ' tcx > ,
3132 abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
3233 def_id : DefId ,
3334 is_call : bool ,
3435 span : impl Fn ( ) -> Span ,
3536) {
37+ // We check this on all functions, including those using the "Rust" ABI.
38+ // For the "Rust" ABI it would be a bug if the lint ever triggered, but better safe than sorry.
3639 let feature_def = tcx. sess . target . features_for_correct_vector_abi ( ) ;
3740 let codegen_attrs = tcx. codegen_fn_attrs ( def_id) ;
3841 let have_feature = |feat : Symbol | {
@@ -88,6 +91,40 @@ fn do_check_abi<'tcx>(
8891 }
8992}
9093
94+ /// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the
95+ /// ABI transition.
96+ fn do_check_wasm_abi < ' tcx > (
97+ tcx : TyCtxt < ' tcx > ,
98+ abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
99+ is_call : bool ,
100+ span : impl Fn ( ) -> Span ,
101+ ) {
102+ // 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`).
103+ if !( tcx. sess . target . arch == "wasm32"
104+ && tcx. sess . target . os == "unknown"
105+ && tcx. wasm_c_abi_opt ( ) == WasmCAbi :: Legacy
106+ && abi. conv == Conv :: C )
107+ {
108+ return ;
109+ }
110+ // Warn against all types whose ABI will change. That's all arguments except for things passed as scalars.
111+ // Return values are not affected by this change. (FIXME: is this true?)
112+ for arg_abi in abi. args . iter ( ) {
113+ if matches ! ( arg_abi. layout. backend_repr, BackendRepr :: Scalar ( _) ) {
114+ continue ;
115+ }
116+ let span = span ( ) ;
117+ tcx. emit_node_span_lint (
118+ WASM_C_ABI ,
119+ CRATE_HIR_ID ,
120+ span,
121+ errors:: WasmCAbiTransition { ty : arg_abi. layout . ty , is_call } ,
122+ ) ;
123+ // Let's only warn once per function.
124+ break ;
125+ }
126+ }
127+
91128/// Checks that the ABI of a given instance of a function does not contain vector-passed arguments
92129/// or return values for which the corresponding target feature is not enabled.
93130fn check_instance_abi < ' tcx > ( tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > ) {
@@ -98,13 +135,10 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
98135 // function.
99136 return ;
100137 } ;
101- do_check_abi (
102- tcx,
103- abi,
104- instance. def_id ( ) ,
105- /*is_call*/ false ,
106- || tcx. def_span ( instance. def_id ( ) ) ,
107- )
138+ do_check_simd_vector_abi ( tcx, abi, instance. def_id ( ) , /*is_call*/ false , || {
139+ tcx. def_span ( instance. def_id ( ) )
140+ } ) ;
141+ do_check_wasm_abi ( tcx, abi, /*is_call*/ false , || tcx. def_span ( instance. def_id ( ) ) ) ;
108142}
109143
110144/// Checks that a call expression does not try to pass a vector-passed argument which requires a
@@ -141,7 +175,8 @@ fn check_call_site_abi<'tcx>(
141175 // ABI failed to compute; this will not get through codegen.
142176 return ;
143177 } ;
144- do_check_abi ( tcx, callee_abi, caller. def_id ( ) , /*is_call*/ true , || span) ;
178+ do_check_simd_vector_abi ( tcx, callee_abi, caller. def_id ( ) , /*is_call*/ true , || span) ;
179+ do_check_wasm_abi ( tcx, callee_abi, /*is_call*/ true , || span) ;
145180}
146181
147182fn check_callees_abi < ' tcx > ( tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > , body : & mir:: Body < ' tcx > ) {
0 commit comments