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.
This commit is contained in:
parent
1de70d33f7
commit
5ad4673a40
4 changed files with 59 additions and 8 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -10,4 +10,5 @@
|
|||
|
||||
pub mod simplify_cfg;
|
||||
pub mod erase_regions;
|
||||
pub mod no_landing_pads;
|
||||
mod util;
|
||||
|
|
|
|||
47
src/librustc_mir/transform/no_landing_pads.rs
Normal file
47
src/librustc_mir/transform/no_landing_pads.rs
Normal file
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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| {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue