33use  rustc_abi:: { BackendRepr ,  RegKind } ; 
44use  rustc_hir:: CRATE_HIR_ID ; 
55use  rustc_middle:: mir:: { self ,  traversal} ; 
6- use  rustc_middle:: ty:: { self ,  Instance ,  InstanceKind ,  Ty ,  TyCtxt } ; 
7- use  rustc_session:: lint:: builtin:: ABI_UNSUPPORTED_VECTOR_TYPES ; 
6+ use  rustc_middle:: ty:: layout:: LayoutCx ; 
7+ use  rustc_middle:: ty:: { self ,  Instance ,  InstanceKind ,  Ty ,  TyCtxt ,  TypingEnv } ; 
8+ use  rustc_session:: lint:: builtin:: { ABI_UNSUPPORTED_VECTOR_TYPES ,  WASM_C_ABI } ; 
89use  rustc_span:: def_id:: DefId ; 
910use  rustc_span:: { DUMMY_SP ,  Span ,  Symbol ,  sym} ; 
10- use  rustc_target:: callconv:: { Conv ,  FnAbi ,  PassMode } ; 
11+ use  rustc_target:: callconv:: { ArgAbi ,  Conv ,  FnAbi ,  PassMode } ; 
12+ use  rustc_target:: spec:: { HasWasmCAbiOpt ,  WasmCAbi } ; 
1113
1214use  crate :: errors; 
1315
@@ -26,13 +28,15 @@ fn uses_vector_registers(mode: &PassMode, repr: &BackendRepr) -> bool {
2628/// for a certain function. 
2729/// `is_call` indicates whether this is a call-site check or a definition-site check; 
2830/// this is only relevant for the wording in the emitted error. 
29- fn  do_check_abi < ' tcx > ( 
31+ fn  do_check_simd_vector_abi < ' tcx > ( 
3032    tcx :  TyCtxt < ' tcx > , 
3133    abi :  & FnAbi < ' tcx ,  Ty < ' tcx > > , 
3234    def_id :  DefId , 
3335    is_call :  bool , 
3436    span :  impl  Fn ( )  -> Span , 
3537)  { 
38+     // We check this on all functions, including those using the "Rust" ABI. 
39+     // For the "Rust" ABI it would be a bug if the lint ever triggered, but better safe than sorry. 
3640    let  feature_def = tcx. sess . target . features_for_correct_vector_abi ( ) ; 
3741    let  codegen_attrs = tcx. codegen_fn_attrs ( def_id) ; 
3842    let  have_feature = |feat :  Symbol | { 
@@ -88,6 +92,59 @@ fn do_check_abi<'tcx>(
8892    } 
8993} 
9094
95+ fn  wasm_abi_safe < ' tcx > ( tcx :  TyCtxt < ' tcx > ,  arg :  & ArgAbi < ' tcx ,  Ty < ' tcx > > )  -> bool  { 
96+     if  matches ! ( arg. layout. backend_repr,  BackendRepr :: Scalar ( _) )  { 
97+         return  true ; 
98+     } 
99+ 
100+     // This matches `unwrap_trivial_aggregate` in the wasm ABI logic.` 
101+     if  arg. layout . is_aggregate ( )  { 
102+         let  cx = LayoutCx :: new ( tcx,  TypingEnv :: fully_monomorphized ( ) ) ; 
103+         if  let  Some ( unit)  = arg. layout . homogeneous_aggregate ( & cx) . ok ( ) . and_then ( |ha| ha. unit ( ) )  { 
104+             let  size = arg. layout . size ; 
105+             if  unit. size  == size { 
106+                 return  true ; 
107+             } 
108+         } 
109+     } 
110+ 
111+     false 
112+ } 
113+ 
114+ /// Warns against usage of `extern "C"` on wasm32-unknown-unknown that is affected by the 
115+ /// ABI transition. 
116+ fn  do_check_wasm_abi < ' tcx > ( 
117+     tcx :  TyCtxt < ' tcx > , 
118+     abi :  & FnAbi < ' tcx ,  Ty < ' tcx > > , 
119+     is_call :  bool , 
120+     span :  impl  Fn ( )  -> Span , 
121+ )  { 
122+     // 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`). 
123+     if  !( tcx. sess . target . arch  == "wasm32" 
124+         && tcx. sess . target . os  == "unknown" 
125+         && tcx. wasm_c_abi_opt ( )  == WasmCAbi :: Legacy 
126+         && abi. conv  == Conv :: C ) 
127+     { 
128+         return ; 
129+     } 
130+     // Warn against all types whose ABI will change. That's all arguments except for things passed as scalars. 
131+     // Return values are not affected by this change. 
132+     for  arg_abi in  abi. args . iter ( )  { 
133+         if  wasm_abi_safe ( tcx,  arg_abi)  { 
134+             continue ; 
135+         } 
136+         let  span = span ( ) ; 
137+         tcx. emit_node_span_lint ( 
138+             WASM_C_ABI , 
139+             CRATE_HIR_ID , 
140+             span, 
141+             errors:: WasmCAbiTransition  {  ty :  arg_abi. layout . ty ,  is_call } , 
142+         ) ; 
143+         // Let's only warn once per function. 
144+         break ; 
145+     } 
146+ } 
147+ 
91148/// Checks that the ABI of a given instance of a function does not contain vector-passed arguments 
92149/// or return values for which the corresponding target feature is not enabled. 
93150fn  check_instance_abi < ' tcx > ( tcx :  TyCtxt < ' tcx > ,  instance :  Instance < ' tcx > )  { 
@@ -98,13 +155,10 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
98155        // function. 
99156        return ; 
100157    } ; 
101-     do_check_abi ( 
102-         tcx, 
103-         abi, 
104-         instance. def_id ( ) , 
105-         /*is_call*/  false , 
106-         || tcx. def_span ( instance. def_id ( ) ) , 
107-     ) 
158+     do_check_simd_vector_abi ( tcx,  abi,  instance. def_id ( ) ,  /*is_call*/  false ,  || { 
159+         tcx. def_span ( instance. def_id ( ) ) 
160+     } ) ; 
161+     do_check_wasm_abi ( tcx,  abi,  /*is_call*/  false ,  || tcx. def_span ( instance. def_id ( ) ) ) ; 
108162} 
109163
110164/// Checks that a call expression does not try to pass a vector-passed argument which requires a 
@@ -141,7 +195,8 @@ fn check_call_site_abi<'tcx>(
141195        // ABI failed to compute; this will not get through codegen. 
142196        return ; 
143197    } ; 
144-     do_check_abi ( tcx,  callee_abi,  caller. def_id ( ) ,  /*is_call*/  true ,  || span) ; 
198+     do_check_simd_vector_abi ( tcx,  callee_abi,  caller. def_id ( ) ,  /*is_call*/  true ,  || span) ; 
199+     do_check_wasm_abi ( tcx,  callee_abi,  /*is_call*/  true ,  || span) ; 
145200} 
146201
147202fn  check_callees_abi < ' tcx > ( tcx :  TyCtxt < ' tcx > ,  instance :  Instance < ' tcx > ,  body :  & mir:: Body < ' tcx > )  { 
0 commit comments