Generate DivergingCall terminator
This simplifies CFG greatly for some cases :)
This commit is contained in:
parent
893a66d7a1
commit
6f18b559df
@ -15,6 +15,7 @@ use build::expr::category::{Category, RvalueFunc};
|
||||
use build::scope::LoopScope;
|
||||
use hair::*;
|
||||
use rustc::middle::region::CodeExtent;
|
||||
use rustc::middle::ty;
|
||||
use rustc::mir::repr::*;
|
||||
use syntax::codemap::Span;
|
||||
|
||||
@ -210,22 +211,30 @@ impl<'a,'tcx> Builder<'a,'tcx> {
|
||||
this.exit_scope(expr_span, extent, block, END_BLOCK);
|
||||
this.cfg.start_new_block().unit()
|
||||
}
|
||||
ExprKind::Call { fun, args } => {
|
||||
ExprKind::Call { ty, fun, args } => {
|
||||
let diverges = match ty.sty {
|
||||
ty::TyBareFn(_, ref f) => f.sig.0.output.diverges(),
|
||||
_ => false
|
||||
};
|
||||
let fun = unpack!(block = this.as_operand(block, fun));
|
||||
let args: Vec<_> =
|
||||
args.into_iter()
|
||||
.map(|arg| unpack!(block = this.as_operand(block, arg)))
|
||||
.collect();
|
||||
|
||||
let success = this.cfg.start_new_block();
|
||||
let panic = this.diverge_cleanup();
|
||||
let targets = CallTargets::WithCleanup((success, panic));
|
||||
this.cfg.terminate(block,
|
||||
Terminator::Call {
|
||||
func: fun,
|
||||
args: args,
|
||||
destination: destination.clone(),
|
||||
targets: targets
|
||||
});
|
||||
let cleanup = this.diverge_cleanup();
|
||||
let term = if diverges {
|
||||
Terminator::DivergingCall { func: fun, args: args, cleanup: Some(cleanup) }
|
||||
} else {
|
||||
Terminator::Call {
|
||||
func: fun,
|
||||
args: args,
|
||||
destination: destination.clone(),
|
||||
targets: CallTargets::WithCleanup((success, cleanup))
|
||||
}
|
||||
};
|
||||
this.cfg.terminate(block, term);
|
||||
success.unit()
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
.map(|e| e.to_ref())
|
||||
.collect();
|
||||
ExprKind::Call {
|
||||
ty: expr.ty,
|
||||
fun: expr.to_ref(),
|
||||
args: args,
|
||||
}
|
||||
@ -58,11 +59,17 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
|
||||
argrefs.extend(args.iter().map(|a| a.to_ref()));
|
||||
|
||||
ExprKind::Call {
|
||||
ty: method.ty,
|
||||
fun: method.to_ref(),
|
||||
args: argrefs,
|
||||
}
|
||||
} else {
|
||||
ExprKind::Call { fun: fun.to_ref(), args: args.to_ref() }
|
||||
ExprKind::Call {
|
||||
ty: &cx.tcx.node_id_to_type(fun.id),
|
||||
fun: fun.to_ref(),
|
||||
args: args.to_ref(),
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -802,6 +809,7 @@ fn overloaded_operator<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
|
||||
// now create the call itself
|
||||
let fun = method_callee(cx, expr, method_call);
|
||||
ExprKind::Call {
|
||||
ty: fun.ty,
|
||||
fun: fun.to_ref(),
|
||||
args: argrefs,
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ use rustc::middle::const_eval::ConstVal;
|
||||
use rustc::middle::def_id::DefId;
|
||||
use rustc::middle::region::CodeExtent;
|
||||
use rustc::middle::subst::Substs;
|
||||
use rustc::middle::ty::{AdtDef, ClosureSubsts, Region, Ty};
|
||||
use rustc::middle::ty::{self, AdtDef, ClosureSubsts, Region, Ty};
|
||||
use rustc_front::hir;
|
||||
use syntax::ast;
|
||||
use syntax::codemap::Span;
|
||||
@ -124,6 +124,7 @@ pub enum ExprKind<'tcx> {
|
||||
value: ExprRef<'tcx>,
|
||||
},
|
||||
Call {
|
||||
ty: ty::Ty<'tcx>,
|
||||
fun: ExprRef<'tcx>,
|
||||
args: Vec<ExprRef<'tcx>>,
|
||||
},
|
||||
|
Loading…
x
Reference in New Issue
Block a user