diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs index 0e641bf679d1..8f786df38915 100644 --- a/src/librustc_mir/mir_map.rs +++ b/src/librustc_mir/mir_map.rs @@ -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; @@ -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 diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 41ea4469734f..017cf3607161 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -10,4 +10,5 @@ pub mod simplify_cfg; pub mod erase_regions; +pub mod no_landing_pads; mod util; diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs new file mode 100644 index 000000000000..0d5b0630cd26 --- /dev/null +++ b/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 or the MIT license +// , 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); + } + } +} diff --git a/src/librustc_trans/trans/mir/block.rs b/src/librustc_trans/trans/mir/block.rs index b3b8214a9a70..ebb3492f9628 100644 --- a/src/librustc_trans/trans/mir/block.rs +++ b/src/librustc_trans/trans/mir/block.rs @@ -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(); @@ -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 { @@ -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, @@ -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| {