@@ -44,98 +44,85 @@ impl MirPass for Deaggregator {
44
44
return ;
45
45
}
46
46
47
- for bb in mir. basic_blocks_mut ( ) {
48
- let mut curr: usize = 0 ;
49
- while let Some ( idx) = get_aggregate_statement_index ( curr, & bb. statements ) {
50
- // do the replacement
51
- debug ! ( "removing statement {:?}" , idx) ;
52
- let src_info = bb. statements [ idx] . source_info ;
53
- let suffix_stmts = bb. statements . split_off ( idx+1 ) ;
47
+ let can_deaggregate = |statement : & Statement | {
48
+ if let StatementKind :: Assign ( _, ref rhs) = statement. kind {
49
+ if let Rvalue :: Aggregate ( ..) = * rhs {
50
+ return true ;
51
+ }
52
+ }
53
+
54
+ false
55
+ } ;
56
+
57
+ let ( basic_blocks, local_decls) = mir. basic_blocks_and_local_decls_mut ( ) ;
58
+ for bb in basic_blocks {
59
+ let mut start = 0 ;
60
+ while let Some ( i) = bb. statements [ start..] . iter ( ) . position ( & can_deaggregate) {
61
+ let i = start + i;
62
+
63
+ // FIXME(eddyb) this is probably more expensive than it should be.
64
+ // Ideally we'd move the block's statements all at once.
65
+ let suffix_stmts = bb. statements . split_off ( i + 1 ) ;
54
66
let orig_stmt = bb. statements . pop ( ) . unwrap ( ) ;
55
- let ( lhs, rhs) = match orig_stmt. kind {
56
- StatementKind :: Assign ( ref lhs, ref rhs) => ( lhs, rhs) ,
57
- _ => span_bug ! ( src_info. span, "expected assign, not {:?}" , orig_stmt) ,
58
- } ;
59
- let ( agg_kind, operands) = match rhs {
60
- & Rvalue :: Aggregate ( ref agg_kind, ref operands) => ( agg_kind, operands) ,
61
- _ => span_bug ! ( src_info. span, "expected aggregate, not {:?}" , rhs) ,
67
+ let source_info = orig_stmt. source_info ;
68
+ let ( mut lhs, kind, operands) = match orig_stmt. kind {
69
+ StatementKind :: Assign ( lhs, Rvalue :: Aggregate ( kind, operands) )
70
+ => ( lhs, kind, operands) ,
71
+ _ => bug ! ( )
62
72
} ;
63
- let ( adt_def, variant, substs) = match * * agg_kind {
64
- AggregateKind :: Adt ( adt_def, variant, substs, None )
65
- => ( adt_def, variant, substs) ,
66
- _ => span_bug ! ( src_info. span, "expected struct, not {:?}" , rhs) ,
73
+
74
+ let mut set_discriminant = None ;
75
+ let active_field_index = match * kind {
76
+ AggregateKind :: Adt ( adt_def, variant_index, _, active_field_index) => {
77
+ if adt_def. is_enum ( ) {
78
+ set_discriminant = Some ( Statement {
79
+ kind : StatementKind :: SetDiscriminant {
80
+ place : lhs. clone ( ) ,
81
+ variant_index,
82
+ } ,
83
+ source_info,
84
+ } ) ;
85
+ lhs = lhs. downcast ( adt_def, variant_index) ;
86
+ }
87
+ active_field_index
88
+ }
89
+ _ => None
67
90
} ;
68
- let n = bb. statements . len ( ) ;
69
- bb. statements . reserve ( n + operands. len ( ) + suffix_stmts. len ( ) ) ;
70
- for ( i, op) in operands. iter ( ) . enumerate ( ) {
71
- let ref variant_def = adt_def. variants [ variant] ;
72
- let ty = variant_def. fields [ i] . ty ( tcx, substs) ;
73
- let rhs = Rvalue :: Use ( op. clone ( ) ) ;
74
91
75
- let lhs_cast = if adt_def. is_enum ( ) {
76
- Place :: Projection ( Box :: new ( PlaceProjection {
77
- base : lhs. clone ( ) ,
78
- elem : ProjectionElem :: Downcast ( adt_def, variant) ,
79
- } ) )
80
- } else {
81
- lhs. clone ( )
82
- } ;
92
+ let new_total_count = bb. statements . len ( ) +
93
+ operands. len ( ) +
94
+ ( set_discriminant. is_some ( ) as usize ) +
95
+ suffix_stmts. len ( ) ;
96
+ bb. statements . reserve ( new_total_count) ;
83
97
84
- let lhs_proj = Place :: Projection ( Box :: new ( PlaceProjection {
85
- base : lhs_cast,
86
- elem : ProjectionElem :: Field ( Field :: new ( i) , ty) ,
87
- } ) ) ;
88
- let new_statement = Statement {
89
- source_info : src_info,
90
- kind : StatementKind :: Assign ( lhs_proj, rhs) ,
98
+ for ( j, op) in operands. into_iter ( ) . enumerate ( ) {
99
+ let lhs_field = if let AggregateKind :: Array ( _) = * kind {
100
+ // FIXME(eddyb) `offset` should be u64.
101
+ let offset = j as u32 ;
102
+ assert_eq ! ( offset as usize , j) ;
103
+ lhs. clone ( ) . elem ( ProjectionElem :: ConstantIndex {
104
+ offset,
105
+ // FIXME(eddyb) `min_length` doesn't appear to be used.
106
+ min_length : offset + 1 ,
107
+ from_end : false
108
+ } )
109
+ } else {
110
+ let ty = op. ty ( local_decls, tcx) ;
111
+ let field = Field :: new ( active_field_index. unwrap_or ( j) ) ;
112
+ lhs. clone ( ) . field ( field, ty)
91
113
} ;
92
- debug ! ( "inserting: {:?} @ {:?}" , new_statement, idx + i) ;
93
- bb. statements . push ( new_statement) ;
114
+ bb. statements . push ( Statement {
115
+ source_info,
116
+ kind : StatementKind :: Assign ( lhs_field, Rvalue :: Use ( op) ) ,
117
+ } ) ;
94
118
}
95
119
96
- // if the aggregate was an enum, we need to set the discriminant
97
- if adt_def. is_enum ( ) {
98
- let set_discriminant = Statement {
99
- kind : StatementKind :: SetDiscriminant {
100
- place : lhs. clone ( ) ,
101
- variant_index : variant,
102
- } ,
103
- source_info : src_info,
104
- } ;
105
- bb. statements . push ( set_discriminant) ;
106
- } ;
120
+ // If the aggregate was an enum, we need to set the discriminant.
121
+ bb. statements . extend ( set_discriminant) ;
107
122
108
- curr = bb. statements . len ( ) ;
123
+ start = bb. statements . len ( ) ;
109
124
bb. statements . extend ( suffix_stmts) ;
110
125
}
111
126
}
112
127
}
113
128
}
114
-
115
- fn get_aggregate_statement_index < ' a , ' tcx , ' b > ( start : usize ,
116
- statements : & Vec < Statement < ' tcx > > )
117
- -> Option < usize > {
118
- for i in start..statements. len ( ) {
119
- let ref statement = statements[ i] ;
120
- let rhs = match statement. kind {
121
- StatementKind :: Assign ( _, ref rhs) => rhs,
122
- _ => continue ,
123
- } ;
124
- let ( kind, operands) = match rhs {
125
- & Rvalue :: Aggregate ( ref kind, ref operands) => ( kind, operands) ,
126
- _ => continue ,
127
- } ;
128
- let ( adt_def, variant) = match * * kind {
129
- AggregateKind :: Adt ( adt_def, variant, _, None ) => ( adt_def, variant) ,
130
- _ => continue ,
131
- } ;
132
- if operands. len ( ) == 0 {
133
- // don't deaggregate ()
134
- continue ;
135
- }
136
- debug ! ( "getting variant {:?}" , variant) ;
137
- debug ! ( "for adt_def {:?}" , adt_def) ;
138
- return Some ( i) ;
139
- } ;
140
- None
141
- }
0 commit comments