Skip to content

Commit a5e3c3d

Browse files
committed
collector: collect functions when they are called/reified
This avoids the creation of unneeded vtable shims.
1 parent 65a4266 commit a5e3c3d

File tree

1 file changed

+86
-93
lines changed

1 file changed

+86
-93
lines changed

src/librustc_trans/collector.rs

Lines changed: 86 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,6 @@ use rustc::mir::{self, Location};
202202
use rustc::mir::visit as mir_visit;
203203
use rustc::mir::visit::Visitor as MirVisitor;
204204

205-
use syntax::abi::Abi;
206205
use context::SharedCrateContext;
207206
use common::{def_ty, instance_ty};
208207
use glue::{self, DropGlueKind};
@@ -486,6 +485,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
486485
self.output);
487486
}
488487
}
488+
mir::Rvalue::Cast(mir::CastKind::ReifyFnPointer, ref operand, _) => {
489+
let fn_ty = operand.ty(self.mir, self.scx.tcx());
490+
let fn_ty = monomorphize::apply_param_substs(
491+
self.scx,
492+
self.param_substs,
493+
&fn_ty);
494+
visit_fn_use(self.scx, fn_ty, false, &mut self.output);
495+
}
489496
mir::Rvalue::Cast(mir::CastKind::ClosureFnPointer, ref operand, _) => {
490497
let source_ty = operand.ty(self.mir, self.scx.tcx());
491498
match source_ty.sty {
@@ -537,111 +544,97 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
537544
self.super_lvalue(lvalue, context, location);
538545
}
539546

540-
fn visit_operand(&mut self, operand: &mir::Operand<'tcx>, location: Location) {
541-
debug!("visiting operand {:?}", *operand);
542-
543-
let callee = match *operand {
544-
mir::Operand::Constant(ref constant) => {
545-
if let ty::TyFnDef(def_id, substs, _) = constant.ty.sty {
546-
// This is something that can act as a callee, proceed
547-
Some((def_id, substs))
548-
} else {
549-
// This is not a callee, but we still have to look for
550-
// references to `const` items
551-
if let mir::Literal::Item { def_id, substs } = constant.literal {
552-
let substs = monomorphize::apply_param_substs(self.scx,
553-
self.param_substs,
554-
&substs);
555-
let instance = monomorphize::resolve(self.scx, def_id, substs);
556-
collect_neighbours(self.scx, instance, self.output);
557-
}
547+
fn visit_constant(&mut self, constant: &mir::Constant<'tcx>, location: Location) {
548+
debug!("visiting constant {:?} @ {:?}", *constant, location);
558549

559-
None
560-
}
561-
}
562-
_ => None
563-
};
564-
565-
if let Some((callee_def_id, callee_substs)) = callee {
566-
debug!(" => operand is callable");
567-
568-
// `callee_def_id` might refer to a trait method instead of a
569-
// concrete implementation, so we have to find the actual
570-
// implementation. For example, the call might look like
571-
//
572-
// std::cmp::partial_cmp(0i32, 1i32)
573-
//
574-
// Calling do_static_dispatch() here will map the def_id of
575-
// `std::cmp::partial_cmp` to the def_id of `i32::partial_cmp<i32>`
550+
if let ty::TyFnDef(..) = constant.ty.sty {
551+
// function definitions are zero-sized, and only generate
552+
// IR when they are called/reified.
553+
self.super_constant(constant, location);
554+
return
555+
}
576556

577-
let callee_substs = monomorphize::apply_param_substs(self.scx,
578-
self.param_substs,
579-
&callee_substs);
580-
let instance =
581-
monomorphize::resolve(self.scx, callee_def_id, callee_substs);
582-
if should_trans_locally(self.scx.tcx(), &instance) {
583-
if let ty::InstanceDef::ClosureOnceShim { .. } = instance.def {
584-
// This call will instantiate an FnOnce adapter, which
585-
// drops the closure environment. Therefore we need to
586-
// make sure that we collect the drop-glue for the
587-
// environment type.
588-
589-
let env_ty = instance.substs.type_at(0);
590-
let env_ty = glue::get_drop_glue_type(self.scx, env_ty);
591-
if self.scx.type_needs_drop(env_ty) {
592-
let dg = DropGlueKind::Ty(env_ty);
593-
self.output.push(TransItem::DropGlue(dg));
594-
}
595-
}
596-
self.output.push(create_fn_trans_item(instance));
597-
}
557+
if let mir::Literal::Item { def_id, substs } = constant.literal {
558+
let substs = monomorphize::apply_param_substs(self.scx,
559+
self.param_substs,
560+
&substs);
561+
let instance = monomorphize::resolve(self.scx, def_id, substs);
562+
collect_neighbours(self.scx, instance, self.output);
598563
}
599564

600-
self.super_operand(operand, location);
565+
self.super_constant(constant, location);
601566
}
602567

603-
// This takes care of the "drop_in_place" intrinsic for which we otherwise
604-
// we would not register drop-glues.
605568
fn visit_terminator_kind(&mut self,
606569
block: mir::BasicBlock,
607570
kind: &mir::TerminatorKind<'tcx>,
608571
location: Location) {
609572
let tcx = self.scx.tcx();
610-
match *kind {
611-
mir::TerminatorKind::Call {
612-
func: mir::Operand::Constant(ref constant),
613-
ref args,
614-
..
615-
} => {
616-
match constant.ty.sty {
617-
ty::TyFnDef(def_id, _, bare_fn_ty)
618-
if is_drop_in_place_intrinsic(tcx, def_id, bare_fn_ty) => {
619-
let operand_ty = args[0].ty(self.mir, tcx);
620-
if let ty::TyRawPtr(mt) = operand_ty.sty {
621-
let operand_ty = monomorphize::apply_param_substs(self.scx,
622-
self.param_substs,
623-
&mt.ty);
624-
let ty = glue::get_drop_glue_type(self.scx, operand_ty);
625-
self.output.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
626-
} else {
627-
bug!("Has the drop_in_place() intrinsic's signature changed?")
628-
}
629-
}
630-
_ => { /* Nothing to do. */ }
631-
}
632-
}
633-
_ => { /* Nothing to do. */ }
573+
if let mir::TerminatorKind::Call {
574+
ref func,
575+
..
576+
} = *kind {
577+
let callee_ty = func.ty(self.mir, tcx);
578+
let callee_ty = monomorphize::apply_param_substs(
579+
self.scx, self.param_substs, &callee_ty);
580+
visit_fn_use(self.scx, callee_ty, true, &mut self.output);
634581
}
635582

636583
self.super_terminator_kind(block, kind, location);
584+
}
585+
}
586+
587+
fn visit_fn_use<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
588+
ty: ty::Ty<'tcx>,
589+
is_direct_call: bool,
590+
output: &mut Vec<TransItem<'tcx>>)
591+
{
592+
debug!("visit_fn_use({:?}, is_direct_call={:?})", ty, is_direct_call);
593+
let (def_id, substs) = match ty.sty {
594+
ty::TyFnDef(def_id, substs, _) => (def_id, substs),
595+
_ => return
596+
};
637597

638-
fn is_drop_in_place_intrinsic<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
639-
def_id: DefId,
640-
bare_fn_ty: ty::PolyFnSig<'tcx>)
641-
-> bool {
642-
(bare_fn_ty.abi() == Abi::RustIntrinsic ||
643-
bare_fn_ty.abi() == Abi::PlatformIntrinsic) &&
644-
tcx.item_name(def_id) == "drop_in_place"
598+
let instance = monomorphize::resolve(scx, def_id, substs);
599+
if !should_trans_locally(scx.tcx(), &instance) {
600+
return
601+
}
602+
603+
match instance.def {
604+
ty::InstanceDef::ClosureOnceShim { .. } => {
605+
// This call will instantiate an FnOnce adapter, which
606+
// drops the closure environment. Therefore we need to
607+
// make sure that we collect the drop-glue for the
608+
// environment type along with the instance.
609+
610+
let env_ty = instance.substs.type_at(0);
611+
let env_ty = glue::get_drop_glue_type(scx, env_ty);
612+
if scx.type_needs_drop(env_ty) {
613+
let dg = DropGlueKind::Ty(env_ty);
614+
output.push(TransItem::DropGlue(dg));
615+
}
616+
output.push(create_fn_trans_item(instance));
617+
}
618+
ty::InstanceDef::Intrinsic(..) => {
619+
if !is_direct_call {
620+
bug!("intrinsic {:?} being reified", ty);
621+
}
622+
if scx.tcx().item_name(def_id) == "drop_in_place" {
623+
// drop_in_place is a call to drop glue, need to instantiate
624+
// that.
625+
let ty = glue::get_drop_glue_type(scx, substs.type_at(0));
626+
output.push(TransItem::DropGlue(DropGlueKind::Ty(ty)));
627+
}
628+
}
629+
ty::InstanceDef::Virtual(..) => {
630+
// don't need to emit shim if we are calling directly.
631+
if !is_direct_call {
632+
output.push(create_fn_trans_item(instance));
633+
}
634+
}
635+
ty::InstanceDef::Item(..) |
636+
ty::InstanceDef::FnPtrShim(..) => {
637+
output.push(create_fn_trans_item(instance));
645638
}
646639
}
647640
}
@@ -657,8 +650,8 @@ fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: &Instan
657650
call_once: _, closure_did: def_id
658651
} => def_id,
659652
ty::InstanceDef::Virtual(..) |
660-
ty::InstanceDef::FnPtrShim(..) => return true,
661-
ty::InstanceDef::Intrinsic(_) => return false
653+
ty::InstanceDef::FnPtrShim(..) |
654+
ty::InstanceDef::Intrinsic(_) => return true
662655
};
663656
match tcx.hir.get_if_local(def_id) {
664657
Some(hir_map::NodeForeignItem(..)) => {

0 commit comments

Comments
 (0)