};
use rustc_span::def_id::DefId;
+#[derive(Copy, Clone, Debug)]
enum EdgeKind {
Unwind,
Normal,
);
}
- fn check_bb(&self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {
+ fn check_edge(&self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {
if let Some(bb) = self.body.basic_blocks().get(bb) {
let src = self.body.basic_blocks().get(location.block).unwrap();
match (src.is_cleanup, bb.is_cleanup, edge_kind) {
_ => {
self.fail(
location,
- format!("encountered jump that does not respect unwind invariants {:?}", bb)
+ format!(
+ "{:?} edge to {:?} violates unwind invariants (cleanup {:?} -> {:?})",
+ edge_kind,
+ bb,
+ src.is_cleanup,
+ bb.is_cleanup,
+ )
)
}
}
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) {
match &terminator.kind {
TerminatorKind::Goto { target } => {
- self.check_bb(location, *target, EdgeKind::Normal);
+ self.check_edge(location, *target, EdgeKind::Normal);
}
TerminatorKind::SwitchInt { targets, values, .. } => {
if targets.len() != values.len() + 1 {
);
}
for target in targets {
- self.check_bb(location, *target, EdgeKind::Normal);
+ self.check_edge(location, *target, EdgeKind::Normal);
}
}
TerminatorKind::Drop { target, unwind, .. } => {
- self.check_bb(location, *target, EdgeKind::Normal);
+ self.check_edge(location, *target, EdgeKind::Normal);
if let Some(unwind) = unwind {
- self.check_bb(location, *unwind, EdgeKind::Unwind);
+ self.check_edge(location, *unwind, EdgeKind::Unwind);
}
}
TerminatorKind::DropAndReplace { target, unwind, .. } => {
- self.check_bb(location, *target, EdgeKind::Normal);
+ self.check_edge(location, *target, EdgeKind::Normal);
if let Some(unwind) = unwind {
- self.check_bb(location, *unwind, EdgeKind::Unwind);
+ self.check_edge(location, *unwind, EdgeKind::Unwind);
}
}
TerminatorKind::Call { func, destination, cleanup, .. } => {
),
}
if let Some((_, target)) = destination {
- self.check_bb(location, *target, EdgeKind::Normal);
+ self.check_edge(location, *target, EdgeKind::Normal);
}
if let Some(cleanup) = cleanup {
- self.check_bb(location, *cleanup, EdgeKind::Unwind);
+ self.check_edge(location, *cleanup, EdgeKind::Unwind);
}
}
TerminatorKind::Assert { cond, target, cleanup, .. } => {
),
);
}
- self.check_bb(location, *target, EdgeKind::Normal);
+ self.check_edge(location, *target, EdgeKind::Normal);
if let Some(cleanup) = cleanup {
- self.check_bb(location, *cleanup, EdgeKind::Unwind);
+ self.check_edge(location, *cleanup, EdgeKind::Unwind);
}
}
TerminatorKind::Yield { resume, drop, .. } => {
- self.check_bb(location, *resume, EdgeKind::Normal);
+ self.check_edge(location, *resume, EdgeKind::Normal);
if let Some(drop) = drop {
- self.check_bb(location, *drop, EdgeKind::Normal);
+ self.check_edge(location, *drop, EdgeKind::Normal);
}
}
TerminatorKind::FalseEdge { real_target, imaginary_target } => {
- self.check_bb(location, *real_target, EdgeKind::Normal);
- self.check_bb(location, *imaginary_target, EdgeKind::Normal);
+ self.check_edge(location, *real_target, EdgeKind::Normal);
+ self.check_edge(location, *imaginary_target, EdgeKind::Normal);
}
TerminatorKind::FalseUnwind { real_target, unwind } => {
- self.check_bb(location, *real_target, EdgeKind::Normal);
+ self.check_edge(location, *real_target, EdgeKind::Normal);
if let Some(unwind) = unwind {
- self.check_bb(location, *unwind, EdgeKind::Unwind);
+ self.check_edge(location, *unwind, EdgeKind::Unwind);
}
}
TerminatorKind::InlineAsm { destination, .. } => {
if let Some(destination) = destination {
- self.check_bb(location, *destination, EdgeKind::Normal);
+ self.check_edge(location, *destination, EdgeKind::Normal);
}
}
// Nothing to validate for these.