Skip to content

Commit e7e2649

Browse files
committed
[WIP] Add replace_unreachable_intrinsic mir pass
1 parent 9248b01 commit e7e2649

File tree

5 files changed

+84
-3
lines changed

5 files changed

+84
-3
lines changed

src/librustc_codegen_llvm/intrinsic.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
113113
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
114114
None)
115115
}
116-
"unreachable" => {
117-
return;
118-
},
119116
"likely" => {
120117
let expect = self.get_intrinsic(&("llvm.expect.i1"));
121118
self.call(expect, &[args[0].immediate(), self.const_bool(true)], None)

src/librustc_mir/transform/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ pub mod promote_consts;
2828
pub mod qualify_consts;
2929
pub mod qualify_min_const_fn;
3030
pub mod remove_noop_landing_pads;
31+
pub mod replace_unreachable_intrinsic;
3132
pub mod dump_mir;
3233
pub mod deaggregator;
3334
pub mod instcombine;
@@ -234,6 +235,7 @@ fn run_optimization_passes<'tcx>(
234235
&simplify_branches::SimplifyBranches::new("initial"),
235236
&remove_noop_landing_pads::RemoveNoopLandingPads,
236237
&cleanup_post_borrowck::CleanupNonCodegenStatements,
238+
&replace_unreachable_intrinsic::ReplaceUnreachableIntrinsic::new(tcx),
237239

238240
&simplify::SimplifyCfg::new("early-opt"),
239241

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//! This pass replaces the unreachable intrinsic with the Unreachable terminator,
2+
//! so that other optimisation passes can eliminate uncreachable code.
3+
4+
use rustc::ty::{self, TyCtxt};
5+
use rustc::mir::*;
6+
use rustc::mir::visit::MutVisitor;
7+
use rustc_target::spec::abi::Abi;
8+
use syntax::symbol::sym;
9+
use crate::transform::{MirPass, MirSource};
10+
11+
pub struct ReplaceUnreachableIntrinsic<'tcx> {
12+
tcx: TyCtxt<'tcx>,
13+
}
14+
15+
impl<'tcx> ReplaceUnreachableIntrinsic<'tcx> {
16+
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
17+
ReplaceUnreachableIntrinsic { tcx }
18+
}
19+
}
20+
21+
impl<'tcx> MirPass<'tcx> for ReplaceUnreachableIntrinsic<'tcx> {
22+
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) {
23+
replace_unreachable_intrinsic(tcx, body)
24+
}
25+
}
26+
27+
pub fn replace_unreachable_intrinsic<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
28+
ReplaceUnreachableIntrinsic::new(tcx).visit_body(body);
29+
}
30+
31+
impl<'tcx> MutVisitor<'tcx> for ReplaceUnreachableIntrinsic<'tcx> {
32+
fn tcx(&self) -> TyCtxt<'tcx> {
33+
self.tcx
34+
}
35+
36+
fn visit_terminator_kind(&mut self,
37+
kind: &mut TerminatorKind<'tcx>,
38+
_location: Location) {
39+
40+
if let TerminatorKind::Call { func: Operand::Constant(c), .. } = kind {
41+
if let ty::FnDef(def_id, ..) = c.literal.ty.kind {
42+
if let Abi::RustIntrinsic = self.tcx.fn_sig(def_id).abi() {
43+
if let sym::unreachable = self.tcx.item_name(def_id) {
44+
*kind = TerminatorKind::Unreachable;
45+
}
46+
}
47+
}
48+
}
49+
}
50+
}

src/libsyntax_pos/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ symbols! {
718718
uniform_paths,
719719
universal_impl_trait,
720720
unmarked_api,
721+
unreachable,
721722
unreachable_code,
722723
unrestricted_attribute_tokens,
723724
unsafe_no_drop_flag,
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#![feature(core_intrinsics)]
2+
3+
// Tests that unreachable intrinsic is replaced by unreachable terminator
4+
5+
fn main() {
6+
let x = Some(1);
7+
8+
match x {
9+
Some(_) => { },
10+
None => unsafe { std::intrinsics::unreachable() }
11+
}
12+
}
13+
14+
15+
// END RUST SOURCE
16+
// START rustc.main.ReplaceUnreachableIntrinsic.before.mir
17+
// ...
18+
// bb3: {
19+
// StorageLive(_3);
20+
// const std::intrinsics::unreachable();
21+
// }
22+
// ...
23+
// END rustc.main.ReplaceUnreachableIntrinsic.before.mir
24+
// START rustc.main.ReplaceUnreachableIntrinsic.after.mir
25+
// ...
26+
// bb3: {
27+
// StorageLive(_3);
28+
// unreachable;
29+
// }
30+
// ...
31+
// END rustc.main.ReplaceUnreachableIntrinsic.after.mir

0 commit comments

Comments
 (0)