Skip to content

Commit

Permalink
Add a no-landing-pads MIR pass
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
nagisa committed Feb 11, 2016
1 parent 1de70d3 commit 5ad4673
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 8 deletions.
6 changes: 5 additions & 1 deletion src/librustc_mir/mir_map.rs
Expand Up @@ -22,7 +22,7 @@ extern crate rustc_front;
use build;
use graphviz;
use pretty;
use transform::simplify_cfg;
use transform::{simplify_cfg, no_landing_pads};
use rustc::dep_graph::DepNode;
use rustc::mir::repr::Mir;
use hair::cx::Cx;
Expand Down Expand Up @@ -148,6 +148,10 @@ impl<'a, 'm, 'tcx> Visitor<'tcx> for InnerDump<'a,'m,'tcx> {

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

let meta_item_list = self.attr
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/transform/mod.rs
Expand Up @@ -10,4 +10,5 @@

pub mod simplify_cfg;
pub mod erase_regions;
pub mod no_landing_pads;
mod util;
47 changes: 47 additions & 0 deletions src/librustc_mir/transform/no_landing_pads.rs
@@ -0,0 +1,47 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This pass removes the unwind branch of all the terminators when the no-landing-pads option is
//! specified.

use rustc::middle::ty;
use rustc::mir::repr::*;
use rustc::mir::visit::MutVisitor;
use rustc::mir::transform::MirPass;

pub struct NoLandingPads;

impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
fn visit_terminator(&mut self, bb: BasicBlock, terminator: &mut Terminator<'tcx>) {
match *terminator {
Terminator::Goto { .. } |
Terminator::Resume |
Terminator::Return |
Terminator::If { .. } |
Terminator::Switch { .. } |
Terminator::SwitchInt { .. } => { /* nothing to do */ },
Terminator::Drop { ref mut unwind, .. } => {
unwind.take();
},
Terminator::Call { ref mut cleanup, .. } => {
cleanup.take();
},
}
self.super_terminator(bb, terminator);
}
}

impl MirPass for NoLandingPads {
fn run_on_mir<'tcx>(&mut self, mir: &mut Mir<'tcx>, tcx: &ty::ctxt<'tcx>) {
if tcx.sess.no_landing_pads() {
self.visit_mir(mir);
}
}
}
13 changes: 6 additions & 7 deletions src/librustc_trans/trans/mir/block.rs
Expand Up @@ -180,11 +180,10 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
}
}

let avoid_invoke = bcx.with_block(|bcx| base::avoid_invoke(bcx));
// Many different ways to call a function handled here
match (is_foreign, avoid_invoke, cleanup, destination) {
match (is_foreign, cleanup, destination) {
// The two cases below are the only ones to use LLVM’s `invoke`.
(false, false, &Some(cleanup), &None) => {
(false, &Some(cleanup), &None) => {
let cleanup = self.bcx(cleanup);
let landingpad = self.make_landing_pad(cleanup);
let unreachable_blk = self.unreachable_block();
Expand All @@ -195,7 +194,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
None,
Some(attrs));
},
(false, false, &Some(cleanup), &Some((_, success))) => {
(false, &Some(cleanup), &Some((_, success))) => {
let cleanup = self.bcx(cleanup);
let landingpad = self.make_landing_pad(cleanup);
let (target, postinvoke) = if must_copy_dest {
Expand Down Expand Up @@ -242,11 +241,11 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
target.br(postinvoketarget.llbb());
}
},
(false, _, _, &None) => {
(false, _, &None) => {
bcx.call(callee.immediate(), &llargs[..], None, Some(attrs));
bcx.unreachable();
}
(false, _, _, &Some((_, target))) => {
(false, _, &Some((_, target))) => {
let llret = bcx.call(callee.immediate(),
&llargs[..],
None,
Expand All @@ -261,7 +260,7 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
bcx.br(self.llblock(target));
}
// Foreign functions
(true, _, _, destination) => {
(true, _, destination) => {
let (dest, _) = ret_dest_ty
.expect("return destination is not set");
bcx = bcx.map_block(|bcx| {
Expand Down

0 comments on commit 5ad4673

Please sign in to comment.