@@ -10,7 +10,7 @@ use rustc_middle::{
1010 Instance , Ty ,
1111 } ,
1212} ;
13- use rustc_target:: abi:: call:: { ArgAbi , ArgAttribute , ArgAttributes , FnAbi , PassMode } ;
13+ use rustc_target:: abi:: call:: { ArgAbi , FnAbi , PassMode } ;
1414use rustc_target:: abi:: { self , FieldIdx } ;
1515use rustc_target:: spec:: abi:: Abi ;
1616
@@ -291,32 +291,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
291291 return true ;
292292 }
293293
294- match ( caller_layout. abi , callee_layout. abi ) {
295- // If both sides have Scalar/Vector/ScalarPair ABI, we can easily directly compare them.
296- // Different valid ranges are okay (the validity check will complain if this leads to
297- // invalid transmutes). Different signs are *not* okay on some targets (e.g. `extern
298- // "C"` on `s390x` where small integers are passed zero/sign-extended in large
299- // registers), so we generally reject them to increase portability.
294+ match caller_layout. abi {
295+ // For Scalar/Vector/ScalarPair ABI, we directly compare them.
300296 // NOTE: this is *not* a stable guarantee! It just reflects a property of our current
301297 // ABIs. It's also fragile; the same pair of types might be considered ABI-compatible
302298 // when used directly by-value but not considered compatible as a struct field or array
303299 // element.
304- ( abi:: Abi :: Scalar ( caller ) , abi:: Abi :: Scalar ( callee ) ) => {
305- caller . primitive ( ) == callee . primitive ( )
300+ abi:: Abi :: Scalar ( .. ) | abi:: Abi :: ScalarPair ( .. ) | abi :: Abi :: Vector { .. } => {
301+ caller_layout . abi . eq_up_to_validity ( & callee_layout . abi )
306302 }
307- (
308- abi:: Abi :: Vector { element : caller_element, count : caller_count } ,
309- abi:: Abi :: Vector { element : callee_element, count : callee_count } ,
310- ) => {
311- caller_element. primitive ( ) == callee_element. primitive ( )
312- && caller_count == callee_count
313- }
314- ( abi:: Abi :: ScalarPair ( caller1, caller2) , abi:: Abi :: ScalarPair ( callee1, callee2) ) => {
315- caller1. primitive ( ) == callee1. primitive ( )
316- && caller2. primitive ( ) == callee2. primitive ( )
317- }
318- ( abi:: Abi :: Aggregate { .. } , abi:: Abi :: Aggregate { .. } ) => {
319- // Aggregates are compatible only if they newtype-wrap the same type, or if they are both 1-ZST.
303+ _ => {
304+ // Everything else is compatible only if they newtype-wrap the same type, or if they are both 1-ZST.
320305 // (The latter part is needed to ensure e.g. that `struct Zst` is compatible with `struct Wrap((), Zst)`.)
321306 // This is conservative, but also means that our check isn't quite so heavily dependent on the `PassMode`,
322307 // which means having ABI-compatibility on one target is much more likely to imply compatibility for other targets.
@@ -329,9 +314,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
329314 == self . unfold_transparent ( callee_layout) . ty
330315 }
331316 }
332- // What remains is `Abi::Uninhabited` (which can never be passed anyway) and
333- // mismatching ABIs, that should all be rejected.
334- _ => false ,
335317 }
336318 }
337319
@@ -340,54 +322,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
340322 caller_abi : & ArgAbi < ' tcx , Ty < ' tcx > > ,
341323 callee_abi : & ArgAbi < ' tcx , Ty < ' tcx > > ,
342324 ) -> bool {
343- // When comparing the PassMode, we have to be smart about comparing the attributes.
344- let arg_attr_compat = |a1 : & ArgAttributes , a2 : & ArgAttributes | {
345- // There's only one regular attribute that matters for the call ABI: InReg.
346- // Everything else is things like noalias, dereferenceable, nonnull, ...
347- // (This also applies to pointee_size, pointee_align.)
348- if a1. regular . contains ( ArgAttribute :: InReg ) != a2. regular . contains ( ArgAttribute :: InReg )
349- {
350- return false ;
351- }
352- // We also compare the sign extension mode -- this could let the callee make assumptions
353- // about bits that conceptually were not even passed.
354- if a1. arg_ext != a2. arg_ext {
355- return false ;
356- }
357- return true ;
358- } ;
359- let mode_compat = || match ( & caller_abi. mode , & callee_abi. mode ) {
360- ( PassMode :: Ignore , PassMode :: Ignore ) => true , // can still be reached for the return type
361- ( PassMode :: Direct ( a1) , PassMode :: Direct ( a2) ) => arg_attr_compat ( a1, a2) ,
362- ( PassMode :: Pair ( a1, b1) , PassMode :: Pair ( a2, b2) ) => {
363- arg_attr_compat ( a1, a2) && arg_attr_compat ( b1, b2)
364- }
365- ( PassMode :: Cast ( c1, pad1) , PassMode :: Cast ( c2, pad2) ) => c1 == c2 && pad1 == pad2,
366- (
367- PassMode :: Indirect { attrs : a1, extra_attrs : None , on_stack : s1 } ,
368- PassMode :: Indirect { attrs : a2, extra_attrs : None , on_stack : s2 } ,
369- ) => arg_attr_compat ( a1, a2) && s1 == s2,
370- (
371- PassMode :: Indirect { attrs : a1, extra_attrs : Some ( e1) , on_stack : s1 } ,
372- PassMode :: Indirect { attrs : a2, extra_attrs : Some ( e2) , on_stack : s2 } ,
373- ) => arg_attr_compat ( a1, a2) && arg_attr_compat ( e1, e2) && s1 == s2,
374- _ => false ,
375- } ;
376-
377325 // Ideally `PassMode` would capture everything there is about argument passing, but that is
378326 // not the case: in `FnAbi::llvm_type`, also parts of the layout and type information are
379327 // used. So we need to check that *both* sufficiently agree to ensures the arguments are
380328 // compatible.
381329 // For instance, `layout_compat` is needed to reject `i32` vs `f32`, which is not reflected
382330 // in `PassMode`. `mode_compat` is needed to reject `u8` vs `bool`, which have the same
383331 // `abi::Primitive` but different `arg_ext`.
384- if self . layout_compat ( caller_abi. layout , callee_abi. layout ) && mode_compat ( ) {
385- // Something went very wrong if our checks don't even imply that the layout is the same.
386- assert ! (
387- caller_abi. layout. size == callee_abi. layout. size
388- && caller_abi. layout. align. abi == callee_abi. layout. align. abi
389- && caller_abi. layout. is_sized( ) == callee_abi. layout. is_sized( )
390- ) ;
332+ if self . layout_compat ( caller_abi. layout , callee_abi. layout )
333+ && caller_abi. mode . eq_abi ( & callee_abi. mode )
334+ {
335+ // Something went very wrong if our checks don't imply layout ABI compatibility.
336+ assert ! ( caller_abi. layout. eq_abi( & callee_abi. layout) ) ;
391337 return true ;
392338 } else {
393339 trace ! (
0 commit comments