@@ -255,6 +255,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
255255 caller_abi : & ArgAbi < ' tcx , Ty < ' tcx > > ,
256256 callee_abi : & ArgAbi < ' tcx , Ty < ' tcx > > ,
257257 ) -> bool {
258+ let primitive_abi_compat = |a1 : abi:: Primitive , a2 : abi:: Primitive | -> bool {
259+ match ( a1, a2) {
260+ // For integers, ignore the sign.
261+ ( abi:: Primitive :: Int ( int_ty1, _sign1) , abi:: Primitive :: Int ( int_ty2, _sign2) ) => {
262+ int_ty1 == int_ty2
263+ }
264+ // For everything else we require full equality.
265+ _ => a1 == a2,
266+ }
267+ } ;
258268 // Heuristic for type comparison.
259269 let layout_compat = || {
260270 if caller_abi. layout . ty == callee_abi. layout . ty {
@@ -267,28 +277,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
267277 // then who knows what happens.
268278 return false ;
269279 }
270- if caller_abi. layout . size != callee_abi. layout . size
271- || caller_abi. layout . align . abi != callee_abi. layout . align . abi
272- {
273- // This cannot go well...
274- return false ;
275- }
276- // The rest *should* be okay, but we are extra conservative.
280+ // This is tricky. Some ABIs split aggregates up into multiple registers etc, so we have
281+ // to be super careful here. For the scalar ABIs we conveniently already have all the
282+ // newtypes unwrapped etc, so in those cases we can just compare the scalar components.
283+ // Everything else we just reject for now.
277284 match ( caller_abi. layout . abi , callee_abi. layout . abi ) {
278- // Different valid ranges are okay (once we enforce validity,
279- // that will take care to make it UB to leave the range, just
280- // like for transmute).
285+ // Different valid ranges are okay (the validity check will complain if this leads
286+ // to invalid transmutes).
281287 ( abi:: Abi :: Scalar ( caller) , abi:: Abi :: Scalar ( callee) ) => {
282- caller. primitive ( ) == callee. primitive ( )
288+ primitive_abi_compat ( caller. primitive ( ) , callee. primitive ( ) )
283289 }
284290 (
285291 abi:: Abi :: ScalarPair ( caller1, caller2) ,
286292 abi:: Abi :: ScalarPair ( callee1, callee2) ,
287293 ) => {
288- caller1. primitive ( ) == callee1. primitive ( )
289- && caller2. primitive ( ) == callee2. primitive ( )
294+ primitive_abi_compat ( caller1. primitive ( ) , callee1. primitive ( ) )
295+ && primitive_abi_compat ( caller2. primitive ( ) , callee2. primitive ( ) )
290296 }
291- // Be conservative
297+ // Be conservative.
292298 _ => false ,
293299 }
294300 } ;
@@ -309,7 +315,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
309315 return true ;
310316 } ;
311317 let mode_compat = || match ( & caller_abi. mode , & callee_abi. mode ) {
312- ( PassMode :: Ignore , PassMode :: Ignore ) => true ,
318+ ( PassMode :: Ignore , PassMode :: Ignore ) => true , // can still be reached for the return type
313319 ( PassMode :: Direct ( a1) , PassMode :: Direct ( a2) ) => arg_attr_compat ( a1, a2) ,
314320 ( PassMode :: Pair ( a1, b1) , PassMode :: Pair ( a2, b2) ) => {
315321 arg_attr_compat ( a1, a2) && arg_attr_compat ( b1, b2)
@@ -326,7 +332,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
326332 _ => false ,
327333 } ;
328334
335+ // We have to check both. `layout_compat` is needed to reject e.g. `i32` vs `f32`,
336+ // which is not reflected in `PassMode`. `mode_compat` is needed to reject `u8` vs `bool`,
337+ // which have the same `abi::Primitive` but different `arg_ext`.
329338 if layout_compat ( ) && mode_compat ( ) {
339+ // Something went very wrong if our checks don't even imply that the layout is the same.
340+ assert ! (
341+ caller_abi. layout. size == callee_abi. layout. size
342+ && caller_abi. layout. align. abi == callee_abi. layout. align. abi
343+ ) ;
330344 return true ;
331345 }
332346 trace ! (
0 commit comments