@@ -20,6 +20,8 @@ use rustc_mir_dataflow::{Analysis, ResultsCursor};
20
20
use rustc_target:: abi:: { Size , FIRST_VARIANT } ;
21
21
use rustc_target:: spec:: abi:: Abi ;
22
22
23
+ use crate :: util:: is_within_packed;
24
+
23
25
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
24
26
enum EdgeKind {
25
27
Unwind ,
@@ -93,6 +95,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
93
95
cfg_checker. visit_body ( body) ;
94
96
cfg_checker. check_cleanup_control_flow ( ) ;
95
97
98
+ // Also run the TypeChecker.
96
99
for ( location, msg) in validate_types ( tcx, self . mir_phase , param_env, body) {
97
100
cfg_checker. fail ( location, msg) ;
98
101
}
@@ -418,22 +421,42 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
418
421
self . check_unwind_edge ( location, * unwind) ;
419
422
420
423
// The call destination place and Operand::Move place used as an argument might be
421
- // passed by a reference to the callee. Consequently they must be non-overlapping.
422
- // Currently this simply checks for duplicate places.
424
+ // passed by a reference to the callee. Consequently they must be non-overlapping
425
+ // and cannot be packed. Currently this simply checks for duplicate places.
423
426
self . place_cache . clear ( ) ;
424
427
self . place_cache . insert ( destination. as_ref ( ) ) ;
428
+ if is_within_packed ( self . tcx , & self . body . local_decls , * destination) . is_some ( ) {
429
+ // This is bad! The callee will expect the memory to be aligned.
430
+ self . fail (
431
+ location,
432
+ format ! (
433
+ "encountered packed place in `Call` terminator destination: {:?}" ,
434
+ terminator. kind,
435
+ ) ,
436
+ ) ;
437
+ }
425
438
let mut has_duplicates = false ;
426
439
for arg in args {
427
440
if let Operand :: Move ( place) = arg {
428
441
has_duplicates |= !self . place_cache . insert ( place. as_ref ( ) ) ;
442
+ if is_within_packed ( self . tcx , & self . body . local_decls , * place) . is_some ( ) {
443
+ // This is bad! The callee will expect the memory to be aligned.
444
+ self . fail (
445
+ location,
446
+ format ! (
447
+ "encountered `Move` of a packed place in `Call` terminator: {:?}" ,
448
+ terminator. kind,
449
+ ) ,
450
+ ) ;
451
+ }
429
452
}
430
453
}
431
454
432
455
if has_duplicates {
433
456
self . fail (
434
457
location,
435
458
format ! (
436
- "encountered overlapping memory in `Call` terminator: {:?}" ,
459
+ "encountered overlapping memory in `Move` arguments to ` Call` terminator: {:?}" ,
437
460
terminator. kind,
438
461
) ,
439
462
) ;
@@ -532,6 +555,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
532
555
}
533
556
}
534
557
558
+ /// A faster version of the validation pass that only checks those things which may break when apply
559
+ /// generic substitutions.
535
560
pub fn validate_types < ' tcx > (
536
561
tcx : TyCtxt < ' tcx > ,
537
562
mir_phase : MirPhase ,
0 commit comments