From 6f18b559dfbfde2677fc2b1450fdcbc5c2a5566a Mon Sep 17 00:00:00 2001 From: Simonas Kazlauskas Date: Tue, 15 Dec 2015 12:20:49 +0200 Subject: [PATCH] Generate DivergingCall terminator This simplifies CFG greatly for some cases :) --- src/librustc_mir/build/expr/into.rs | 29 +++++++++++++++++++---------- src/librustc_mir/hair/cx/expr.rs | 10 +++++++++- src/librustc_mir/hair/mod.rs | 3 ++- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs index 4a262196d36..a173018b74f 100644 --- a/src/librustc_mir/build/expr/into.rs +++ b/src/librustc_mir/build/expr/into.rs @@ -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() } diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index aa6257345fe..012bd9691be 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -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, } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 6363ddf1e14..fb81cc7e6d9 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -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>, },