Skip to content

Commit

Permalink
refactor trans::mir::block to trans all calls through the same code
Browse files Browse the repository at this point in the history
  • Loading branch information
arielb1 committed May 28, 2017
1 parent 9da2aac commit 24c1a07
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 67 deletions.
12 changes: 11 additions & 1 deletion src/librustc_trans/abi.rs
Expand Up @@ -11,7 +11,7 @@
use llvm::{self, ValueRef, AttributePlace};
use base;
use builder::Builder;
use common::{type_is_fat_ptr, C_uint};
use common::{instance_ty, ty_fn_sig, type_is_fat_ptr, C_uint};
use context::CrateContext;
use cabi_x86;
use cabi_x86_64;
Expand Down Expand Up @@ -610,6 +610,14 @@ pub struct FnType<'tcx> {
}

impl<'a, 'tcx> FnType<'tcx> {
pub fn of_instance(ccx: &CrateContext<'a, 'tcx>, instance: &ty::Instance<'tcx>)
-> Self {
let fn_ty = instance_ty(ccx.shared(), &instance);
let sig = ty_fn_sig(ccx, fn_ty);
let sig = ccx.tcx().erase_late_bound_regions_and_normalize(&sig);
Self::new(ccx, sig, &[])
}

pub fn new(ccx: &CrateContext<'a, 'tcx>,
sig: ty::FnSig<'tcx>,
extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
Expand All @@ -631,6 +639,8 @@ impl<'a, 'tcx> FnType<'tcx> {
pub fn unadjusted(ccx: &CrateContext<'a, 'tcx>,
sig: ty::FnSig<'tcx>,
extra_args: &[Ty<'tcx>]) -> FnType<'tcx> {
debug!("FnType::unadjusted({:?}, {:?})", sig, extra_args);

use self::Abi::*;
let cconv = match ccx.sess().target.target.adjust_abi(sig.abi) {
RustIntrinsic | PlatformIntrinsic |
Expand Down
139 changes: 73 additions & 66 deletions src/librustc_trans/mir/block.rs
Expand Up @@ -53,7 +53,23 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
_ => funclets[bb].as_ref(),
};

for statement in &data.statements {
bcx = self.trans_statement(bcx, statement);
}

self.trans_terminator(bcx, bb, data.terminator(), funclet);
}

fn trans_terminator(&mut self,
mut bcx: Builder<'a, 'tcx>,
bb: mir::BasicBlock,
terminator: &mir::Terminator<'tcx>,
funclet: Option<&Funclet>)
{
debug!("trans_terminator: {:?}", terminator);

// Create the cleanup bundle, if needed.
let tcx = bcx.tcx();
let cleanup_pad = funclet.map(|lp| lp.cleanuppad());
let cleanup_bundle = funclet.map(|l| l.bundle());

Expand Down Expand Up @@ -104,12 +120,53 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
}
};

for statement in &data.statements {
bcx = self.trans_statement(bcx, statement);
}
let do_call = |
this: &mut Self,
bcx: Builder<'a, 'tcx>,
fn_ty: FnType<'tcx>,
fn_ptr: ValueRef,
llargs: &[ValueRef],
destination: Option<(ReturnDest, ty::Ty<'tcx>, mir::BasicBlock)>,
cleanup: Option<mir::BasicBlock>
| {
if let Some(cleanup) = cleanup {
let ret_bcx = if let Some((_, _, target)) = destination {
this.blocks[target]
} else {
this.unreachable_block()
};
let invokeret = bcx.invoke(fn_ptr,
&llargs,
ret_bcx,
llblock(this, cleanup),
cleanup_bundle);
fn_ty.apply_attrs_callsite(invokeret);

if let Some((ret_dest, ret_ty, target)) = destination {
let ret_bcx = this.get_builder(target);
this.set_debug_loc(&ret_bcx, terminator.source_info);
let op = OperandRef {
val: Immediate(invokeret),
ty: ret_ty,
};
this.store_return(&ret_bcx, ret_dest, &fn_ty.ret, op);
}
} else {
let llret = bcx.call(fn_ptr, &llargs, cleanup_bundle);
fn_ty.apply_attrs_callsite(llret);

let terminator = data.terminator();
debug!("trans_block: terminator: {:?}", terminator);
if let Some((ret_dest, ret_ty, target)) = destination {
let op = OperandRef {
val: Immediate(llret),
ty: ret_ty,
};
this.store_return(&bcx, ret_dest, &fn_ty.ret, op);
funclet_br(this, bcx, target);
} else {
bcx.unreachable();
}
}
};

let span = terminator.source_info.span;
self.set_debug_loc(&bcx, terminator.source_info);
Expand Down Expand Up @@ -218,24 +275,16 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
}

let lvalue = self.trans_lvalue(&bcx, location);
let fn_ty = FnType::of_instance(bcx.ccx, &drop_fn);
let (drop_fn, need_extra) = match ty.sty {
ty::TyDynamic(..) => (meth::DESTRUCTOR.get_fn(&bcx, lvalue.llextra),
false),
_ => (callee::get_fn(bcx.ccx, drop_fn), lvalue.has_extra())
};
let args = &[lvalue.llval, lvalue.llextra][..1 + need_extra as usize];
if let Some(unwind) = unwind {
bcx.invoke(
drop_fn,
args,
self.blocks[target],
llblock(self, unwind),
cleanup_bundle
);
} else {
bcx.call(drop_fn, args, cleanup_bundle);
funclet_br(self, bcx, target);
}
do_call(self, bcx, fn_ty, drop_fn, args,
Some((ReturnDest::Nothing, tcx.mk_nil(), target)),
unwind);
}

mir::TerminatorKind::Assert { ref cond, expected, ref msg, target, cleanup } => {
Expand Down Expand Up @@ -342,26 +391,18 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
// Obtain the panic entry point.
let def_id = common::langcall(bcx.tcx(), Some(span), "", lang_item);
let instance = ty::Instance::mono(bcx.tcx(), def_id);
let fn_ty = FnType::of_instance(bcx.ccx, &instance);
let llfn = callee::get_fn(bcx.ccx, instance);

// Translate the actual panic invoke/call.
if let Some(unwind) = cleanup {
bcx.invoke(llfn,
&args,
self.unreachable_block(),
llblock(self, unwind),
cleanup_bundle);
} else {
bcx.call(llfn, &args, cleanup_bundle);
bcx.unreachable();
}
do_call(self, bcx, fn_ty, llfn, &args, None, cleanup);
}

mir::TerminatorKind::DropAndReplace { .. } => {
bug!("undesugared DropAndReplace in trans: {:?}", data);
bug!("undesugared DropAndReplace in trans: {:?}", terminator);
}

mir::TerminatorKind::Call { ref func, ref args, ref destination, ref cleanup } => {
mir::TerminatorKind::Call { ref func, ref args, ref destination, cleanup } => {
// Create the callee. This is a fn ptr or zero-sized and hence a kind of scalar.
let callee = self.trans_operand(&bcx, func);

Expand Down Expand Up @@ -514,43 +555,9 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
_ => span_bug!(span, "no llfn for call"),
};

// Many different ways to call a function handled here
if let &Some(cleanup) = cleanup {
let ret_bcx = if let Some((_, target)) = *destination {
self.blocks[target]
} else {
self.unreachable_block()
};
let invokeret = bcx.invoke(fn_ptr,
&llargs,
ret_bcx,
llblock(self, cleanup),
cleanup_bundle);
fn_ty.apply_attrs_callsite(invokeret);

if let Some((_, target)) = *destination {
let ret_bcx = self.get_builder(target);
self.set_debug_loc(&ret_bcx, terminator.source_info);
let op = OperandRef {
val: Immediate(invokeret),
ty: sig.output(),
};
self.store_return(&ret_bcx, ret_dest, &fn_ty.ret, op);
}
} else {
let llret = bcx.call(fn_ptr, &llargs, cleanup_bundle);
fn_ty.apply_attrs_callsite(llret);
if let Some((_, target)) = *destination {
let op = OperandRef {
val: Immediate(llret),
ty: sig.output(),
};
self.store_return(&bcx, ret_dest, &fn_ty.ret, op);
funclet_br(self, bcx, target);
} else {
bcx.unreachable();
}
}
do_call(self, bcx, fn_ty, fn_ptr, &llargs,
destination.as_ref().map(|&(_, target)| (ret_dest, sig.output(), target)),
cleanup);
}
}
}
Expand Down

0 comments on commit 24c1a07

Please sign in to comment.