@@ -202,7 +202,6 @@ use rustc::mir::{self, Location};
202
202
use rustc:: mir:: visit as mir_visit;
203
203
use rustc:: mir:: visit:: Visitor as MirVisitor ;
204
204
205
- use syntax:: abi:: Abi ;
206
205
use context:: SharedCrateContext ;
207
206
use common:: { def_ty, instance_ty} ;
208
207
use glue:: { self , DropGlueKind } ;
@@ -486,6 +485,14 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
486
485
self . output ) ;
487
486
}
488
487
}
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
+ }
489
496
mir:: Rvalue :: Cast ( mir:: CastKind :: ClosureFnPointer , ref operand, _) => {
490
497
let source_ty = operand. ty ( self . mir , self . scx . tcx ( ) ) ;
491
498
match source_ty. sty {
@@ -537,111 +544,97 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
537
544
self . super_lvalue ( lvalue, context, location) ;
538
545
}
539
546
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) ;
558
549
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
+ }
576
556
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 ) ;
598
563
}
599
564
600
- self . super_operand ( operand , location) ;
565
+ self . super_constant ( constant , location) ;
601
566
}
602
567
603
- // This takes care of the "drop_in_place" intrinsic for which we otherwise
604
- // we would not register drop-glues.
605
568
fn visit_terminator_kind ( & mut self ,
606
569
block : mir:: BasicBlock ,
607
570
kind : & mir:: TerminatorKind < ' tcx > ,
608
571
location : Location ) {
609
572
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 ) ;
634
581
}
635
582
636
583
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
+ } ;
637
597
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) ) ;
645
638
}
646
639
}
647
640
}
@@ -657,8 +650,8 @@ fn should_trans_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: &Instan
657
650
call_once : _, closure_did : def_id
658
651
} => def_id,
659
652
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
662
655
} ;
663
656
match tcx. hir . get_if_local ( def_id) {
664
657
Some ( hir_map:: NodeForeignItem ( ..) ) => {
0 commit comments