1
- use std:: any:: Any ;
2
1
use 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
+ } ;
4
11
extern crate rustc_middle;
5
12
extern crate rustc_monomorphize;
6
13
extern crate rustc_session;
@@ -13,9 +20,11 @@ extern crate stable_mir;
13
20
extern crate serde;
14
21
extern crate serde_json;
15
22
use 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
+ } ;
17
26
use rustc_session:: config:: { OutFileName , OutputType } ;
18
- use rustc_smir:: rustc_internal;
27
+ use rustc_smir:: rustc_internal:: { self , internal } ;
19
28
use rustc_span:: {
20
29
def_id:: { DefId , LOCAL_CRATE } ,
21
30
symbol,
@@ -24,10 +33,8 @@ use serde::{Serialize, Serializer};
24
33
use stable_mir:: {
25
34
mir:: mono:: { Instance , InstanceKind , MonoItem } ,
26
35
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 } ,
31
38
CrateDef , CrateItem , ItemKind ,
32
39
} ;
33
40
@@ -480,13 +487,93 @@ type AllocMap = HashMap<stable_mir::mir::alloc::AllocId, AllocInfo>;
480
487
type TyMap =
481
488
HashMap < stable_mir:: ty:: Ty , ( stable_mir:: ty:: TyKind , Option < stable_mir:: abi:: LayoutShape > ) > ;
482
489
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
+
483
570
struct InternedValueCollector < ' tcx , ' local > {
484
571
tcx : TyCtxt < ' tcx > ,
485
572
_sym : String ,
486
573
locals : & ' local [ LocalDecl ] ,
487
574
link_map : & ' local mut LinkMap < ' tcx > ,
488
575
visited_allocs : & ' local mut AllocMap ,
489
- visited_tys : & ' local mut TyMap ,
576
+ ty_visitor : & ' local mut TyCollector < ' tcx > ,
490
577
}
491
578
492
579
type InternedValues < ' tcx > = ( LinkMap < ' tcx > , AllocMap , TyMap ) ;
@@ -601,103 +688,6 @@ fn collect_alloc(
601
688
} ;
602
689
}
603
690
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
-
701
691
impl MirVisitor for InternedValueCollector < ' _ , ' _ > {
702
692
fn visit_terminator ( & mut self , term : & Terminator , loc : stable_mir:: mir:: visit:: Location ) {
703
693
use stable_mir:: mir:: { ConstOperand , Operand :: Constant } ;
@@ -772,14 +762,15 @@ impl MirVisitor for InternedValueCollector<'_, '_> {
772
762
}
773
763
774
764
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) ;
776
767
}
777
768
}
778
769
779
770
fn collect_interned_values < ' tcx > ( tcx : TyCtxt < ' tcx > , items : Vec < & MonoItem > ) -> InternedValues < ' tcx > {
780
771
let mut calls_map = HashMap :: new ( ) ;
781
- let mut visited_tys = HashMap :: new ( ) ;
782
772
let mut visited_allocs = HashMap :: new ( ) ;
773
+ let mut ty_visitor = TyCollector :: new ( tcx) ;
783
774
if link_items_enabled ( ) {
784
775
for item in items. iter ( ) {
785
776
if let MonoItem :: Fn ( inst) = item {
@@ -800,8 +791,8 @@ fn collect_interned_values<'tcx>(tcx: TyCtxt<'tcx>, items: Vec<&MonoItem>) -> In
800
791
_sym : inst. mangled_name ( ) ,
801
792
locals : body. locals ( ) ,
802
793
link_map : & mut calls_map,
803
- visited_tys : & mut visited_tys,
804
794
visited_allocs : & mut visited_allocs,
795
+ ty_visitor : & mut ty_visitor,
805
796
}
806
797
. visit_body ( & body)
807
798
} else {
@@ -819,8 +810,8 @@ fn collect_interned_values<'tcx>(tcx: TyCtxt<'tcx>, items: Vec<&MonoItem>) -> In
819
810
_sym : inst. mangled_name ( ) ,
820
811
locals : & [ ] ,
821
812
link_map : & mut calls_map,
822
- visited_tys : & mut visited_tys,
823
813
visited_allocs : & mut visited_allocs,
814
+ ty_visitor : & mut ty_visitor,
824
815
}
825
816
. visit_body ( & body)
826
817
} else {
@@ -833,7 +824,7 @@ fn collect_interned_values<'tcx>(tcx: TyCtxt<'tcx>, items: Vec<&MonoItem>) -> In
833
824
MonoItem :: GlobalAsm ( _) => { }
834
825
}
835
826
}
836
- ( calls_map, visited_allocs, visited_tys )
827
+ ( calls_map, visited_allocs, ty_visitor . types )
837
828
}
838
829
839
830
// Collection Transitive Closure
0 commit comments