@@ -18,7 +18,7 @@ use rustc_target::abi::call::{
18
18
ArgAbi , ArgAttribute , ArgAttributes , ArgExtension , Conv , FnAbi , PassMode , Reg , RegKind ,
19
19
} ;
20
20
use 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 } ;
22
22
23
23
use std:: cmp;
24
24
use std:: fmt;
@@ -2015,6 +2015,12 @@ impl<'tcx> HasDataLayout for TyCtxt<'tcx> {
2015
2015
}
2016
2016
}
2017
2017
2018
+ impl < ' tcx > HasTargetSpec for TyCtxt < ' tcx > {
2019
+ fn target_spec ( & self ) -> & Target {
2020
+ & self . sess . target
2021
+ }
2022
+ }
2023
+
2018
2024
impl < ' tcx > HasTyCtxt < ' tcx > for TyCtxt < ' tcx > {
2019
2025
#[ inline]
2020
2026
fn tcx ( & self ) -> TyCtxt < ' tcx > {
@@ -2048,6 +2054,12 @@ impl<'tcx, T: HasDataLayout> HasDataLayout for LayoutCx<'tcx, T> {
2048
2054
}
2049
2055
}
2050
2056
2057
+ impl < ' tcx , T : HasTargetSpec > HasTargetSpec for LayoutCx < ' tcx , T > {
2058
+ fn target_spec ( & self ) -> & Target {
2059
+ self . tcx . target_spec ( )
2060
+ }
2061
+ }
2062
+
2051
2063
impl < ' tcx , T : HasTyCtxt < ' tcx > > HasTyCtxt < ' tcx > for LayoutCx < ' tcx , T > {
2052
2064
fn tcx ( & self ) -> TyCtxt < ' tcx > {
2053
2065
self . tcx . tcx ( )
@@ -2788,9 +2800,39 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv {
2788
2800
}
2789
2801
}
2790
2802
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
+
2791
2833
pub trait FnAbiExt < ' tcx , C >
2792
2834
where
2793
- C : LayoutOf < ' tcx , LayoutOfResult = TyAndLayout < ' tcx > > + HasTargetSpec ,
2835
+ C : HasTyCtxt < ' tcx > + HasParamEnv < ' tcx > ,
2794
2836
{
2795
2837
/// Compute a `FnAbi` suitable for indirect calls, i.e. to `fn` pointers.
2796
2838
///
@@ -2808,10 +2850,26 @@ where
2808
2850
2809
2851
impl < ' tcx , C > FnAbiExt < ' tcx , C > for call:: FnAbi < ' tcx , Ty < ' tcx > >
2810
2852
where
2811
- C : LayoutOf < ' tcx , LayoutOfResult = TyAndLayout < ' tcx > > + HasTargetSpec ,
2853
+ C : HasTyCtxt < ' tcx > + HasParamEnv < ' tcx > ,
2812
2854
{
2813
2855
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
+ } )
2815
2873
}
2816
2874
2817
2875
fn of_instance ( cx : & C , instance : ty:: Instance < ' tcx > , extra_args : & [ Ty < ' tcx > ] ) -> Self {
@@ -2826,35 +2884,57 @@ where
2826
2884
let attrs = cx. tcx ( ) . codegen_fn_attrs ( instance. def_id ( ) ) . flags ;
2827
2885
2828
2886
call:: FnAbi :: new_internal (
2829
- cx ,
2887
+ & LayoutCx { tcx : cx . tcx ( ) , param_env : cx . param_env ( ) } ,
2830
2888
sig,
2831
2889
extra_args,
2832
2890
caller_location,
2833
2891
attrs,
2834
2892
matches ! ( instance. def, ty:: InstanceDef :: Virtual ( ..) ) ,
2835
2893
)
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
+ } )
2836
2909
}
2837
2910
}
2838
2911
2839
2912
/// 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
2841
2916
where
2842
- C : LayoutOf < ' tcx , LayoutOfResult = TyAndLayout < ' tcx > > + HasTargetSpec ,
2917
+ C : LayoutOf < ' tcx , LayoutOfResult = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > >
2918
+ + HasTargetSpec ,
2843
2919
{
2920
+ // FIXME(eddyb) perhaps group the signature/type-containing (or all of them?)
2921
+ // arguments of this method, into a separate `struct`.
2844
2922
fn new_internal (
2845
2923
cx : & C ,
2846
2924
sig : ty:: PolyFnSig < ' tcx > ,
2847
2925
extra_args : & [ Ty < ' tcx > ] ,
2848
2926
caller_location : Option < Ty < ' tcx > > ,
2849
2927
codegen_fn_attr_flags : CodegenFnAttrFlags ,
2928
+ // FIXME(eddyb) replace this with something typed, like an `enum`.
2850
2929
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 > > ;
2853
2932
}
2854
2933
2855
2934
impl < ' tcx , C > FnAbiInternalExt < ' tcx , C > for call:: FnAbi < ' tcx , Ty < ' tcx > >
2856
2935
where
2857
- C : LayoutOf < ' tcx , LayoutOfResult = TyAndLayout < ' tcx > > + HasTargetSpec ,
2936
+ C : LayoutOf < ' tcx , LayoutOfResult = Result < TyAndLayout < ' tcx > , LayoutError < ' tcx > > >
2937
+ + HasTargetSpec ,
2858
2938
{
2859
2939
fn new_internal (
2860
2940
cx : & C ,
@@ -2863,10 +2943,10 @@ where
2863
2943
caller_location : Option < Ty < ' tcx > > ,
2864
2944
codegen_fn_attr_flags : CodegenFnAttrFlags ,
2865
2945
force_thin_self_ptr : bool ,
2866
- ) -> Self {
2946
+ ) -> Result < Self , FnAbiError < ' tcx > > {
2867
2947
debug ! ( "FnAbi::new_internal({:?}, {:?})" , sig, extra_args) ;
2868
2948
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) ;
2870
2950
2871
2951
let conv = conv_from_spec_abi ( cx. tcx ( ) , sig. abi ) ;
2872
2952
@@ -2972,10 +3052,10 @@ where
2972
3052
}
2973
3053
} ;
2974
3054
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 > > {
2976
3056
let is_return = arg_idx. is_none ( ) ;
2977
3057
2978
- let layout = cx. layout_of ( ty) ;
3058
+ let layout = cx. layout_of ( ty) ? ;
2979
3059
let layout = if force_thin_self_ptr && arg_idx == Some ( 0 ) {
2980
3060
// Don't pass the vtable, it's not an argument of the virtual fn.
2981
3061
// Instead, pass just the data pointer, but give it the type `*const/mut dyn Trait`
@@ -3006,32 +3086,32 @@ where
3006
3086
}
3007
3087
}
3008
3088
3009
- arg
3089
+ Ok ( arg)
3010
3090
} ;
3011
3091
3012
3092
let mut fn_abi = FnAbi {
3013
- ret : arg_of ( sig. output ( ) , None ) ,
3093
+ ret : arg_of ( sig. output ( ) , None ) ? ,
3014
3094
args : inputs
3015
3095
. iter ( )
3016
3096
. cloned ( )
3017
3097
. chain ( extra_args)
3018
3098
. chain ( caller_location)
3019
3099
. enumerate ( )
3020
3100
. map ( |( i, ty) | arg_of ( ty, Some ( i) ) )
3021
- . collect ( ) ,
3101
+ . collect :: < Result < _ , _ > > ( ) ? ,
3022
3102
c_variadic : sig. c_variadic ,
3023
3103
fixed_count : inputs. len ( ) ,
3024
3104
conv,
3025
3105
can_unwind : fn_can_unwind ( cx. tcx ( ) , codegen_fn_attr_flags, sig. abi ) ,
3026
3106
} ;
3027
- fn_abi. adjust_for_abi ( cx, sig. abi ) ;
3107
+ fn_abi. adjust_for_abi ( cx, sig. abi ) ? ;
3028
3108
debug ! ( "FnAbi::new_internal = {:?}" , fn_abi) ;
3029
- fn_abi
3109
+ Ok ( fn_abi)
3030
3110
}
3031
3111
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 > > {
3033
3113
if abi == SpecAbi :: Unadjusted {
3034
- return ;
3114
+ return Ok ( ( ) ) ;
3035
3115
}
3036
3116
3037
3117
if abi == SpecAbi :: Rust
@@ -3095,12 +3175,11 @@ where
3095
3175
for arg in & mut self . args {
3096
3176
fixup ( arg) ;
3097
3177
}
3098
- return ;
3178
+ } else {
3179
+ self . adjust_for_foreign_abi ( cx, abi) ?;
3099
3180
}
3100
3181
3101
- if let Err ( msg) = self . adjust_for_foreign_abi ( cx, abi) {
3102
- cx. tcx ( ) . sess . fatal ( & msg) ;
3103
- }
3182
+ Ok ( ( ) )
3104
3183
}
3105
3184
}
3106
3185
0 commit comments