Skip to content

Commit 5ad4673

Browse files
committed
Add a no-landing-pads MIR pass
The pass removes the unwind branch of each terminator, thus moving the responsibility of handling the -Z no-landing-pads flag to a small self-contained pass… instead of polluting the translator.
1 parent 1de70d3 commit 5ad4673

File tree

4 files changed

+59
-8
lines changed

4 files changed

+59
-8
lines changed

src/librustc_mir/mir_map.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ extern crate rustc_front;
2222
use build;
2323
use graphviz;
2424
use pretty;
25-
use transform::simplify_cfg;
25+
use transform::{simplify_cfg, no_landing_pads};
2626
use rustc::dep_graph::DepNode;
2727
use rustc::mir::repr::Mir;
2828
use hair::cx::Cx;
@@ -148,6 +148,10 @@ impl<'a, 'm, 'tcx> Visitor<'tcx> for InnerDump<'a,'m,'tcx> {
148148

149149
match build_mir(Cx::new(&infcx), implicit_arg_tys, id, span, decl, body) {
150150
Ok(mut mir) => {
151+
// FIXME: This should run later rather than earlier (since this is supposed to be a
152+
// codegen option), but we do not want to re-run the whole simplify_cfg pass all
153+
// over again after this pass.
154+
no_landing_pads::NoLandingPads.run_on_mir(&mut mir, self.tcx);
151155
simplify_cfg::SimplifyCfg::new().run_on_mir(&mut mir, self.tcx);
152156

153157
let meta_item_list = self.attr

src/librustc_mir/transform/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@
1010

1111
pub mod simplify_cfg;
1212
pub mod erase_regions;
13+
pub mod no_landing_pads;
1314
mod util;
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
//! This pass removes the unwind branch of all the terminators when the no-landing-pads option is
12+
//! specified.
13+
14+
use rustc::middle::ty;
15+
use rustc::mir::repr::*;
16+
use rustc::mir::visit::MutVisitor;
17+
use rustc::mir::transform::MirPass;
18+
19+
pub struct NoLandingPads;
20+
21+
impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
22+
fn visit_terminator(&mut self, bb: BasicBlock, terminator: &mut Terminator<'tcx>) {
23+
match *terminator {
24+
Terminator::Goto { .. } |
25+
Terminator::Resume |
26+
Terminator::Return |
27+
Terminator::If { .. } |
28+
Terminator::Switch { .. } |
29+
Terminator::SwitchInt { .. } => { /* nothing to do */ },
30+
Terminator::Drop { ref mut unwind, .. } => {
31+
unwind.take();
32+
},
33+
Terminator::Call { ref mut cleanup, .. } => {
34+
cleanup.take();
35+
},
36+
}
37+
self.super_terminator(bb, terminator);
38+
}
39+
}
40+
41+
impl MirPass for NoLandingPads {
42+
fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ty::ctxt<'tcx>) {
43+
if tcx.sess.no_landing_pads() {
44+
self.visit_mir(mir);
45+
}
46+
}
47+
}

src/librustc_trans/trans/mir/block.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,11 +180,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
180180
}
181181
}
182182

183-
let avoid_invoke = bcx.with_block(|bcx| base::avoid_invoke(bcx));
184183
// Many different ways to call a function handled here
185-
match (is_foreign, avoid_invoke, cleanup, destination) {
184+
match (is_foreign, cleanup, destination) {
186185
// The two cases below are the only ones to use LLVM’s `invoke`.
187-
(false, false, &Some(cleanup), &None) => {
186+
(false, &Some(cleanup), &None) => {
188187
let cleanup = self.bcx(cleanup);
189188
let landingpad = self.make_landing_pad(cleanup);
190189
let unreachable_blk = self.unreachable_block();
@@ -195,7 +194,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
195194
None,
196195
Some(attrs));
197196
},
198-
(false, false, &Some(cleanup), &Some((_, success))) => {
197+
(false, &Some(cleanup), &Some((_, success))) => {
199198
let cleanup = self.bcx(cleanup);
200199
let landingpad = self.make_landing_pad(cleanup);
201200
let (target, postinvoke) = if must_copy_dest {
@@ -242,11 +241,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
242241
target.br(postinvoketarget.llbb());
243242
}
244243
},
245-
(false, _, _, &None) => {
244+
(false, _, &None) => {
246245
bcx.call(callee.immediate(), &llargs[..], None, Some(attrs));
247246
bcx.unreachable();
248247
}
249-
(false, _, _, &Some((_, target))) => {
248+
(false, _, &Some((_, target))) => {
250249
let llret = bcx.call(callee.immediate(),
251250
&llargs[..],
252251
None,
@@ -261,7 +260,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
261260
bcx.br(self.llblock(target));
262261
}
263262
// Foreign functions
264-
(true, _, _, destination) => {
263+
(true, _, destination) => {
265264
let (dest, _) = ret_dest_ty
266265
.expect("return destination is not set");
267266
bcx = bcx.map_block(|bcx| {

0 commit comments

Comments
 (0)