1
1
//! MIR definitions and implementation
2
2
3
- use std:: { fmt:: Display , iter} ;
3
+ use std:: { collections :: hash_map :: Entry , fmt:: Display , iter} ;
4
4
5
5
use crate :: {
6
6
consteval:: usize_const,
@@ -37,6 +37,7 @@ pub use monomorphization::{
37
37
monomorphize_mir_body_bad, monomorphized_mir_body_for_closure_query,
38
38
monomorphized_mir_body_query, monomorphized_mir_body_recover,
39
39
} ;
40
+ use rustc_hash:: FxHashMap ;
40
41
use smallvec:: { smallvec, SmallVec } ;
41
42
use stdx:: { impl_from, never} ;
42
43
use triomphe:: Arc ;
@@ -223,35 +224,93 @@ impl<V, T> ProjectionElem<V, T> {
223
224
224
225
type PlaceElem = ProjectionElem < LocalId , Ty > ;
225
226
227
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
228
+ pub struct ProjectionId ( u32 ) ;
229
+
230
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
231
+ pub struct ProjectionStore {
232
+ id_to_proj : FxHashMap < ProjectionId , Box < [ PlaceElem ] > > ,
233
+ proj_to_id : FxHashMap < Box < [ PlaceElem ] > , ProjectionId > ,
234
+ }
235
+
236
+ impl Default for ProjectionStore {
237
+ fn default ( ) -> Self {
238
+ let mut this = Self { id_to_proj : Default :: default ( ) , proj_to_id : Default :: default ( ) } ;
239
+ // Ensure that [] will get the id 0 which is used in `ProjectionId::Empty`
240
+ this. intern ( Box :: new ( [ ] ) ) ;
241
+ this
242
+ }
243
+ }
244
+
245
+ impl ProjectionStore {
246
+ fn shrink_to_fit ( & mut self ) {
247
+ self . id_to_proj . shrink_to_fit ( ) ;
248
+ self . proj_to_id . shrink_to_fit ( ) ;
249
+ }
250
+
251
+ fn intern_if_exist ( & self , projection : & [ PlaceElem ] ) -> Option < ProjectionId > {
252
+ self . proj_to_id . get ( projection) . copied ( )
253
+ }
254
+
255
+ fn intern ( & mut self , projection : Box < [ PlaceElem ] > ) -> ProjectionId {
256
+ let new_id = ProjectionId ( self . proj_to_id . len ( ) as u32 ) ;
257
+ match self . proj_to_id . entry ( projection) {
258
+ Entry :: Occupied ( id) => * id. get ( ) ,
259
+ Entry :: Vacant ( e) => {
260
+ let key_clone = e. key ( ) . clone ( ) ;
261
+ e. insert ( new_id) ;
262
+ self . id_to_proj . insert ( new_id, key_clone) ;
263
+ new_id
264
+ }
265
+ }
266
+ }
267
+ }
268
+
269
+ impl ProjectionId {
270
+ const EMPTY : ProjectionId = ProjectionId ( 0 ) ;
271
+
272
+ fn lookup ( self , store : & ProjectionStore ) -> & [ PlaceElem ] {
273
+ store. id_to_proj . get ( & self ) . unwrap ( )
274
+ }
275
+
276
+ fn project ( self , projection : PlaceElem , store : & mut ProjectionStore ) -> ProjectionId {
277
+ let mut current = self . lookup ( store) . to_vec ( ) ;
278
+ current. push ( projection) ;
279
+ store. intern ( current. into ( ) )
280
+ }
281
+ }
282
+
226
283
#[ derive( Debug , Clone , PartialEq , Eq , Hash ) ]
227
284
pub struct Place {
228
285
pub local : LocalId ,
229
- pub projection : Box < [ PlaceElem ] > ,
286
+ pub projection : ProjectionId ,
230
287
}
231
288
232
289
impl Place {
233
- fn is_parent ( & self , child : & Place ) -> bool {
234
- self . local == child. local && child. projection . starts_with ( & self . projection )
290
+ fn is_parent ( & self , child : & Place , store : & ProjectionStore ) -> bool {
291
+ self . local == child. local
292
+ && child. projection . lookup ( store) . starts_with ( & self . projection . lookup ( store) )
235
293
}
236
294
237
295
/// The place itself is not included
238
- fn iterate_over_parents ( & self ) -> impl Iterator < Item = Place > + ' _ {
239
- ( 0 ..self . projection . len ( ) )
240
- . map ( |x| & self . projection [ 0 ..x] )
241
- . map ( |x| Place { local : self . local , projection : x. to_vec ( ) . into ( ) } )
296
+ fn iterate_over_parents < ' a > (
297
+ & ' a self ,
298
+ store : & ' a ProjectionStore ,
299
+ ) -> impl Iterator < Item = Place > + ' a {
300
+ let projection = self . projection . lookup ( store) ;
301
+ ( 0 ..projection. len ( ) ) . map ( |x| & projection[ 0 ..x] ) . filter_map ( move |x| {
302
+ Some ( Place { local : self . local , projection : store. intern_if_exist ( x) ? } )
303
+ } )
242
304
}
243
305
244
- fn project ( & self , projection : PlaceElem ) -> Place {
245
- Place {
246
- local : self . local ,
247
- projection : self . projection . iter ( ) . cloned ( ) . chain ( [ projection] ) . collect ( ) ,
248
- }
306
+ fn project ( & self , projection : PlaceElem , store : & mut ProjectionStore ) -> Place {
307
+ Place { local : self . local , projection : self . projection . project ( projection, store) }
249
308
}
250
309
}
251
310
252
311
impl From < LocalId > for Place {
253
312
fn from ( local : LocalId ) -> Self {
254
- Self { local, projection : vec ! [ ] . into ( ) }
313
+ Self { local, projection : ProjectionId :: EMPTY }
255
314
}
256
315
}
257
316
@@ -997,6 +1056,7 @@ pub struct BasicBlock {
997
1056
998
1057
#[ derive( Debug , Clone , PartialEq , Eq ) ]
999
1058
pub struct MirBody {
1059
+ pub projection_store : ProjectionStore ,
1000
1060
pub basic_blocks : Arena < BasicBlock > ,
1001
1061
pub locals : Arena < Local > ,
1002
1062
pub start_block : BasicBlockId ,
@@ -1009,11 +1069,15 @@ pub struct MirBody {
1009
1069
}
1010
1070
1011
1071
impl MirBody {
1012
- fn walk_places ( & mut self , mut f : impl FnMut ( & mut Place ) ) {
1013
- fn for_operand ( op : & mut Operand , f : & mut impl FnMut ( & mut Place ) ) {
1072
+ fn walk_places ( & mut self , mut f : impl FnMut ( & mut Place , & mut ProjectionStore ) ) {
1073
+ fn for_operand (
1074
+ op : & mut Operand ,
1075
+ f : & mut impl FnMut ( & mut Place , & mut ProjectionStore ) ,
1076
+ store : & mut ProjectionStore ,
1077
+ ) {
1014
1078
match op {
1015
1079
Operand :: Copy ( p) | Operand :: Move ( p) => {
1016
- f ( p) ;
1080
+ f ( p, store ) ;
1017
1081
}
1018
1082
Operand :: Constant ( _) | Operand :: Static ( _) => ( ) ,
1019
1083
}
@@ -1022,38 +1086,40 @@ impl MirBody {
1022
1086
for statement in & mut block. statements {
1023
1087
match & mut statement. kind {
1024
1088
StatementKind :: Assign ( p, r) => {
1025
- f ( p) ;
1089
+ f ( p, & mut self . projection_store ) ;
1026
1090
match r {
1027
1091
Rvalue :: ShallowInitBoxWithAlloc ( _) => ( ) ,
1028
1092
Rvalue :: ShallowInitBox ( o, _)
1029
1093
| Rvalue :: UnaryOp ( _, o)
1030
1094
| Rvalue :: Cast ( _, o, _)
1031
1095
| Rvalue :: Repeat ( o, _)
1032
- | Rvalue :: Use ( o) => for_operand ( o, & mut f) ,
1096
+ | Rvalue :: Use ( o) => for_operand ( o, & mut f, & mut self . projection_store ) ,
1033
1097
Rvalue :: CopyForDeref ( p)
1034
1098
| Rvalue :: Discriminant ( p)
1035
1099
| Rvalue :: Len ( p)
1036
- | Rvalue :: Ref ( _, p) => f ( p) ,
1100
+ | Rvalue :: Ref ( _, p) => f ( p, & mut self . projection_store ) ,
1037
1101
Rvalue :: CheckedBinaryOp ( _, o1, o2) => {
1038
- for_operand ( o1, & mut f) ;
1039
- for_operand ( o2, & mut f) ;
1102
+ for_operand ( o1, & mut f, & mut self . projection_store ) ;
1103
+ for_operand ( o2, & mut f, & mut self . projection_store ) ;
1040
1104
}
1041
1105
Rvalue :: Aggregate ( _, ops) => {
1042
1106
for op in ops. iter_mut ( ) {
1043
- for_operand ( op, & mut f) ;
1107
+ for_operand ( op, & mut f, & mut self . projection_store ) ;
1044
1108
}
1045
1109
}
1046
1110
}
1047
1111
}
1048
- StatementKind :: Deinit ( p) => f ( p) ,
1112
+ StatementKind :: Deinit ( p) => f ( p, & mut self . projection_store ) ,
1049
1113
StatementKind :: StorageLive ( _)
1050
1114
| StatementKind :: StorageDead ( _)
1051
1115
| StatementKind :: Nop => ( ) ,
1052
1116
}
1053
1117
}
1054
1118
match & mut block. terminator {
1055
1119
Some ( x) => match & mut x. kind {
1056
- TerminatorKind :: SwitchInt { discr, .. } => for_operand ( discr, & mut f) ,
1120
+ TerminatorKind :: SwitchInt { discr, .. } => {
1121
+ for_operand ( discr, & mut f, & mut self . projection_store )
1122
+ }
1057
1123
TerminatorKind :: FalseEdge { .. }
1058
1124
| TerminatorKind :: FalseUnwind { .. }
1059
1125
| TerminatorKind :: Goto { .. }
@@ -1063,23 +1129,24 @@ impl MirBody {
1063
1129
| TerminatorKind :: Return
1064
1130
| TerminatorKind :: Unreachable => ( ) ,
1065
1131
TerminatorKind :: Drop { place, .. } => {
1066
- f ( place) ;
1132
+ f ( place, & mut self . projection_store ) ;
1067
1133
}
1068
1134
TerminatorKind :: DropAndReplace { place, value, .. } => {
1069
- f ( place) ;
1070
- for_operand ( value, & mut f) ;
1135
+ f ( place, & mut self . projection_store ) ;
1136
+ for_operand ( value, & mut f, & mut self . projection_store ) ;
1071
1137
}
1072
1138
TerminatorKind :: Call { func, args, destination, .. } => {
1073
- for_operand ( func, & mut f) ;
1074
- args. iter_mut ( ) . for_each ( |x| for_operand ( x, & mut f) ) ;
1075
- f ( destination) ;
1139
+ for_operand ( func, & mut f, & mut self . projection_store ) ;
1140
+ args. iter_mut ( )
1141
+ . for_each ( |x| for_operand ( x, & mut f, & mut self . projection_store ) ) ;
1142
+ f ( destination, & mut self . projection_store ) ;
1076
1143
}
1077
1144
TerminatorKind :: Assert { cond, .. } => {
1078
- for_operand ( cond, & mut f) ;
1145
+ for_operand ( cond, & mut f, & mut self . projection_store ) ;
1079
1146
}
1080
1147
TerminatorKind :: Yield { value, resume_arg, .. } => {
1081
- for_operand ( value, & mut f) ;
1082
- f ( resume_arg) ;
1148
+ for_operand ( value, & mut f, & mut self . projection_store ) ;
1149
+ f ( resume_arg, & mut self . projection_store ) ;
1083
1150
}
1084
1151
} ,
1085
1152
None => ( ) ,
@@ -1096,7 +1163,9 @@ impl MirBody {
1096
1163
binding_locals,
1097
1164
param_locals,
1098
1165
closures,
1166
+ projection_store,
1099
1167
} = self ;
1168
+ projection_store. shrink_to_fit ( ) ;
1100
1169
basic_blocks. shrink_to_fit ( ) ;
1101
1170
locals. shrink_to_fit ( ) ;
1102
1171
binding_locals. shrink_to_fit ( ) ;
0 commit comments