Skip to content

Commit

Permalink
Mir: Add TerminatorKind::Abort and generate one for foreign functions
Browse files Browse the repository at this point in the history
  • Loading branch information
diwic committed Oct 7, 2017
1 parent b167fc0 commit 729092c
Show file tree
Hide file tree
Showing 16 changed files with 62 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/librustc/ich/impls_mir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ for mir::Terminator<'gcx> {
mir::TerminatorKind::Goto { .. } |
mir::TerminatorKind::SwitchInt { .. } |
mir::TerminatorKind::Resume |
mir::TerminatorKind::Abort |
mir::TerminatorKind::Return |
mir::TerminatorKind::GeneratorDrop |
mir::TerminatorKind::Unreachable |
Expand Down Expand Up @@ -148,6 +149,7 @@ for mir::TerminatorKind<'gcx> {
targets.hash_stable(hcx, hasher);
}
mir::TerminatorKind::Resume |
mir::TerminatorKind::Abort |
mir::TerminatorKind::Return |
mir::TerminatorKind::GeneratorDrop |
mir::TerminatorKind::Unreachable => {}
Expand Down
13 changes: 10 additions & 3 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,10 @@ pub enum TerminatorKind<'tcx> {
/// continue. Emitted by build::scope::diverge_cleanup.
Resume,

/// Indicates that the landing pad is finished and that the process
/// should abort. Used to prevent unwinding for foreign items.
Abort,

