Skip to content

Commit 729092c

Browse files
committed
Mir: Add TerminatorKind::Abort and generate one for foreign functions
Fixes rust-lang#18510
1 parent b167fc0 commit 729092c

File tree

16 files changed

+62
-3
lines changed

16 files changed

+62
-3
lines changed

src/librustc/ich/impls_mir.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ for mir::Terminator<'gcx> {
5454
mir::TerminatorKind::Goto { .. } |
5555
mir::TerminatorKind::SwitchInt { .. } |
5656
mir::TerminatorKind::Resume |
57+
mir::TerminatorKind::Abort |
5758
mir::TerminatorKind::Return |
5859
mir::TerminatorKind::GeneratorDrop |
5960
mir::TerminatorKind::Unreachable |
@@ -148,6 +149,7 @@ for mir::TerminatorKind<'gcx> {
148149
targets.hash_stable(hcx, hasher);
149150
}
150151
mir::TerminatorKind::Resume |
152+
mir::TerminatorKind::Abort |
151153
mir::TerminatorKind::Return |
152154
mir::TerminatorKind::GeneratorDrop |
153155
mir::TerminatorKind::Unreachable => {}

src/librustc/mir/mod.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -575,6 +575,10 @@ pub enum TerminatorKind<'tcx> {
575575
/// continue. Emitted by build::scope::diverge_cleanup.
576576
Resume,
577577

