1- use std:: any:: Any ;
21use std:: io:: Write ;
3- use std:: { collections:: HashMap , fs:: File , io, iter:: Iterator , str, vec:: Vec } ;
2+ use std:: ops:: ControlFlow ;
3+ use std:: {
4+ collections:: { HashMap , HashSet } ,
5+ fs:: File ,
6+ io,
7+ iter:: Iterator ,
8+ str,
9+ vec:: Vec ,
10+ } ;
411extern crate rustc_middle;
512extern crate rustc_monomorphize;
613extern crate rustc_session;
@@ -13,9 +20,11 @@ extern crate stable_mir;
1320extern crate serde;
1421extern crate serde_json;
1522use rustc_middle as middle;
16- use rustc_middle:: ty:: { EarlyBinder , FnSig , GenericArgs , Ty , TyCtxt , TypeFoldable , TypingEnv } ;
23+ use rustc_middle:: ty:: {
24+ EarlyBinder , FnSig , GenericArgs , List , Ty , TyCtxt , TypeFoldable , TypingEnv ,
25+ } ;
1726use rustc_session:: config:: { OutFileName , OutputType } ;
18- use rustc_smir:: rustc_internal;
27+ use rustc_smir:: rustc_internal:: { self , internal } ;
1928use rustc_span:: {
2029 def_id:: { DefId , LOCAL_CRATE } ,
2130 symbol,
@@ -24,10 +33,8 @@ use serde::{Serialize, Serializer};
2433use stable_mir:: {
2534 mir:: mono:: { Instance , InstanceKind , MonoItem } ,
2635 mir:: { alloc:: AllocId , visit:: MirVisitor , Body , LocalDecl , Rvalue , Terminator , TerminatorKind } ,
27- ty:: {
28- AdtDef , Allocation , ConstDef , ForeignItemKind , IndexedVal , RigidTy , TyConstKind , TyKind ,
29- VariantIdx ,
30- } ,
36+ ty:: { AdtDef , Allocation , ConstDef , ForeignItemKind , IndexedVal , RigidTy , TyKind , VariantIdx } ,
37+ visitor:: { Visitable , Visitor } ,
3138 CrateDef , CrateItem , ItemKind ,
3239} ;
3340
@@ -480,13 +487,93 @@ type AllocMap = HashMap<stable_mir::mir::alloc::AllocId, AllocInfo>;
480487type TyMap =
481488 HashMap < stable_mir:: ty:: Ty , ( stable_mir:: ty:: TyKind , Option < stable_mir:: abi:: LayoutShape > ) > ;
482489
490+ struct TyCollector < ' tcx > {
491+ tcx : TyCtxt < ' tcx > ,
492+ types : TyMap ,
493+ resolved : HashSet < stable_mir:: ty:: Ty > ,
494+ }
495+
496+ impl TyCollector < ' _ > {
497+ fn new ( tcx : TyCtxt < ' _ > ) -> TyCollector {
498+ TyCollector {
499+ tcx,
500+ types : HashMap :: new ( ) ,
501+ resolved : HashSet :: new ( ) ,
502+ }
503+ }
504+ }
505+
506+ impl TyCollector < ' _ > {
507+ #[ inline( always) ]
508+ fn visit_instance ( & mut self , instance : Instance ) -> ControlFlow < <Self as Visitor >:: Break > {
509+ let fn_abi = instance. fn_abi ( ) . unwrap ( ) ;
510+ let mut inputs_outputs: Vec < stable_mir:: ty:: Ty > =
511+ fn_abi. args . iter ( ) . map ( |arg_abi| arg_abi. ty ) . collect ( ) ;
512+ inputs_outputs. push ( fn_abi. ret . ty ) ;
513+ inputs_outputs. super_visit ( self )
514+ }
515+ }
516+
517+ impl Visitor for TyCollector < ' _ > {
518+ type Break = ( ) ;
519+
520+ fn visit_ty ( & mut self , ty : & stable_mir:: ty:: Ty ) -> ControlFlow < Self :: Break > {
521+ if self . types . contains_key ( ty) || self . resolved . contains ( ty) {
522+ return ControlFlow :: Continue ( ( ) ) ;
523+ }
524+
525+ match ty. kind ( ) {
526+ TyKind :: RigidTy ( RigidTy :: Closure ( def, ref args) ) => {
527+ self . resolved . insert ( * ty) ;
528+ let instance =
529+ Instance :: resolve_closure ( def, args, stable_mir:: ty:: ClosureKind :: Fn ) . unwrap ( ) ;
530+ self . visit_instance ( instance)
531+ }
532+ // Break on CoroutineWitnesses, because they aren't expected when getting the layout
533+ TyKind :: RigidTy ( RigidTy :: CoroutineWitness ( ..) ) => ControlFlow :: Break ( ( ) ) ,
534+ TyKind :: RigidTy ( RigidTy :: FnDef ( def, ref args) ) => {
535+ self . resolved . insert ( * ty) ;
536+ let instance = Instance :: resolve ( def, args) . unwrap ( ) ;
537+ self . visit_instance ( instance)
538+ }
539+ TyKind :: RigidTy ( RigidTy :: FnPtr ( binder_stable) ) => {
540+ self . resolved . insert ( * ty) ;
541+ let binder_internal = internal ( self . tcx , binder_stable) ;
542+ let sig_stable = rustc_internal:: stable (
543+ self . tcx
544+ . fn_abi_of_fn_ptr (
545+ TypingEnv :: fully_monomorphized ( )
546+ . as_query_input ( ( binder_internal, List :: empty ( ) ) ) ,
547+ )
548+ . unwrap ( ) ,
549+ ) ;
550+ let mut inputs_outputs: Vec < stable_mir:: ty:: Ty > =
551+ sig_stable. args . iter ( ) . map ( |arg_abi| arg_abi. ty ) . collect ( ) ;
552+ inputs_outputs. push ( sig_stable. ret . ty ) ;
553+ inputs_outputs. super_visit ( self )
554+ }
555+ _ => {
556+ let control = ty. super_visit ( self ) ;
557+ match control {
558+ ControlFlow :: Continue ( _) => {
559+ let maybe_layout_shape = ty. layout ( ) . ok ( ) . map ( |layout| layout. shape ( ) ) ;
560+ self . types . insert ( * ty, ( ty. kind ( ) , maybe_layout_shape) ) ;
561+ control
562+ }
563+ _ => control,
564+ }
565+ }
566+ }
567+ }
568+ }
569+
483570struct InternedValueCollector < ' tcx , ' local > {
484571 tcx : TyCtxt < ' tcx > ,
485572 _sym : String ,
486573 locals : & ' local [ LocalDecl ] ,
487574 link_map : & ' local mut LinkMap < ' tcx > ,
488575 visited_allocs : & ' local mut AllocMap ,
489- visited_tys : & ' local mut TyMap ,
576+ ty_visitor : & ' local mut TyCollector < ' tcx > ,
490577}
491578
492579type InternedValues < ' tcx > = ( LinkMap < ' tcx > , AllocMap , TyMap ) ;
@@ -601,103 +688,6 @@ fn collect_alloc(
601688 } ;
602689}
603690
604- fn collect_vec_tys ( collector : & mut InternedValueCollector , tys : Vec < stable_mir:: ty:: Ty > ) {
605- tys. into_iter ( ) . for_each ( |ty| collect_ty ( collector, ty) ) ;
606- }
607-
608- fn collect_arg_tys ( collector : & mut InternedValueCollector , args : & stable_mir:: ty:: GenericArgs ) {
609- use stable_mir:: ty:: { GenericArgKind :: * , TyConstKind :: * } ; // TyConst
610- for arg in args. 0 . iter ( ) {
611- match arg {
612- Type ( ty) => collect_ty ( collector, * ty) ,
613- Const ( ty_const) => match ty_const. kind ( ) {
614- Value ( ty, _) | ZSTValue ( ty) => collect_ty ( collector, * ty) ,
615- _ => { }
616- } ,
617- _ => { }
618- }
619- }
620- }
621-
622- fn collect_ty ( val_collector : & mut InternedValueCollector , val : stable_mir:: ty:: Ty ) {
623- use stable_mir:: ty:: { RigidTy :: * , TyKind :: RigidTy } ;
624-
625- let maybe_layout_shape = val. layout ( ) . ok ( ) . map ( |layout| layout. shape ( ) ) ;
626-
627- if val_collector
628- . visited_tys
629- . insert ( val, ( val. kind ( ) , maybe_layout_shape) )
630- . is_some ( )
631- {
632- match val. kind ( ) {
633- RigidTy ( Array ( ty, ty_const) ) => {
634- collect_ty ( val_collector, ty) ;
635- match ty_const. kind ( ) {
636- TyConstKind :: Value ( ty, _) => collect_ty ( val_collector, * ty) ,
637- TyConstKind :: ZSTValue ( ty) => collect_ty ( val_collector, * ty) ,
638- _ => ( ) ,
639- }
640- }
641- RigidTy ( Pat ( ty, _) | Slice ( ty) | RawPtr ( ty, _) | Ref ( _, ty, _) ) => {
642- collect_ty ( val_collector, ty)
643- }
644- RigidTy ( Tuple ( tys) ) => collect_vec_tys ( val_collector, tys) ,
645- RigidTy ( Adt ( def, ref args) ) => {
646- for variant in def. variants_iter ( ) {
647- for field in variant. fields ( ) {
648- collect_ty ( val_collector, field. ty ( ) ) ;
649- }
650- }
651- collect_arg_tys ( val_collector, args) ;
652- }
653- // FIXME: Would be good to grab the coroutine signature
654- RigidTy ( Coroutine ( _, ref args, _) | CoroutineWitness ( _, ref args) ) => {
655- collect_arg_tys ( val_collector, args)
656- }
657- RigidTy ( Closure ( def, ref args) ) => {
658- // Need to monomorphise again
659- // let ty_internal = rustc_internal::internal(val_collector.tcx, val);
660- // let closure_kind = ty_internal.to_opt_closure_kind().unwrap(); // Errors on span for some reason
661- // Choose FnOnce, got the idea from kani reachability.rs
662- let instance =
663- Instance :: resolve_closure ( def, args, stable_mir:: ty:: ClosureKind :: Fn ) . unwrap ( ) ;
664- let fn_abi = instance. fn_abi ( ) . unwrap ( ) ;
665- let mut inputs_and_outputs: Vec < stable_mir:: ty:: Ty > =
666- fn_abi. args . iter ( ) . map ( |arg| arg. ty ) . collect ( ) ;
667- if inputs_and_outputs[ 0 ] . type_id ( ) == val. type_id ( ) {
668- // TODO: Not sure if it always occurs, but had case where the first ArgAbi had ty same as val.
669- // This causes an infinite loop
670- inputs_and_outputs. remove ( 0 ) ;
671- }
672- inputs_and_outputs. push ( fn_abi. ret . ty ) ;
673-
674- collect_vec_tys ( val_collector, inputs_and_outputs) ;
675- collect_arg_tys ( val_collector, args) ; // Do I need to do this again?
676- }
677- ref _kind @ RigidTy ( FnDef ( def, ref args) ) => {
678- // Need to monomorphise again
679- let instance = Instance :: resolve ( def, args) . unwrap ( ) ;
680- let fn_abi = instance. fn_abi ( ) . unwrap ( ) ;
681- let mut inputs_and_outputs: Vec < stable_mir:: ty:: Ty > =
682- fn_abi. args . iter ( ) . map ( |arg| arg. ty ) . collect ( ) ;
683- inputs_and_outputs. push ( fn_abi. ret . ty ) ;
684-
685- collect_vec_tys ( val_collector, inputs_and_outputs) ;
686- collect_arg_tys ( val_collector, args) ; // Do I need to do this again?
687- }
688- RigidTy ( Foreign ( def) ) => match def. kind ( ) {
689- ForeignItemKind :: Fn ( def) => {
690- // I think this is fully monomorphised???
691- collect_vec_tys ( val_collector, def. fn_sig ( ) . value . inputs_and_output )
692- }
693- ForeignItemKind :: Type ( ty) => collect_ty ( val_collector, ty) ,
694- ForeignItemKind :: Static ( def) => collect_ty ( val_collector, def. ty ( ) ) ,
695- } ,
696- _ => { } // TODO: I think we need to add arm for FnPtr? Maybe we should create an example that uses it first
697- }
698- }
699- }
700-
701691impl MirVisitor for InternedValueCollector < ' _ , ' _ > {
702692 fn visit_terminator ( & mut self , term : & Terminator , loc : stable_mir:: mir:: visit:: Location ) {
703693 use stable_mir:: mir:: { ConstOperand , Operand :: Constant } ;
@@ -772,14 +762,15 @@ impl MirVisitor for InternedValueCollector<'_, '_> {
772762 }
773763
774764 fn visit_ty ( & mut self , ty : & stable_mir:: ty:: Ty , _location : stable_mir:: mir:: visit:: Location ) {
775- collect_ty ( self , * ty) ;
765+ ty. visit ( self . ty_visitor ) ;
766+ self . super_ty ( ty) ;
776767 }
777768}
778769
779770fn collect_interned_values < ' tcx > ( tcx : TyCtxt < ' tcx > , items : Vec < & MonoItem > ) -> InternedValues < ' tcx > {
780771 let mut calls_map = HashMap :: new ( ) ;
781- let mut visited_tys = HashMap :: new ( ) ;
782772 let mut visited_allocs = HashMap :: new ( ) ;
773+ let mut ty_visitor = TyCollector :: new ( tcx) ;
783774 if link_items_enabled ( ) {
784775 for item in items. iter ( ) {
785776 if let MonoItem :: Fn ( inst) = item {
@@ -800,8 +791,8 @@ fn collect_interned_values<'tcx>(tcx: TyCtxt<'tcx>, items: Vec<&MonoItem>) -> In
800791 _sym : inst. mangled_name ( ) ,
801792 locals : body. locals ( ) ,
802793 link_map : & mut calls_map,
803- visited_tys : & mut visited_tys,
804794 visited_allocs : & mut visited_allocs,
795+ ty_visitor : & mut ty_visitor,
805796 }
806797 . visit_body ( & body)
807798 } else {
@@ -819,8 +810,8 @@ fn collect_interned_values<'tcx>(tcx: TyCtxt<'tcx>, items: Vec<&MonoItem>) -> In
819810 _sym : inst. mangled_name ( ) ,
820811 locals : & [ ] ,
821812 link_map : & mut calls_map,
822- visited_tys : & mut visited_tys,
823813 visited_allocs : & mut visited_allocs,
814+ ty_visitor : & mut ty_visitor,
824815 }
825816 . visit_body ( & body)
826817 } else {
@@ -833,7 +824,7 @@ fn collect_interned_values<'tcx>(tcx: TyCtxt<'tcx>, items: Vec<&MonoItem>) -> In
833824 MonoItem :: GlobalAsm ( _) => { }
834825 }
835826 }
836- ( calls_map, visited_allocs, visited_tys )
827+ ( calls_map, visited_allocs, ty_visitor . types )
837828}
838829
839830// Collection Transitive Closure
0 commit comments