@@ -14,7 +14,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
14
14
use rustc_middle:: middle:: dependency_format:: Linkage ;
15
15
use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
16
16
use rustc_middle:: ty:: layout:: { FnAbiOf , LayoutOf , MaybeResult , TyAndLayout } ;
17
- use rustc_middle:: ty:: { self , FloatTy , IntTy , Ty , TyCtxt , UintTy } ;
17
+ use rustc_middle:: ty:: { self , Binder , FloatTy , FnSig , IntTy , Ty , TyCtxt , UintTy } ;
18
18
use rustc_session:: config:: CrateType ;
19
19
use rustc_span:: { Span , Symbol } ;
20
20
use rustc_target:: callconv:: { Conv , FnAbi } ;
@@ -994,10 +994,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
994
994
exp_abi : Conv ,
995
995
link_name : Symbol ,
996
996
args : & ' a [ OpTy < ' tcx > ] ,
997
- ) -> InterpResult < ' tcx , & ' a [ OpTy < ' tcx > ; N ] >
998
- where
999
- & ' a [ OpTy < ' tcx > ; N ] : TryFrom < & ' a [ OpTy < ' tcx > ] > ,
1000
- {
997
+ ) -> InterpResult < ' tcx , & ' a [ OpTy < ' tcx > ; N ] > {
1001
998
self . check_abi_and_shim_symbol_clash ( abi, exp_abi, link_name) ?;
1002
999
1003
1000
if abi. c_variadic {
@@ -1015,6 +1012,80 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
1015
1012
)
1016
1013
}
1017
1014
1015
+ /// Check that the given `caller_fn_abi` matches the expected ABI described by
1016
+ /// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and the return the list of
1017
+ /// arguments.
1018
+ fn check_shim_abi < ' a , const N : usize > (
1019
+ & mut self ,
1020
+ link_name : Symbol ,
1021
+ caller_fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1022
+ callee_abi : ExternAbi ,
1023
+ callee_input_tys : [ Ty < ' tcx > ; N ] ,
1024
+ callee_output_ty : Ty < ' tcx > ,
1025
+ caller_args : & ' a [ OpTy < ' tcx > ] ,
1026
+ ) -> InterpResult < ' tcx , & ' a [ OpTy < ' tcx > ; N ] > {
1027
+ let this = self . eval_context_mut ( ) ;
1028
+ let mut inputs_and_output = callee_input_tys. to_vec ( ) ;
1029
+ inputs_and_output. push ( callee_output_ty) ;
1030
+ let fn_sig_binder = Binder :: dummy ( FnSig {
1031
+ inputs_and_output : this. machine . tcx . mk_type_list ( & inputs_and_output) ,
1032
+ c_variadic : false ,
1033
+ // This does not matter for the ABI.
1034
+ safety : Safety :: Safe ,
1035
+ abi : callee_abi,
1036
+ } ) ;
1037
+ let callee_fn_abi = this. fn_abi_of_fn_ptr ( fn_sig_binder, Default :: default ( ) ) ?;
1038
+
1039
+ this. check_abi_and_shim_symbol_clash ( caller_fn_abi, callee_fn_abi. conv , link_name) ?;
1040
+
1041
+ if caller_fn_abi. c_variadic {
1042
+ throw_ub_format ! (
1043
+ "ABI mismatch: calling a non-variadic function with a variadic caller-side signature"
1044
+ ) ;
1045
+ }
1046
+
1047
+ if callee_fn_abi. fixed_count != caller_fn_abi. fixed_count {
1048
+ throw_ub_format ! (
1049
+ "ABI mismatch: expected {} arguments, found {} arguments " ,
1050
+ callee_fn_abi. fixed_count,
1051
+ caller_fn_abi. fixed_count
1052
+ ) ;
1053
+ }
1054
+
1055
+ if callee_fn_abi. can_unwind && !caller_fn_abi. can_unwind {
1056
+ throw_ub_format ! (
1057
+ "ABI mismatch: callee may unwind, but caller-side signature prohibits unwinding" ,
1058
+ ) ;
1059
+ }
1060
+
1061
+ if !this. check_argument_compat ( & caller_fn_abi. ret , & callee_fn_abi. ret ) ? {
1062
+ throw_ub ! ( AbiMismatchReturn {
1063
+ caller_ty: caller_fn_abi. ret. layout. ty,
1064
+ callee_ty: callee_fn_abi. ret. layout. ty
1065
+ } ) ;
1066
+ }
1067
+
1068
+ if let Some ( index) = caller_fn_abi
1069
+ . args
1070
+ . iter ( )
1071
+ . zip ( callee_fn_abi. args . iter ( ) )
1072
+ . map ( |( caller_arg, callee_arg) | this. check_argument_compat ( caller_arg, callee_arg) )
1073
+ . collect :: < InterpResult < ' tcx , Vec < bool > > > ( ) ?
1074
+ . into_iter ( )
1075
+ . position ( |b| !b)
1076
+ {
1077
+ throw_ub ! ( AbiMismatchArgument {
1078
+ caller_ty: caller_fn_abi. args[ index] . layout. ty,
1079
+ callee_ty: callee_fn_abi. args[ index] . layout. ty
1080
+ } ) ;
1081
+ }
1082
+
1083
+ if let Ok ( ops) = caller_args. try_into ( ) {
1084
+ return interp_ok ( ops) ;
1085
+ }
1086
+ unreachable ! ( )
1087
+ }
1088
+
1018
1089
/// Check shim for variadic function.
1019
1090
/// Returns a tuple that consisting of an array of fixed args, and a slice of varargs.
1020
1091
fn check_shim_variadic < ' a , const N : usize > (
0 commit comments