578+
/// Indicates that the landing pad is finished and that the process
579+
/// should abort. Used to prevent unwinding for foreign items.
580+
Abort,
581+
578582
/// Indicates a normal return. The return pointer lvalue should
579583
/// have been filled in by now. This should occur at most once.
580584
Return,
@@ -660,7 +664,7 @@ impl<'tcx> TerminatorKind<'tcx> {
660664
match *self {
661665
Goto { target: ref b } => slice::ref_slice(b).into_cow(),
662666
SwitchInt { targets: ref b, .. } => b[..].into_cow(),
663-
Resume | GeneratorDrop => (&[]).into_cow(),
667+
Resume | Abort | GeneratorDrop => (&[]).into_cow(),
664668
Return => (&[]).into_cow(),
665669
Unreachable => (&[]).into_cow(),
666670
Call { destination: Some((_, t)), cleanup: Some(c), .. } => vec![t, c].into_cow(),
@@ -690,7 +694,7 @@ impl<'tcx> TerminatorKind<'tcx> {
690694
match *self {
691695
Goto { target: ref mut b } => vec![b],
692696
SwitchInt { targets: ref mut b, .. } => b.iter_mut().collect(),
693-
Resume | GeneratorDrop => Vec::new(),
697+
Resume | Abort | GeneratorDrop => Vec::new(),
694698
Return => Vec::new(),
695699
Unreachable => Vec::new(),
696700
Call { destination: Some((_, ref mut t)), cleanup: Some(ref mut c), .. } => vec![t, c],
@@ -780,6 +784,7 @@ impl<'tcx> TerminatorKind<'tcx> {
780784
Return => write!(fmt, "return"),
781785
GeneratorDrop => write!(fmt, "generator_drop"),
782786
Resume => write!(fmt, "resume"),
787+
Abort => write!(fmt, "abort"),
783788
Yield { ref value, .. } => write!(fmt, "_1 = suspend({:?})", value),
784789
Unreachable => write!(fmt, "unreachable"),
785790
Drop { ref location, .. } => write!(fmt, "drop({:?})", location),
@@ -831,7 +836,7 @@ impl<'tcx> TerminatorKind<'tcx> {
831836
pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
832837
use self::TerminatorKind::*;
833838
match *self {
834-
Return | Resume | Unreachable | GeneratorDrop => vec![],
839+
Return | Resume | Abort | Unreachable | GeneratorDrop => vec![],
835840
Goto { .. } => vec!["".into()],
836841
SwitchInt { ref values, .. } => {
837842
values.iter()
@@ -1806,6 +1811,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
18061811
},
18071812
GeneratorDrop => GeneratorDrop,
18081813
Resume => Resume,
1814+
Abort => Abort,
18091815
Return => Return,
18101816
Unreachable => Unreachable,
18111817
};
@@ -1845,6 +1851,7 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
18451851
},
18461852
Goto { .. } |
18471853
Resume |
1854+
Abort |
18481855
Return |
18491856
GeneratorDrop |
18501857
Unreachable => false

src/librustc/mir/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,7 @@ macro_rules! make_mir_visitor {
431431
}
432432

433433
TerminatorKind::Resume |
434+
TerminatorKind::Abort |
434435
TerminatorKind::Return |
435436
TerminatorKind::GeneratorDrop |
436437
TerminatorKind::Unreachable => {

src/librustc_mir/borrow_check.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> DataflowResultsConsumer<'b, 'gcx>
291291

292292
TerminatorKind::Goto { target: _ } |
293293
TerminatorKind::Resume |
294+
TerminatorKind::Abort |
294295
TerminatorKind::Return |
295296
TerminatorKind::GeneratorDrop |
296297
TerminatorKind::Unreachable => {

src/librustc_mir/build/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,10 +378,27 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
378378
let arg_scope = region::Scope::Arguments(body.value.hir_id.local_id);
379379
let mut block = START_BLOCK;
380380
let source_info = builder.source_info(span);
381+
381382
unpack!(block = builder.in_scope((call_site_scope, source_info), block, |builder| {
383+
384+
// According to rustc_trans/callee we mark all foreign instances with nounwind,
385+
// so let's make sure we don't unwind.
386+
// Therefore generate an extra "Abort" landing pad.
387+
388+
// This does not work :-(
389+
// let is_foreign = tcx.is_foreign_item(tcx.hir.local_def_id(fn_id));
390+
let is_foreign = match abi {
391+
Abi::Rust | Abi::RustCall | Abi::RustIntrinsic => false,
392+
_ => true,
393+
};
394+
if is_foreign && !tcx.sess.no_landing_pads() {
395+
builder.schedule_abort();
396+
};
397+
382398
unpack!(block = builder.in_scope((arg_scope, source_info), block, |builder| {
383399
builder.args_and_body(block, &arguments, arg_scope, &body.value)
384400
}));
401+
385402
// Attribute epilogue to function's closing brace
386403
let fn_end = span.with_lo(span.hi());
387404
let source_info = builder.source_info(fn_end);

src/librustc_mir/build/scope.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
563563
}
564564
}
565565

566+
pub fn schedule_abort(&mut self) -> BasicBlock {
567+
self.scopes[0].needs_cleanup = true;
568+
let abortblk = self.cfg.start_new_cleanup_block();
569+
self.cfg.terminate(abortblk, self.scopes[0].source_info(self.fn_span), TerminatorKind::Abort);
570+
self.cached_resume_block = Some(abortblk);
571+
abortblk
572+
}
573+
566574
// Scheduling drops
567575
// ================
568576
/// Indicates that `lvalue` should be dropped on exit from

src/librustc_mir/dataflow/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D> where D: BitDenotation
676676
{
677677
match bb_data.terminator().kind {
678678
mir::TerminatorKind::Return |
679+
mir::TerminatorKind::Abort |
679680
mir::TerminatorKind::Resume |
680681
mir::TerminatorKind::GeneratorDrop |
681682
mir::TerminatorKind::Unreachable => {}

src/librustc_mir/dataflow/move_paths/builder.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
263263
match term.kind {
264264
TerminatorKind::Goto { target: _ } |
265265
TerminatorKind::Resume |
266+
TerminatorKind::Abort |
266267
TerminatorKind::GeneratorDrop |
267268
TerminatorKind::Unreachable => { }
268269

src/librustc_mir/transform/inline.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,9 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> {
713713
*kind = TerminatorKind::Goto { target: tgt }
714714
}
715715
}
716+
TerminatorKind::Abort => {
717+
unimplemented!("I assume here's where we're supposed to insert a call to intrinsics::abort?");
718+
}
716719
TerminatorKind::Unreachable => { }
717720
}
718721
}

src/librustc_mir/transform/no_landing_pads.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
4141
match terminator.kind {
4242
TerminatorKind::Goto { .. } |
4343
TerminatorKind::Resume |
44+
TerminatorKind::Abort |
4445
TerminatorKind::Return |
4546
TerminatorKind::Unreachable |
4647
TerminatorKind::GeneratorDrop |

src/librustc_mir/transform/qualify_consts.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -315,6 +315,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
315315
TerminatorKind::SwitchInt {..} |
316316
TerminatorKind::DropAndReplace { .. } |
317317
TerminatorKind::Resume |
318+
TerminatorKind::Abort |
318319
TerminatorKind::GeneratorDrop |
319320
TerminatorKind::Yield { .. } |
320321
TerminatorKind::Unreachable => None,

src/librustc_mir/transform/type_check.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -438,6 +438,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
438438
match term.kind {
439439
TerminatorKind::Goto { .. } |
440440
TerminatorKind::Resume |
441+
TerminatorKind::Abort |
441442
TerminatorKind::Return |
442443
TerminatorKind::GeneratorDrop |
443444
TerminatorKind::Unreachable |
@@ -643,6 +644,11 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
643644
span_mirbug!(self, block, "resume on non-cleanup block!")
644645
}
645646
}
647+
TerminatorKind::Abort => {
648+
if !is_cleanup {
649+
span_mirbug!(self, block, "abort on non-cleanup block!")
650+
}
651+
}
646652
TerminatorKind::Return => {
647653
if is_cleanup {
648654
span_mirbug!(self, block, "return on cleanup block")

src/librustc_passes/mir_stats.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
113113
TerminatorKind::Goto { .. } => "TerminatorKind::Goto",
114114
TerminatorKind::SwitchInt { .. } => "TerminatorKind::SwitchInt",
115115
TerminatorKind::Resume => "TerminatorKind::Resume",
116+
TerminatorKind::Abort => "TerminatorKind::Abort",
116117
TerminatorKind::Return => "TerminatorKind::Return",
117118
TerminatorKind::Unreachable => "TerminatorKind::Unreachable",
118119
TerminatorKind::Drop { .. } => "TerminatorKind::Drop",

src/librustc_trans/collector.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
615615
mir::TerminatorKind::Goto { .. } |
616616
mir::TerminatorKind::SwitchInt { .. } |
617617
mir::TerminatorKind::Resume |
618+
mir::TerminatorKind::Abort |
618619
mir::TerminatorKind::Return |
619620
mir::TerminatorKind::Unreachable |
620621
mir::TerminatorKind::Assert { .. } => {}

src/librustc_trans/mir/analyze.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,7 @@ pub fn cleanup_kinds<'a, 'tcx>(mir: &mir::Mir<'tcx>) -> IndexVec<mir::BasicBlock
217217
match data.terminator().kind {
218218
TerminatorKind::Goto { .. } |
219219
TerminatorKind::Resume |
220+
TerminatorKind::Abort |
220221
TerminatorKind::Return |
221222
TerminatorKind::GeneratorDrop |
222223
TerminatorKind::Unreachable |

src/librustc_trans/mir/block.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,13 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
170170

171171
self.set_debug_loc(&bcx, terminator.source_info);
172172
match terminator.kind {
173+
mir::TerminatorKind::Abort => {
174+
// Call core::intrinsics::abort()
175+
let fnname = bcx.ccx.get_intrinsic(&("llvm.trap"));
176+
bcx.call(fnname, &[], None);
177+
bcx.unreachable();
178+
}
179+
173180
mir::TerminatorKind::Resume => {
174181
if let Some(cleanup_pad) = cleanup_pad {
175182
bcx.cleanup_ret(cleanup_pad, None);

0 commit comments

Comments
 (0)