Skip to content

Commit 6f18b55

Browse files
committed
Generate DivergingCall terminator
This simplifies CFG greatly for some cases :)
1 parent 893a66d commit 6f18b55

File tree

3 files changed

+30
-12
lines changed

3 files changed

+30
-12
lines changed

src/librustc_mir/build/expr/into.rs

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use build::expr::category::{Category, RvalueFunc};
1515
use build::scope::LoopScope;
1616
use hair::*;
1717
use rustc::middle::region::CodeExtent;
18+
use rustc::middle::ty;
1819
use rustc::mir::repr::*;
1920
use syntax::codemap::Span;
2021

@@ -210,22 +211,30 @@ impl<'a,'tcx> Builder<'a,'tcx> {
210211
this.exit_scope(expr_span, extent, block, END_BLOCK);
211212
this.cfg.start_new_block().unit()
212213
}
213-
ExprKind::Call { fun, args } => {
214+
ExprKind::Call { ty, fun, args } => {
215+
let diverges = match ty.sty {
216+
ty::TyBareFn(_, ref f) => f.sig.0.output.diverges(),
217+
_ => false
218+
};
214219
let fun = unpack!(block = this.as_operand(block, fun));
215220
let args: Vec<_> =
216221
args.into_iter()
217222
.map(|arg| unpack!(block = this.as_operand(block, arg)))
218223
.collect();
224+
219225
let success = this.cfg.start_new_block();
220-
let panic = this.diverge_cleanup();
221-
let targets = CallTargets::WithCleanup((success, panic));
222-
this.cfg.terminate(block,
223-
Terminator::Call {
224-
func: fun,
225-
args: args,
226-
destination: destination.clone(),
227-
targets: targets
228-
});
226+
let cleanup = this.diverge_cleanup();
227+
let term = if diverges {
228+
Terminator::DivergingCall { func: fun, args: args, cleanup: Some(cleanup) }
229+
} else {
230+
Terminator::Call {
231+
func: fun,
232+
args: args,
233+
destination: destination.clone(),
234+
targets: CallTargets::WithCleanup((success, cleanup))
235+
}
236+
};
237+
this.cfg.terminate(block, term);
229238
success.unit()
230239
}
231240

src/librustc_mir/hair/cx/expr.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
4141
.map(|e| e.to_ref())
4242
.collect();
4343
ExprKind::Call {
44+
ty: expr.ty,
4445
fun: expr.to_ref(),
4546
args: args,
4647
}
@@ -58,11 +59,17 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
5859
argrefs.extend(args.iter().map(|a| a.to_ref()));
5960

6061
ExprKind::Call {
62+
ty: method.ty,
6163
fun: method.to_ref(),
6264
args: argrefs,
6365
}
6466
} else {
65-
ExprKind::Call { fun: fun.to_ref(), args: args.to_ref() }
67+
ExprKind::Call {
68+
ty: &cx.tcx.node_id_to_type(fun.id),
69+
fun: fun.to_ref(),
70+
args: args.to_ref(),
71+
}
72+
6673
}
6774
}
6875

@@ -802,6 +809,7 @@ fn overloaded_operator<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
802809
// now create the call itself
803810
let fun = method_callee(cx, expr, method_call);
804811
ExprKind::Call {
812+
ty: fun.ty,
805813
fun: fun.to_ref(),
806814
args: argrefs,
807815
}

src/librustc_mir/hair/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use rustc::middle::const_eval::ConstVal;
1919
use rustc::middle::def_id::DefId;
2020
use rustc::middle::region::CodeExtent;
2121
use rustc::middle::subst::Substs;
22-
use rustc::middle::ty::{AdtDef, ClosureSubsts, Region, Ty};
22+
use rustc::middle::ty::{self, AdtDef, ClosureSubsts, Region, Ty};
2323
use rustc_front::hir;
2424
use syntax::ast;
2525
use syntax::codemap::Span;
@@ -124,6 +124,7 @@ pub enum ExprKind<'tcx> {
124124
value: ExprRef<'tcx>,
125125
},
126126
Call {
127+
ty: ty::Ty<'tcx>,
127128
fun: ExprRef<'tcx>,
128129
args: Vec<ExprRef<'tcx>>,
129130
},

0 commit comments

Comments
 (0)