@@ -10,7 +10,7 @@ use rustc_middle::{
10
10
Instance , Ty ,
11
11
} ,
12
12
} ;
13
- use rustc_target:: abi:: call:: { ArgAbi , ArgAttribute , ArgAttributes , FnAbi , PassMode } ;
13
+ use rustc_target:: abi:: call:: { ArgAbi , FnAbi , PassMode } ;
14
14
use rustc_target:: abi:: { self , FieldIdx } ;
15
15
use rustc_target:: spec:: abi:: Abi ;
16
16
@@ -291,32 +291,17 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
291
291
return true ;
292
292
}
293
293
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.
300
296
// NOTE: this is *not* a stable guarantee! It just reflects a property of our current
301
297
// ABIs. It's also fragile; the same pair of types might be considered ABI-compatible
302
298
// when used directly by-value but not considered compatible as a struct field or array
303
299
// 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 )
306
302
}
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.
320
305
// (The latter part is needed to ensure e.g. that `struct Zst` is compatible with `struct Wrap((), Zst)`.)
321
306
// This is conservative, but also means that our check isn't quite so heavily dependent on the `PassMode`,
322
307
// 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> {
329
314
== self . unfold_transparent ( callee_layout) . ty
330
315
}
331
316
}
332
- // What remains is `Abi::Uninhabited` (which can never be passed anyway) and
333
- // mismatching ABIs, that should all be rejected.
334
- _ => false ,
335
317
}
336
318
}
337
319
@@ -340,54 +322,18 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
340
322
caller_abi : & ArgAbi < ' tcx , Ty < ' tcx > > ,
341
323
callee_abi : & ArgAbi < ' tcx , Ty < ' tcx > > ,
342
324
) -> 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
-
377
325
// Ideally `PassMode` would capture everything there is about argument passing, but that is
378
326
// not the case: in `FnAbi::llvm_type`, also parts of the layout and type information are
379
327
// used. So we need to check that *both* sufficiently agree to ensures the arguments are
380
328
// compatible.
381
329
// For instance, `layout_compat` is needed to reject `i32` vs `f32`, which is not reflected
382
330
// in `PassMode`. `mode_compat` is needed to reject `u8` vs `bool`, which have the same
383
331
// `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. abi_eq( & callee_abi. layout) ) ;
391
337
return true ;
392
338
} else {
393
339
trace ! (
0 commit comments