@@ -18,7 +18,7 @@ use rustc_target::abi::call::{
1818 ArgAbi , ArgAttribute , ArgAttributes , ArgExtension , Conv , FnAbi , PassMode , Reg , RegKind ,
1919} ;
2020use rustc_target:: abi:: * ;
21- use rustc_target:: spec:: { abi:: Abi as SpecAbi , HasTargetSpec , PanicStrategy } ;
21+ use rustc_target:: spec:: { abi:: Abi as SpecAbi , HasTargetSpec , PanicStrategy , Target } ;
2222
2323use std:: cmp;
2424use std:: fmt;
@@ -2015,6 +2015,12 @@ impl<'tcx> HasDataLayout for TyCtxt<'tcx> {
20152015 }
20162016}
20172017
2018+ impl < ' tcx > HasTargetSpec for TyCtxt < ' tcx > {
2019+ fn target_spec ( & self ) -> & Target {
2020+ & self . sess . target
2021+ }
2022+ }
2023+
20182024impl < ' tcx > HasTyCtxt < ' tcx > for TyCtxt < ' tcx > {
20192025 #[ inline]
20202026 fn tcx ( & self ) -> TyCtxt < ' tcx > {
@@ -2048,6 +2054,12 @@ impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> {
20482054 }
20492055}
20502056
2057+ impl < ' tcx , T : HasTargetSpec > HasTargetSpec for LayoutCx < ' tcx , T > {
2058+ fn target_spec ( & self ) -> & Target {
2059+ self . tcx . target_spec ( )
2060+ }
2061+ }
2062+
20512063impl < ' tcx , T : HasTyCtxt < ' tcx > > HasTyCtxt < ' tcx > for LayoutCx < ' tcx , T > {
20522064 fn tcx ( & self ) -> TyCtxt < ' tcx > {
20532065 self . tcx . tcx ( )
@@ -2788,9 +2800,39 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
27882800 }
27892801}
27902802
2803+ /// Error produced by attempting to compute or adjust a `FnAbi`.
2804+ enum FnAbiError < ' tcx > {
2805+ /// Error produced by a `layout_of` call, while computing `FnAbi` initially.
2806+ Layout ( LayoutError < ' tcx > ) ,
2807+
2808+ /// Error produced by attempting to adjust a `FnAbi`, for a "foreign" ABI.
2809+ AdjustForForeignAbi ( call:: AdjustForForeignAbiError ) ,
2810+ }
2811+
2812+ impl From < LayoutError < ' tcx > > for FnAbiError < ' tcx > {
2813+ fn from ( err : LayoutError < ' tcx > ) -> Self {
2814+ Self :: Layout ( err)
2815+ }
2816+ }
2817+
2818+ impl From < call:: AdjustForForeignAbiError > for FnAbiError < ' _ > {
2819+ fn from ( err : call:: AdjustForForeignAbiError ) -> Self {
2820+ Self :: AdjustForForeignAbi ( err)
2821+ }
2822+ }
2823+
2824+ impl < ' tcx > fmt:: Display for FnAbiError < ' tcx > {
2825+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
2826+ match self {
2827+ Self :: Layout ( err) => err. fmt ( f) ,
2828+ Self :: AdjustForForeignAbi ( err) => err. fmt ( f) ,
2829+ }
2830+ }
2831+ }
2832+
27912833pub trait FnAbiExt < ' tcx , C >
27922834where
2793- C : LayoutOf < ' tcx , LayoutOfResult = TyAndLayout < ' tcx > > + HasTargetSpec ,
2835+ C : HasTyCtxt < ' tcx > + HasParamEnv < ' tcx > ,
27942836{
27952837 /// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
27962838 ///
@@ -2808,10 +2850,26 @@ where
28082850
28092851impl < ' tcx , C > FnAbiExt < ' tcx , C > for call:: FnAbi < ' tcx , Ty < ' tcx > >
28102852where
2811- C : LayoutOf < ' tcx , LayoutOfResult = TyAndLayout < ' tcx > > + HasTargetSpec ,
2853+ C : HasTyCtxt < ' tcx > + HasParamEnv < ' tcx > ,
28122854{
28132855 fn of_fn_ptr ( cx : & C , sig : ty:: PolyFnSig < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
2814- call:: FnAbi :: new_internal ( cx, sig, extra_args, None , CodegenFnAttrFlags :: empty ( ) , false )
2856+ call:: FnAbi :: new_internal (
2857+ & LayoutCx { tcx : cx. tcx ( ) , param_env : cx. param_env ( ) } ,
2858+ sig,
2859+ extra_args,
2860+ None ,
2861+ CodegenFnAttrFlags :: empty ( ) ,
2862+ false ,
2863+ )
2864+ . unwrap_or_else ( |err| {
2865+ // FIXME(eddyb) get a better `span` here.
2866+ let span = DUMMY_SP ;
2867+ if let FnAbiError :: Layout ( LayoutError :: SizeOverflow ( _) ) = err {
2868+ cx. tcx ( ) . sess . span_fatal ( span, & err. to_string ( ) )
2869+ } else {
2870+ span_bug ! ( span, "`FnAbi::of_fn_ptr({}, {:?})` failed: {}" , sig, extra_args, err) ;
2871+ }
2872+ } )
28152873 }
28162874
28172875 fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
@@ -2826,35 +2884,57 @@ where
28262884 let attrs = cx. tcx ( ) . codegen_fn_attrs ( instance. def_id ( ) ) . flags ;
28272885
28282886 call:: FnAbi :: new_internal (
2829- cx ,
2887+ & LayoutCx { tcx : cx . tcx ( ) , param_env : cx . param_env ( ) } ,
28302888 sig,
28312889 extra_args,
28322890 caller_location,
28332891 attrs,
28342892 matches ! ( instance. def, ty:: InstanceDef :: Virtual ( ..) ) ,
28352893 )
2894+ . unwrap_or_else ( |err| {
2895+ // FIXME(eddyb) get a better `span` here.
2896+ let span = cx. tcx ( ) . def_span ( instance. def_id ( ) ) ;
2897+ if let FnAbiError :: Layout ( LayoutError :: SizeOverflow ( _) ) = err {
2898+ cx. tcx ( ) . sess . span_fatal ( span, & err. to_string ( ) )
2899+ } else {
2900+ span_bug ! (
2901+ span,
2902+ "`FnAbi::of_instance({}, {:?})` failed: {}" ,
2903+ instance,
2904+ extra_args,
2905+ err
2906+ ) ;
2907+ }
2908+ } )
28362909 }
28372910}
28382911
28392912/// Implementation detail of computing `FnAbi`s, shouldn't be exported.
2840- trait FnAbiInternalExt < ' tcx , C >
2913+ // FIXME(eddyb) move this off of being generic on `C: LayoutOf`, and
2914+ // explicitly take `LayoutCx` *or* `TyCtxt` and `ParamEnvAnd<...>`.
2915+ trait FnAbiInternalExt < ' tcx , C > : Sized
28412916where
2842- C : LayoutOf < ' tcx , LayoutOfResult = TyAndLayout < ' tcx > > + HasTargetSpec ,
2917+ C : LayoutOf < ' tcx , LayoutOfResult = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > >
2918+ + HasTargetSpec ,
28432919{
2920+ // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
2921+ // arguments of this method, into a separate `struct`.
28442922 fn new_internal (
28452923 cx : & C ,
28462924 sig : ty:: PolyFnSig < ' tcx > ,
28472925 extra_args : & [ Ty < ' tcx > ] ,
28482926 caller_location : Option < Ty < ' tcx > > ,
28492927 codegen_fn_attr_flags : CodegenFnAttrFlags ,
2928+ // FIXME(eddyb) replace this with something typed, like an `enum`.
28502929 make_self_ptr_thin : bool ,
2851- ) -> Self ;
2852- fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) ;
2930+ ) -> Result < Self , FnAbiError < ' tcx > > ;
2931+ fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) -> Result < ( ) , FnAbiError < ' tcx > > ;
28532932}
28542933
28552934impl < ' tcx , C > FnAbiInternalExt < ' tcx , C > for call:: FnAbi < ' tcx , Ty < ' tcx > >
28562935where
2857- C : LayoutOf < ' tcx , LayoutOfResult = TyAndLayout < ' tcx > > + HasTargetSpec ,
2936+ C : LayoutOf < ' tcx , LayoutOfResult = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > >
2937+ + HasTargetSpec ,
28582938{
28592939 fn new_internal (
28602940 cx : & C ,
@@ -2863,10 +2943,10 @@ where
28632943 caller_location : Option < Ty < ' tcx > > ,
28642944 codegen_fn_attr_flags : CodegenFnAttrFlags ,
28652945 force_thin_self_ptr : bool ,
2866- ) -> Self {
2946+ ) -> Result < Self , FnAbiError < ' tcx > > {
28672947 debug ! ( "FnAbi::new_internal({:?}, {:?})" , sig, extra_args) ;
28682948
2869- let sig = cx. tcx ( ) . normalize_erasing_late_bound_regions ( ty :: ParamEnv :: reveal_all ( ) , sig) ;
2949+ let sig = cx. tcx ( ) . normalize_erasing_late_bound_regions ( cx . param_env ( ) , sig) ;
28702950
28712951 let conv = conv_from_spec_abi ( cx. tcx ( ) , sig. abi ) ;
28722952
@@ -2972,10 +3052,10 @@ where
29723052 }
29733053 } ;
29743054
2975- let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | {
3055+ let arg_of = |ty : Ty < ' tcx > , arg_idx : Option < usize > | -> Result < _ , FnAbiError < ' tcx > > {
29763056 let is_return = arg_idx. is_none ( ) ;
29773057
2978- let layout = cx. layout_of ( ty) ;
3058+ let layout = cx. layout_of ( ty) ? ;
29793059 let layout = if force_thin_self_ptr && arg_idx == Some ( 0 ) {
29803060 // Don't pass the vtable, it's not an argument of the virtual fn.
29813061 // Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
@@ -3006,32 +3086,32 @@ where
30063086 }
30073087 }
30083088
3009- arg
3089+ Ok ( arg)
30103090 } ;
30113091
30123092 let mut fn_abi = FnAbi {
3013- ret : arg_of ( sig. output ( ) , None ) ,
3093+ ret : arg_of ( sig. output ( ) , None ) ? ,
30143094 args : inputs
30153095 . iter ( )
30163096 . cloned ( )
30173097 . chain ( extra_args)
30183098 . chain ( caller_location)
30193099 . enumerate ( )
30203100 . map ( |( i, ty) | arg_of ( ty, Some ( i) ) )
3021- . collect ( ) ,
3101+ . collect :: < Result < _ , _ > > ( ) ? ,
30223102 c_variadic : sig. c_variadic ,
30233103 fixed_count : inputs. len ( ) ,
30243104 conv,
30253105 can_unwind : fn_can_unwind ( cx. tcx ( ) , codegen_fn_attr_flags, sig. abi ) ,
30263106 } ;
3027- fn_abi. adjust_for_abi ( cx, sig. abi ) ;
3107+ fn_abi. adjust_for_abi ( cx, sig. abi ) ? ;
30283108 debug ! ( "FnAbi::new_internal = {:?}" , fn_abi) ;
3029- fn_abi
3109+ Ok ( fn_abi)
30303110 }
30313111
3032- fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) {
3112+ fn adjust_for_abi ( & mut self , cx : & C , abi : SpecAbi ) -> Result < ( ) , FnAbiError < ' tcx > > {
30333113 if abi == SpecAbi :: Unadjusted {
3034- return ;
3114+ return Ok ( ( ) ) ;
30353115 }
30363116
30373117 if abi == SpecAbi :: Rust
@@ -3095,12 +3175,11 @@ where
30953175 for arg in & mut self . args {
30963176 fixup ( arg) ;
30973177 }
3098- return ;
3178+ } else {
3179+ self . adjust_for_foreign_abi ( cx, abi) ?;
30993180 }
31003181
3101- if let Err ( msg) = self . adjust_for_foreign_abi ( cx, abi) {
3102- cx. tcx ( ) . sess . fatal ( & msg) ;
3103- }
3182+ Ok ( ( ) )
31043183 }
31053184}
31063185
0 commit comments