@@ -14,9 +14,10 @@ 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
+ use rustc_symbol_mangling:: mangle_internal_symbol;
20
21
use rustc_target:: callconv:: { Conv , FnAbi } ;
21
22
22
23
use crate :: * ;
@@ -994,10 +995,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
994
995
exp_abi : Conv ,
995
996
link_name : Symbol ,
996
997
args : & ' a [ OpTy < ' tcx > ] ,
997
- ) -> InterpResult < ' tcx , & ' a [ OpTy < ' tcx > ; N ] >
998
- where
999
- & ' a [ OpTy < ' tcx > ; N ] : TryFrom < & ' a [ OpTy < ' tcx > ] > ,
1000
- {
998
+ ) -> InterpResult < ' tcx , & ' a [ OpTy < ' tcx > ; N ] > {
1001
999
self . check_abi_and_shim_symbol_clash ( abi, exp_abi, link_name) ?;
1002
1000
1003
1001
if abi. c_variadic {
@@ -1015,6 +1013,80 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
1015
1013
)
1016
1014
}
1017
1015
1016
+ /// Check that the given `caller_fn_abi` matches the expected ABI described by
1017
+ /// `callee_abi`, `callee_input_tys`, `callee_output_ty`, and the return the list of
1018
+ /// arguments.
1019
+ fn check_shim_abi < ' a , const N : usize > (
1020
+ & mut self ,
1021
+ link_name : Symbol ,
1022
+ caller_fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1023
+ callee_abi : ExternAbi ,
1024
+ callee_input_tys : [ Ty < ' tcx > ; N ] ,
1025
+ callee_output_ty : Ty < ' tcx > ,
1026
+ caller_args : & ' a [ OpTy < ' tcx > ] ,
1027
+ ) -> InterpResult < ' tcx , & ' a [ OpTy < ' tcx > ; N ] > {
1028
+ let this = self . eval_context_mut ( ) ;
1029
+ let mut inputs_and_output = callee_input_tys. to_vec ( ) ;
1030
+ inputs_and_output. push ( callee_output_ty) ;
1031
+ let fn_sig_binder = Binder :: dummy ( FnSig {
1032
+ inputs_and_output : this. machine . tcx . mk_type_list ( & inputs_and_output) ,
1033
+ c_variadic : false ,
1034
+ // This does not matter for the ABI.
1035
+ safety : Safety :: Safe ,
1036
+ abi : callee_abi,
1037
+ } ) ;
1038
+ let callee_fn_abi = this. fn_abi_of_fn_ptr ( fn_sig_binder, Default :: default ( ) ) ?;
1039
+
1040
+ this. check_abi_and_shim_symbol_clash ( caller_fn_abi, callee_fn_abi. conv , link_name) ?;
1041
+
1042
+ if caller_fn_abi. c_variadic {
1043
+ throw_ub_format ! (
1044
+ "ABI mismatch: calling a non-variadic function with a variadic caller-side signature"
1045
+ ) ;
1046
+ }
1047
+
1048
+ if callee_fn_abi. fixed_count != caller_fn_abi. fixed_count {
1049
+ throw_ub_format ! (
1050
+ "ABI mismatch: expected {} arguments, found {} arguments " ,
1051
+ callee_fn_abi. fixed_count,
1052
+ caller_fn_abi. fixed_count
1053
+ ) ;
1054
+ }
1055
+
1056
+ if callee_fn_abi. can_unwind && !caller_fn_abi. can_unwind {
1057
+ throw_ub_format ! (
1058
+ "ABI mismatch: callee may unwind, but caller-side signature prohibits unwinding" ,
1059
+ ) ;
1060
+ }
1061
+
1062
+ if !this. check_argument_compat ( & caller_fn_abi. ret , & callee_fn_abi. ret ) ? {
1063
+ throw_ub ! ( AbiMismatchReturn {
1064
+ caller_ty: caller_fn_abi. ret. layout. ty,
1065
+ callee_ty: callee_fn_abi. ret. layout. ty
1066
+ } ) ;
1067
+ }
1068
+
1069
+ if let Some ( index) = caller_fn_abi
1070
+ . args
1071
+ . iter ( )
1072
+ . zip ( callee_fn_abi. args . iter ( ) )
1073
+ . map ( |( caller_arg, callee_arg) | this. check_argument_compat ( caller_arg, callee_arg) )
1074
+ . collect :: < InterpResult < ' tcx , Vec < bool > > > ( ) ?
1075
+ . into_iter ( )
1076
+ . position ( |b| !b)
1077
+ {
1078
+ throw_ub ! ( AbiMismatchArgument {
1079
+ caller_ty: caller_fn_abi. args[ index] . layout. ty,
1080
+ callee_ty: callee_fn_abi. args[ index] . layout. ty
1081
+ } ) ;
1082
+ }
1083
+
1084
+ if let Ok ( ops) = caller_args. try_into ( ) {
1085
+ return interp_ok ( ops) ;
1086
+ }
1087
+ unreachable ! ( )
1088
+ }
1089
+
1018
1090
/// Check shim for variadic function.
1019
1091
/// Returns a tuple that consisting of an array of fixed args, and a slice of varargs.
1020
1092
fn check_shim_variadic < ' a , const N : usize > (
@@ -1187,6 +1259,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
1187
1259
1188
1260
interp_ok ( array)
1189
1261
}
1262
+
1263
+ fn mangle_internal_symbol < ' a > ( & ' a mut self , name : & ' static str ) -> & ' a str
1264
+ where
1265
+ ' tcx : ' a ,
1266
+ {
1267
+ let this = self . eval_context_mut ( ) ;
1268
+ let tcx = * this. tcx ;
1269
+ this. machine
1270
+ . mangle_internal_symbol_cache
1271
+ . entry ( name)
1272
+ . or_insert_with ( || mangle_internal_symbol ( tcx, name) )
1273
+ }
1190
1274
}
1191
1275
1192
1276
impl < ' tcx > MiriMachine < ' tcx > {
0 commit comments