@@ -19,9 +19,9 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
1919 StableHasherResult } ;
2020
2121pub use rustc_target:: abi:: * ;
22- use rustc_target:: spec:: HasTargetSpec ;
22+ use rustc_target:: spec:: { HasTargetSpec , abi :: Abi as SpecAbi } ;
2323use rustc_target:: abi:: call:: {
24- ArgAttribute , ArgAttributes , ArgType , Conv , FnType , IgnoreMode , PassMode
24+ ArgAttribute , ArgAttributes , ArgType , Conv , FnType , IgnoreMode , PassMode , Reg , RegKind
2525} ;
2626
2727
@@ -2266,81 +2266,48 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for LayoutError<'gcx>
22662266 }
22672267}
22682268
2269- pub trait FnTypeExt < ' tcx , C > {
2270- fn of_instance ( cx : & C , instance : & ty:: Instance < ' tcx > ) -> Self
2271- where
2272- C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
2273- + HasDataLayout
2274- + HasTargetSpec
2275- + HasTyCtxt < ' tcx >
2276- + HasParamEnv < ' tcx > ;
2277- fn new ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self
2278- where
2279- C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
2280- + HasDataLayout
2281- + HasTargetSpec
2282- + HasTyCtxt < ' tcx >
2283- + HasParamEnv < ' tcx > ;
2284- fn new_vtable ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self
2285- where
2286- C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
2287- + HasDataLayout
2288- + HasTargetSpec
2289- + HasTyCtxt < ' tcx >
2290- + HasParamEnv < ' tcx > ;
2269+ pub trait FnTypeExt < ' tcx , C >
2270+ where
2271+ C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
2272+ + HasDataLayout
2273+ + HasTargetSpec
2274+ + HasTyCtxt < ' tcx >
2275+ + HasParamEnv < ' tcx > ,
2276+ {
2277+ fn of_instance ( cx : & C , instance : & ty:: Instance < ' tcx > ) -> Self ;
2278+ fn new ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self ;
2279+ fn new_vtable ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self ;
22912280 fn new_internal (
22922281 cx : & C ,
22932282 sig : ty:: FnSig < ' tcx > ,
22942283 extra_args : & [ Ty < ' tcx > ] ,
22952284 mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgType < ' tcx , Ty < ' tcx > > ,
2296- ) -> Self
2297- where
2298- C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
2299- + HasDataLayout
2300- + HasTargetSpec
2301- + HasTyCtxt < ' tcx >
2302- + HasParamEnv < ' tcx > ;
2285+ ) -> Self ;
2286+ fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) ;
23032287}
23042288
2305-
2306- impl < ' tcx , C > FnTypeExt < ' tcx , C > for call:: FnType < ' tcx , Ty < ' tcx > > {
2307- fn of_instance ( cx : & C , instance : & ty:: Instance < ' tcx > ) -> Self
2308- where
2309- C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
2310- + HasDataLayout
2311- + HasTargetSpec
2312- + HasTargetSpec
2313- + HasTyCtxt < ' tcx >
2314- + HasParamEnv < ' tcx > ,
2315- {
2289+ impl < ' tcx , C > FnTypeExt < ' tcx , C > for call:: FnType < ' tcx , Ty < ' tcx > >
2290+ where
2291+ C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
2292+ + HasDataLayout
2293+ + HasTargetSpec
2294+ + HasTyCtxt < ' tcx >
2295+ + HasParamEnv < ' tcx > ,
2296+ {
2297+ fn of_instance ( cx : & C , instance : & ty:: Instance < ' tcx > ) -> Self {
23162298 let sig = instance. fn_sig ( cx. tcx ( ) ) ;
23172299 let sig = cx
23182300 . tcx ( )
23192301 . normalize_erasing_late_bound_regions ( ty:: ParamEnv :: reveal_all ( ) , & sig) ;
23202302 call:: FnType :: new ( cx, sig, & [ ] )
23212303 }
23222304
2323- fn new ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self
2324- where
2325- C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
2326- + HasDataLayout
2327- + HasTargetSpec
2328- + HasTyCtxt < ' tcx >
2329- + HasParamEnv < ' tcx > ,
2330- {
2305+ fn new ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
23312306 call:: FnType :: new_internal ( cx, sig, extra_args, |ty, _| ArgType :: new ( cx. layout_of ( ty) ) )
23322307 }
23332308
2334-
2335- fn new_vtable ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self
2336- where
2337- C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
2338- + HasDataLayout
2339- + HasTargetSpec
2340- + HasTyCtxt < ' tcx >
2341- + HasParamEnv < ' tcx > ,
2342- {
2343- FnType :: new_internal ( cx, sig, extra_args, |ty, arg_idx| {
2309+ fn new_vtable ( cx : & C , sig : ty:: FnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
2310+ FnTypeExt :: new_internal ( cx, sig, extra_args, |ty, arg_idx| {
23442311 let mut layout = cx. layout_of ( ty) ;
23452312 // Don't pass the vtable, it's not an argument of the virtual fn.
23462313 // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
@@ -2395,19 +2362,11 @@ impl<'tcx, C> FnTypeExt<'tcx, C> for call::FnType<'tcx, Ty<'tcx>> {
23952362 }
23962363
23972364 fn new_internal (
2398- cx : & C ,
2399- sig : ty:: FnSig < ' tcx > ,
2400- extra_args : & [ Ty < ' tcx > ] ,
2401- mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgType < ' tcx , Ty < ' tcx > > ,
2402- ) -> Self
2403- where
2404- C : LayoutOf < Ty = Ty < ' tcx > , TyLayout = TyLayout < ' tcx > >
2405- + HasDataLayout
2406- + HasTargetSpec
2407- + HasTargetSpec
2408- + HasTyCtxt < ' tcx >
2409- + HasParamEnv < ' tcx > ,
2410- {
2365+ cx : & C ,
2366+ sig : ty:: FnSig < ' tcx > ,
2367+ extra_args : & [ Ty < ' tcx > ] ,
2368+ mk_arg_type : impl Fn ( Ty < ' tcx > , Option < usize > ) -> ArgType < ' tcx , Ty < ' tcx > > ,
2369+ ) -> Self {
24112370 debug ! ( "FnType::new_internal({:?}, {:?})" , sig, extra_args) ;
24122371
24132372 use rustc_target:: spec:: abi:: Abi :: * ;
@@ -2591,7 +2550,7 @@ impl<'tcx, C> FnTypeExt<'tcx, C> for call::FnType<'tcx, Ty<'tcx>> {
25912550 arg
25922551 } ;
25932552
2594- let fn_ty = FnType {
2553+ let mut fn_ty = FnType {
25952554 ret : arg_of ( sig. output ( ) , None ) ,
25962555 args : inputs
25972556 . iter ( )
@@ -2603,8 +2562,83 @@ impl<'tcx, C> FnTypeExt<'tcx, C> for call::FnType<'tcx, Ty<'tcx>> {
26032562 c_variadic : sig. c_variadic ,
26042563 conv,
26052564 } ;
2606- // FIXME: uncomment this after figuring out wwhere should adjust_for_abi reside.
2607- //fn_ty.adjust_for_abi(cx, sig.abi);
2565+ fn_ty. adjust_for_abi ( cx, sig. abi ) ;
26082566 fn_ty
26092567 }
2568+
2569+ fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) {
2570+ if abi == SpecAbi :: Unadjusted {
2571+ return ;
2572+ }
2573+
2574+ if abi == SpecAbi :: Rust
2575+ || abi == SpecAbi :: RustCall
2576+ || abi == SpecAbi :: RustIntrinsic
2577+ || abi == SpecAbi :: PlatformIntrinsic
2578+ {
2579+ let fixup = |arg : & mut ArgType < ' tcx , Ty < ' tcx > > | {
2580+ if arg. is_ignore ( ) {
2581+ return ;
2582+ }
2583+
2584+ match arg. layout . abi {
2585+ Abi :: Aggregate { .. } => { }
2586+
2587+ // This is a fun case! The gist of what this is doing is
2588+ // that we want callers and callees to always agree on the
2589+ // ABI of how they pass SIMD arguments. If we were to *not*
2590+ // make these arguments indirect then they'd be immediates
2591+ // in LLVM, which means that they'd used whatever the
2592+ // appropriate ABI is for the callee and the caller. That
2593+ // means, for example, if the caller doesn't have AVX
2594+ // enabled but the callee does, then passing an AVX argument
2595+ // across this boundary would cause corrupt data to show up.
2596+ //
2597+ // This problem is fixed by unconditionally passing SIMD
2598+ // arguments through memory between callers and callees
2599+ // which should get them all to agree on ABI regardless of
2600+ // target feature sets. Some more information about this
2601+ // issue can be found in #44367.
2602+ //
2603+ // Note that the platform intrinsic ABI is exempt here as
2604+ // that's how we connect up to LLVM and it's unstable
2605+ // anyway, we control all calls to it in libstd.
2606+ Abi :: Vector { .. }
2607+ if abi != SpecAbi :: PlatformIntrinsic
2608+ && cx. tcx ( ) . sess . target . target . options . simd_types_indirect =>
2609+ {
2610+ arg. make_indirect ( ) ;
2611+ return ;
2612+ }
2613+
2614+ _ => return ,
2615+ }
2616+
2617+ let size = arg. layout . size ;
2618+ if arg. layout . is_unsized ( ) || size > Pointer . size ( cx) {
2619+ arg. make_indirect ( ) ;
2620+ } else {
2621+ // We want to pass small aggregates as immediates, but using
2622+ // a LLVM aggregate type for this leads to bad optimizations,
2623+ // so we pick an appropriately sized integer type instead.
2624+ arg. cast_to ( Reg {
2625+ kind : RegKind :: Integer ,
2626+ size,
2627+ } ) ;
2628+ }
2629+ } ;
2630+ fixup ( & mut self . ret ) ;
2631+ for arg in & mut self . args {
2632+ fixup ( arg) ;
2633+ }
2634+ if let PassMode :: Indirect ( ref mut attrs, _) = self . ret . mode {
2635+ attrs. set ( ArgAttribute :: StructRet ) ;
2636+ }
2637+ return ;
2638+ }
2639+
2640+ if let Err ( msg) = self . adjust_for_cabi ( cx, abi) {
2641+ cx. tcx ( ) . sess . fatal ( & msg) ;
2642+ }
2643+ }
26102644}
0 commit comments