@@ -202,7 +202,6 @@ use rustc::mir::{self, Location};
202202use rustc:: mir:: visit as mir_visit;
203203use rustc:: mir:: visit:: Visitor as MirVisitor ;
204204
205- use syntax:: abi:: Abi ;
206205use context:: SharedCrateContext ;
207206use common:: { def_ty, instance_ty} ;
208207use 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