@@ -14,7 +14,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1414use rustc_middle:: middle:: dependency_format:: Linkage ;
1515use rustc_middle:: middle:: exported_symbols:: ExportedSymbol ;
1616use 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 } ;
1818use rustc_session:: config:: CrateType ;
1919use rustc_span:: { Span , Symbol } ;
2020use rustc_target:: callconv:: { Conv , FnAbi } ;
@@ -994,10 +994,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
994994 exp_abi : Conv ,
995995 link_name : Symbol ,
996996 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 ] > {
1001998 self . check_abi_and_shim_symbol_clash ( abi, exp_abi, link_name) ?;
1002999
10031000 if abi. c_variadic {
@@ -1015,6 +1012,80 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
10151012 )
10161013 }
10171014
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+
10181089 /// Check shim for variadic function.
10191090 /// Returns a tuple that consisting of an array of fixed args, and a slice of varargs.
10201091 fn check_shim_variadic < ' a , const N : usize > (
0 commit comments