1
Fork 0

Add UnwindAction::Unreachable

This also makes eval machine's `StackPopUnwind`
redundant so that is replaced.
This commit is contained in:
Gary Guo 2022-10-10 19:50:49 +01:00
parent daeb844e0c
commit 5e6ed132fa
23 changed files with 160 additions and 149 deletions

View file

@ -12,6 +12,8 @@ pub struct MirPatch<'tcx> {
new_statements: Vec<(Location, StatementKind<'tcx>)>,
new_locals: Vec<LocalDecl<'tcx>>,
resume_block: Option<BasicBlock>,
// Only for unreachable in cleanup path.
unreachable_block: Option<BasicBlock>,
body_span: Span,
next_local: usize,
}
@ -25,11 +27,12 @@ impl<'tcx> MirPatch<'tcx> {
new_locals: vec![],
next_local: body.local_decls.len(),
resume_block: None,
unreachable_block: None,
body_span: body.span,
};
// Check if we already have a resume block
for (bb, block) in body.basic_blocks.iter_enumerated() {
// Check if we already have a resume block
if let TerminatorKind::Resume = block.terminator().kind && block.statements.is_empty() {
result.resume_block = Some(bb);
break;

View file

@ -753,12 +753,17 @@ pub enum TerminatorKind<'tcx> {
}
/// Action to be taken when a stack unwind happens.
#[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)]
#[derive(TypeFoldable, TypeVisitable)]
pub enum UnwindAction {
// No action is to be taken. Continue unwinding.
/// No action is to be taken. Continue unwinding.
///
/// This is similar to `Cleanup(bb)` where `bb` does nothing but `Resume`, but they are not
/// equivalent, as presence of `Cleanup(_)` will make a frame non-POF.
Continue,
// Cleanups to be done.
/// Triggers undefined behavior if unwind happens.
Unreachable,
/// Cleanups to be done.
Cleanup(BasicBlock),
}

View file

@ -270,11 +270,16 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
let labels = self.fmt_successor_labels();
assert_eq!(successor_count, labels.len());
match successor_count {
0 => Ok(()),
1 => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
let unwind = match self.unwind() {
// Not needed or included in successors
None | Some(UnwindAction::Continue) | Some(UnwindAction::Cleanup(_)) => None,
Some(UnwindAction::Unreachable) => Some("unwind unreachable"),
};
match (successor_count, unwind) {
(0, None) => Ok(()),
(0, Some(unwind)) => write!(fmt, " -> {}", unwind),
(1, None) => write!(fmt, " -> {:?}", self.successors().next().unwrap()),
_ => {
write!(fmt, " -> [")?;
for (i, target) in self.successors().enumerate() {
@ -283,6 +288,9 @@ impl<'tcx> Debug for TerminatorKind<'tcx> {
}
write!(fmt, "{}: {:?}", labels[i], target)?;
}
if let Some(unwind) = unwind {
write!(fmt, ", {unwind}")?;
}
write!(fmt, "]")
}
}
@ -391,30 +399,32 @@ impl<'tcx> TerminatorKind<'tcx> {
Call { target: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
vec!["return".into(), "unwind".into()]
}
Call { target: Some(_), unwind: UnwindAction::Continue, .. } => vec!["return".into()],
Call { target: Some(_), unwind: _, .. } => vec!["return".into()],
Call { target: None, unwind: UnwindAction::Cleanup(_), .. } => vec!["unwind".into()],
Call { target: None, unwind: UnwindAction::Continue, .. } => vec![],
Call { target: None, unwind: _, .. } => vec![],
Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()],
Yield { drop: None, .. } => vec!["resume".into()],
Drop { unwind: UnwindAction::Continue, .. } => vec!["return".into()],
Drop { unwind: UnwindAction::Cleanup(_), .. } => vec!["return".into(), "unwind".into()],
Assert { unwind: UnwindAction::Continue, .. } => vec!["".into()],
Assert { .. } => vec!["success".into(), "unwind".into()],
Drop { unwind: _, .. } => vec!["return".into()],
Assert { unwind: UnwindAction::Cleanup(_), .. } => {
vec!["success".into(), "unwind".into()]
}
Assert { unwind: _, .. } => vec!["success".into()],
FalseEdge { .. } => vec!["real".into(), "imaginary".into()],
FalseUnwind { unwind: UnwindAction::Cleanup(_), .. } => {
vec!["real".into(), "cleanup".into()]
vec!["real".into(), "unwind".into()]
}
FalseUnwind { unwind: UnwindAction::Continue, .. } => vec!["real".into()],
FalseUnwind { unwind: _, .. } => vec!["real".into()],
InlineAsm { destination: Some(_), unwind: UnwindAction::Cleanup(_), .. } => {
vec!["return".into(), "unwind".into()]
}
InlineAsm { destination: Some(_), unwind: UnwindAction::Continue, .. } => {
InlineAsm { destination: Some(_), unwind: _, .. } => {
vec!["return".into()]
}
InlineAsm { destination: None, unwind: UnwindAction::Cleanup(_), .. } => {
vec!["unwind".into()]
}
InlineAsm { destination: None, unwind: UnwindAction::Continue, .. } => vec![],
InlineAsm { destination: None, unwind: _, .. } => vec![],
}
}
}