/// Indicates a normal return. The return pointer lvalue should
/// have been filled in by now. This should occur at most once.
Return,
Expand Down Expand Up @@ -660,7 +664,7 @@ impl<'tcx> TerminatorKind<'tcx> {
match *self {
Goto { target: ref b } => slice::ref_slice(b).into_cow(),
SwitchInt { targets: ref b, .. } => b[..].into_cow(),
Resume | GeneratorDrop => (&[]).into_cow(),
Resume | Abort | GeneratorDrop => (&[]).into_cow(),
Return => (&[]).into_cow(),
Unreachable => (&[]).into_cow(),
Call { destination: Some((_, t)), cleanup: Some(c), .. } => vec![t, c].into_cow(),
Expand Down Expand Up @@ -690,7 +694,7 @@ impl<'tcx> TerminatorKind<'tcx> {
match *self {
Goto { target: ref mut b } => vec![b],
SwitchInt { targets: ref mut b, .. } => b.iter_mut().collect(),
Resume | GeneratorDrop => Vec::new(),
Resume | Abort | GeneratorDrop => Vec::new(),
Return => Vec::new(),
Unreachable => Vec::new(),
Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut c), .. } => vec![t, c],
Expand Down Expand Up @@ -780,6 +784,7 @@ impl<'tcx> TerminatorKind<'tcx> {
Return => write!(fmt, "return"),
GeneratorDrop => write!(fmt, "generator_drop"),
Resume => write!(fmt, "resume"),
Abort => write!(fmt, "abort"),
Yield { ref value, .. } => write!(fmt, "_1 = suspend({:?})", value),
Unreachable => write!(fmt, "unreachable"),
Drop { ref location, .. } => write!(fmt, "drop({:?})", location),
Expand Down Expand Up @@ -831,7 +836,7 @@ impl<'tcx> TerminatorKind<'tcx> {
pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
use self::TerminatorKind::*;
match *self {
Return | Resume | Unreachable | GeneratorDrop => vec![],
Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
Goto { .. } => vec!["".into()],
SwitchInt { ref values, .. } => {
values.iter()
Expand Down Expand Up @@ -1806,6 +1811,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
},
GeneratorDrop => GeneratorDrop,
Resume => Resume,
Abort => Abort,
Return => Return,
Unreachable => Unreachable,
};
Expand Down Expand Up @@ -1845,6 +1851,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
},
Goto { .. } |
Resume |
Abort |
Return |
GeneratorDrop |
Unreachable => false
Expand Down
1 change: 1 addition & 0 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,7 @@ macro_rules! make_mir_visitor {
}

TerminatorKind::Resume |
TerminatorKind::Abort |
TerminatorKind::Return |
TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable => {
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/borrow_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>

TerminatorKind::Goto { target: _ } |
TerminatorKind::Resume |
TerminatorKind::Abort |
TerminatorKind::Return |
TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable => {
Expand Down
17 changes: 17 additions & 0 deletions src/librustc_mir/build/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,10 +378,27 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
let arg_scope = region::Scope::Arguments(body.value.hir_id.local_id);
let mut block = START_BLOCK;
let source_info = builder.source_info(span);

unpack!(block = builder.in_scope((call_site_scope, source_info), block, |builder| {

// According to rustc_trans/callee we mark all foreign instances with nounwind,
// so let's make sure we don't unwind.
// Therefore generate an extra "Abort" landing pad.

// This does not work :-(
// let is_foreign = tcx.is_foreign_item(tcx.hir.local_def_id(fn_id));
let is_foreign = match abi {
Abi::Rust | Abi::RustCall | Abi::RustIntrinsic => false,
_ => true,
};
if is_foreign && !tcx.sess.no_landing_pads() {
builder.schedule_abort();
};

unpack!(block = builder.in_scope((arg_scope, source_info), block, |builder| {
builder.args_and_body(block, &arguments, arg_scope, &body.value)
}));

// Attribute epilogue to function's closing brace
let fn_end = span.with_lo(span.hi());
let source_info = builder.source_info(fn_end);
Expand Down
8 changes: 8 additions & 0 deletions src/librustc_mir/build/scope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
}
}

pub fn schedule_abort(&mut self) -> BasicBlock {
self.scopes[0].needs_cleanup = true;
let abortblk = self.cfg.start_new_cleanup_block();
self.cfg.terminate(abortblk, self.scopes[0].source_info(self.fn_span), TerminatorKind::Abort);
self.cached_resume_block = Some(abortblk);
abortblk
}

// Scheduling drops
// ================
/// Indicates that `lvalue` should be dropped on exit from
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/dataflow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
{
match bb_data.terminator().kind {
mir::TerminatorKind::Return |
mir::TerminatorKind::Abort |
mir::TerminatorKind::Resume |
mir::TerminatorKind::GeneratorDrop |
mir::TerminatorKind::Unreachable => {}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/dataflow/move_paths/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
match term.kind {
TerminatorKind::Goto { target: _ } |
TerminatorKind::Resume |
TerminatorKind::Abort |
TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable => { }

Expand Down
3 changes: 3 additions & 0 deletions src/librustc_mir/transform/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
*kind = TerminatorKind::Goto { target: tgt }
}
}
TerminatorKind::Abort => {
unimplemented!("I assume here's where we're supposed to insert a call to intrinsics::abort?");
}
TerminatorKind::Unreachable => { }
}
}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/transform/no_landing_pads.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
match terminator.kind {
TerminatorKind::Goto { .. } |
TerminatorKind::Resume |
TerminatorKind::Abort |
TerminatorKind::Return |
TerminatorKind::Unreachable |
TerminatorKind::GeneratorDrop |
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/transform/qualify_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
TerminatorKind::SwitchInt {..} |
TerminatorKind::DropAndReplace { .. } |
TerminatorKind::Resume |
TerminatorKind::Abort |
TerminatorKind::GeneratorDrop |
TerminatorKind::Yield { .. } |
TerminatorKind::Unreachable => None,
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_mir/transform/type_check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
match term.kind {
TerminatorKind::Goto { .. } |
TerminatorKind::Resume |
TerminatorKind::Abort |
TerminatorKind::Return |
TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable |
Expand Down Expand Up @@ -643,6 +644,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
span_mirbug!(self, block, "resume on non-cleanup block!")
}
}
TerminatorKind::Abort => {
if !is_cleanup {
span_mirbug!(self, block, "abort on non-cleanup block!")
}
}
TerminatorKind::Return => {
if is_cleanup {
span_mirbug!(self, block, "return on cleanup block")
Expand Down
1 change: 1 addition & 0 deletions src/librustc_passes/mir_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
TerminatorKind::Goto { .. } => "TerminatorKind::Goto",
TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt",
TerminatorKind::Resume => "TerminatorKind::Resume",
TerminatorKind::Abort => "TerminatorKind::Abort",
TerminatorKind::Return => "TerminatorKind::Return",
TerminatorKind::Unreachable => "TerminatorKind::Unreachable",
TerminatorKind::Drop { .. } => "TerminatorKind::Drop",
Expand Down
1 change: 1 addition & 0 deletions src/librustc_trans/collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
mir::TerminatorKind::Goto { .. } |
mir::TerminatorKind::SwitchInt { .. } |
mir::TerminatorKind::Resume |
mir::TerminatorKind::Abort |
mir::TerminatorKind::Return |
mir::TerminatorKind::Unreachable |
mir::TerminatorKind::Assert { .. } => {}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_trans/mir/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock
match data.terminator().kind {
TerminatorKind::Goto { .. } |
TerminatorKind::Resume |
TerminatorKind::Abort |
TerminatorKind::Return |
TerminatorKind::GeneratorDrop |
TerminatorKind::Unreachable |
Expand Down
7 changes: 7 additions & 0 deletions src/librustc_trans/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,13 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {

self.set_debug_loc(&bcx, terminator.source_info);
match terminator.kind {
mir::TerminatorKind::Abort => {
// Call core::intrinsics::abort()
let fnname = bcx.ccx.get_intrinsic(&("llvm.trap"));
bcx.call(fnname, &[], None);
bcx.unreachable();
}

mir::TerminatorKind::Resume => {
if let Some(cleanup_pad) = cleanup_pad {
bcx.cleanup_ret(cleanup_pad, None);
Expand Down

0 comments on commit 729092c

Please sign in to comment.