@@ -95,8 +95,10 @@ mod pointer;
95
95
mod queries;
96
96
mod value;
97
97
98
+ use std:: cell:: RefCell ;
98
99
use std:: convert:: TryFrom ;
99
100
use std:: fmt;
101
+ use std:: fmt:: Debug ;
100
102
use std:: io;
101
103
use std:: io:: { Read , Write } ;
102
104
use std:: num:: { NonZeroU32 , NonZeroU64 } ;
@@ -106,10 +108,13 @@ use rustc_ast::LitKind;
106
108
use rustc_data_structures:: fx:: FxHashMap ;
107
109
use rustc_data_structures:: sync:: { HashMapExt , Lock } ;
108
110
use rustc_data_structures:: tiny_list:: TinyList ;
111
+ use rustc_hir as hir;
109
112
use rustc_hir:: def_id:: DefId ;
110
- use rustc_macros:: HashStable ;
113
+ use rustc_hir:: definitions:: DefPathData ;
114
+ use rustc_middle:: traits:: Reveal ;
111
115
use rustc_middle:: ty:: print:: with_no_trimmed_paths;
112
116
use rustc_serialize:: { Decodable , Encodable } ;
117
+ use rustc_span:: { Pos , Span } ;
113
118
use rustc_target:: abi:: Endian ;
114
119
115
120
use crate :: mir;
@@ -446,6 +451,88 @@ impl<'tcx> AllocMap<'tcx> {
446
451
}
447
452
}
448
453
454
+ /// What we store about a frame in an interpreter backtrace.
455
+ #[ derive( Debug ) ]
456
+ pub struct FrameInfo < ' tcx > {
457
+ pub instance : ty:: Instance < ' tcx > ,
458
+ pub span : Span ,
459
+ pub lint_root : Option < hir:: HirId > ,
460
+ }
461
+
462
+ impl < ' tcx > fmt:: Display for FrameInfo < ' tcx > {
463
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
464
+ ty:: tls:: with ( |tcx| {
465
+ if tcx. def_key ( self . instance . def_id ( ) ) . disambiguated_data . data
466
+ == DefPathData :: ClosureExpr
467
+ {
468
+ write ! ( f, "inside closure" ) ?;
469
+ } else {
470
+ write ! ( f, "inside `{}`" , self . instance) ?;
471
+ }
472
+ if !self . span . is_dummy ( ) {
473
+ let sm = tcx. sess . source_map ( ) ;
474
+ let lo = sm. lookup_char_pos ( self . span . lo ( ) ) ;
475
+ write ! (
476
+ f,
477
+ " at {}:{}:{}" ,
478
+ sm. filename_for_diagnostics( & lo. file. name) ,
479
+ lo. line,
480
+ lo. col. to_usize( ) + 1
481
+ ) ?;
482
+ }
483
+ Ok ( ( ) )
484
+ } )
485
+ }
486
+ }
487
+
488
+ #[ derive( Clone , Copy , Debug ) ]
489
+ pub enum ConstDedupResult < T : Clone + Copy + Debug > {
490
+ Selection ( T ) ,
491
+ UserFacing ( T ) ,
492
+ All ( T ) ,
493
+ }
494
+
495
+ impl < T : Clone + Copy + Debug > ConstDedupResult < T > {
496
+ pub fn new ( reveal : Reveal , val : T ) -> Self {
497
+ match reveal {
498
+ Reveal :: Selection => ConstDedupResult :: Selection ( val) ,
499
+ Reveal :: UserFacing => ConstDedupResult :: UserFacing ( val) ,
500
+ Reveal :: All => ConstDedupResult :: All ( val) ,
501
+ }
502
+ }
503
+ }
504
+
505
+ /// Used to store results of calls to `eval_to_allocation_raw` and
506
+ /// `eval_to_const_value_raw`.
507
+ #[ derive( Debug ) ]
508
+ pub struct ConstDedupMap < ' tcx > {
509
+ // interning for deduplication of `eval_to_allocation_raw`
510
+ pub alloc_map : RefCell < FxHashMap < GlobalId < ' tcx > , ConstDedupResult < ConstAlloc < ' tcx > > > > ,
511
+
512
+ // interning for deduplication of `eval_to_const_value_raw`
513
+ pub const_val_map : RefCell < FxHashMap < GlobalId < ' tcx > , ConstDedupResult < ConstValue < ' tcx > > > > ,
514
+ }
515
+
516
+ impl < ' tcx > ConstDedupMap < ' tcx > {
517
+ pub fn new ( ) -> Self {
518
+ ConstDedupMap { alloc_map : Default :: default ( ) , const_val_map : Default :: default ( ) }
519
+ }
520
+
521
+ #[ instrument( skip( self ) , level = "debug" ) ]
522
+ fn insert_alloc ( & self , id : GlobalId < ' tcx > , val : ConstDedupResult < ConstAlloc < ' tcx > > ) {
523
+ let mut alloc_map = self . alloc_map . borrow_mut ( ) ;
524
+ alloc_map. insert ( id, val) ;
525
+ debug ! ( "alloc_map after update: {:#?}" , alloc_map) ;
526
+ }
527
+
528
+ #[ instrument( skip( self ) , level = "debug" ) ]
529
+ fn insert_const_val ( & self , id : GlobalId < ' tcx > , val : ConstDedupResult < ConstValue < ' tcx > > ) {
530
+ let mut const_val_map = self . const_val_map . borrow_mut ( ) ;
531
+ const_val_map. insert ( id, val) ;
532
+ debug ! ( "const_val_map after update: {:#?}" , const_val_map) ;
533
+ }
534
+ }
535
+
449
536
impl < ' tcx > TyCtxt < ' tcx > {
450
537
/// Obtains a new allocation ID that can be referenced but does not
451
538
/// yet have an allocation backing it.
@@ -554,6 +641,129 @@ impl<'tcx> TyCtxt<'tcx> {
554
641
fn set_alloc_id_same_memory ( self , id : AllocId , mem : & ' tcx Allocation ) {
555
642
self . alloc_map . lock ( ) . alloc_map . insert_same ( id, GlobalAlloc :: Memory ( mem) ) ;
556
643
}
644
+
645
+ /// Store the result of a call to `eval_to_allocation_raw` in order to
646
+ /// allow deduplication.
647
+ #[ instrument( skip( self ) , level = "debug" ) ]
648
+ pub fn save_alloc_for_dedup ( self , id : GlobalId < ' tcx > , val : ConstDedupResult < ConstAlloc < ' tcx > > ) {
649
+ let dedup_const_map = self . dedup_const_map . lock ( ) ;
650
+ dedup_const_map. insert_alloc ( id, val) ;
651
+ debug ! ( "dedup_const_map after insert: {:#?}" , dedup_const_map) ;
652
+ }
653
+
654
+ /// Store the result of a call to `eval_to_const_value_raw` in order to deduplicate it.
655
+ #[ instrument( skip( self ) , level = "debug" ) ]
656
+ pub fn save_const_value_for_dedup (
657
+ self ,
658
+ id : GlobalId < ' tcx > ,
659
+ val : ConstDedupResult < ConstValue < ' tcx > > ,
660
+ ) {
661
+ let dedup_const_map = self . dedup_const_map . lock ( ) ;
662
+ dedup_const_map. insert_const_val ( id, val) ;
663
+ debug ! ( "dedup_const_map after insert: {:#?}" , dedup_const_map) ;
664
+ }
665
+
666
+ /// Tries to deduplicate a call to `eval_to_allocation_raw`. If deduplication isn't
667
+ /// successful `eval_to_allocation_raw` query is executed.
668
+ #[ instrument( skip( self , opt_span) , level = "debug" ) ]
669
+ pub fn dedup_eval_alloc_raw (
670
+ self ,
671
+ key : ty:: ParamEnvAnd < ' tcx , GlobalId < ' tcx > > ,
672
+ opt_span : Option < Span > ,
673
+ ) -> EvalToAllocationRawResult < ' tcx > {
674
+ use ConstDedupResult :: * ;
675
+
676
+ let ( param_env, id) = key. into_parts ( ) ;
677
+ let dedup_const_map = self . dedup_const_map . lock ( ) ;
678
+ debug ! ( "dedup_const_map: {:#?}" , dedup_const_map) ;
679
+ let alloc_map = dedup_const_map. alloc_map . borrow ( ) ;
680
+ debug ! ( "alloc_map: {:#?}" , alloc_map) ;
681
+
682
+ let dedup_result = alloc_map. get ( & id) ;
683
+ debug ! ( ?dedup_result) ;
684
+
685
+ match param_env. reveal ( ) {
686
+ Reveal :: Selection => match dedup_result {
687
+ Some ( Selection ( alloc) | UserFacing ( alloc) ) => return Ok ( * alloc) ,
688
+ _ => { }
689
+ } ,
690
+ Reveal :: UserFacing => match dedup_result {
691
+ Some ( Selection ( alloc) | UserFacing ( alloc) ) => {
692
+ return Ok ( * alloc) ;
693
+ }
694
+ _ => { }
695
+ } ,
696
+ Reveal :: All => match dedup_result {
697
+ Some ( Selection ( alloc) | UserFacing ( alloc) | All ( alloc) ) => {
698
+ return Ok ( * alloc) ;
699
+ }
700
+ _ => { }
701
+ } ,
702
+ }
703
+
704
+ // Important to drop the lock here
705
+ drop ( alloc_map) ;
706
+ drop ( dedup_const_map) ;
707
+
708
+ debug ! ( "unable to deduplicate" ) ;
709
+
710
+ // We weren't able to deduplicate
711
+ match opt_span {
712
+ Some ( span) => self . at ( span) . eval_to_allocation_raw ( key) ,
713
+ None => self . eval_to_allocation_raw ( key) ,
714
+ }
715
+ }
716
+
717
+ /// Tries to deduplicate a call to `eval_to_const_value_raw`. If deduplication isn't
718
+ /// successful, `eval_to_const_value_raw` query is executed.
719
+ #[ instrument( skip( self ) , level = "debug" ) ]
720
+ pub fn dedup_eval_const_value_raw (
721
+ self ,
722
+ key : ty:: ParamEnvAnd < ' tcx , GlobalId < ' tcx > > ,
723
+ opt_span : Option < Span > ,
724
+ ) -> EvalToConstValueResult < ' tcx > {
725
+ use ConstDedupResult :: * ;
726
+
727
+ let ( param_env, id) = key. into_parts ( ) ;
728
+ let dedup_const_map = self . dedup_const_map . lock ( ) ;
729
+ debug ! ( "dedup_const_map: {:#?}" , dedup_const_map) ;
730
+ let const_val_map = dedup_const_map. const_val_map . borrow ( ) ;
731
+ debug ! ( "const_val_map: {:#?}" , const_val_map) ;
732
+
733
+ let dedup_result = const_val_map. get ( & id) ;
734
+ debug ! ( ?dedup_result) ;
735
+
736
+ match param_env. reveal ( ) {
737
+ Reveal :: Selection => match dedup_result {
738
+ Some ( Selection ( const_val) | UserFacing ( const_val) ) => return Ok ( * const_val) ,
739
+ _ => { }
740
+ } ,
741
+ Reveal :: UserFacing => match dedup_result {
742
+ Some ( Selection ( const_value) | UserFacing ( const_value) ) => {
743
+ return Ok ( * const_value) ;
744
+ }
745
+ _ => { }
746
+ } ,
747
+ Reveal :: All => match dedup_result {
748
+ Some ( Selection ( const_value) | UserFacing ( const_value) | All ( const_value) ) => {
749
+ return Ok ( * const_value) ;
750
+ }
751
+ _ => { }
752
+ } ,
753
+ }
754
+
755
+ // Important to drop the lock here
756
+ drop ( const_val_map) ;
757
+ drop ( dedup_const_map) ;
758
+
759
+ debug ! ( "unable to deduplicate" ) ;
760
+
761
+ // We weren't able to deduplicate
762
+ match opt_span {
763
+ Some ( span) => self . at ( span) . eval_to_const_value_raw ( key) ,
764
+ None => self . eval_to_const_value_raw ( key) ,
765
+ }
766
+ }
557
767
}
558
768
559
769
////////////////////////////////////////////////////////////////////////////////
0 commit comments