@@ -179,19 +179,19 @@ impl<'a, 'tcx> OperandValue {
179
179
}
180
180
181
181
impl < ' a , ' tcx > MirContext < ' a , ' tcx > {
182
- pub fn trans_consume ( & mut self ,
183
- bcx : & Builder < ' a , ' tcx > ,
184
- lvalue : & mir:: Lvalue < ' tcx > )
185
- -> OperandRef < ' tcx >
182
+ fn maybe_trans_consume_direct ( & mut self ,
183
+ bcx : & Builder < ' a , ' tcx > ,
184
+ lvalue : & mir:: Lvalue < ' tcx > )
185
+ -> Option < OperandRef < ' tcx > >
186
186
{
187
- debug ! ( "trans_consume (lvalue={:?})" , lvalue) ;
187
+ debug ! ( "maybe_trans_consume_direct (lvalue={:?})" , lvalue) ;
188
188
189
189
// watch out for locals that do not have an
190
190
// alloca; they are handled somewhat differently
191
191
if let mir:: Lvalue :: Local ( index) = * lvalue {
192
192
match self . locals [ index] {
193
193
LocalRef :: Operand ( Some ( o) ) => {
194
- return o ;
194
+ return Some ( o ) ;
195
195
}
196
196
LocalRef :: Operand ( None ) => {
197
197
bug ! ( "use of {:?} before def" , lvalue) ;
@@ -204,28 +204,53 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
204
204
205
205
// Moves out of pair fields are trivial.
206
206
if let & mir:: Lvalue :: Projection ( ref proj) = lvalue {
207
- if let mir:: Lvalue :: Local ( index) = proj. base {
208
- if let LocalRef :: Operand ( Some ( o) ) = self . locals [ index] {
209
- match ( o. val , & proj. elem ) {
210
- ( OperandValue :: Pair ( a, b) ,
211
- & mir:: ProjectionElem :: Field ( ref f, ty) ) => {
212
- let layout = bcx. ccx . layout_of ( self . monomorphize ( & ty) ) ;
207
+ if let mir:: ProjectionElem :: Field ( ref f, _) = proj. elem {
208
+ if let Some ( o) = self . maybe_trans_consume_direct ( bcx, & proj. base ) {
209
+ let layout = o. layout . field ( bcx. ccx , f. index ( ) ) ;
210
+
211
+ // Handled in `trans_consume`.
212
+ assert ! ( !layout. is_zst( ) ) ;
213
+
214
+ match o. val {
215
+ OperandValue :: Pair ( a, b) => {
213
216
let llval = [ a, b] [ f. index ( ) ] ;
214
217
// HACK(eddyb) have to bitcast pointers
215
218
// until LLVM removes pointee types.
216
219
let llval = bcx. bitcast ( llval,
217
220
layout. immediate_llvm_type ( bcx. ccx ) ) ;
218
- return OperandRef {
221
+ return Some ( OperandRef {
219
222
val : OperandValue :: Immediate ( llval) ,
220
223
layout
221
- } ;
224
+ } ) ;
222
225
}
223
226
_ => { }
224
227
}
225
228
}
226
229
}
227
230
}
228
231
232
+ None
233
+ }
234
+
235
+ pub fn trans_consume ( & mut self ,
236
+ bcx : & Builder < ' a , ' tcx > ,
237
+ lvalue : & mir:: Lvalue < ' tcx > )
238
+ -> OperandRef < ' tcx >
239
+ {
240
+ debug ! ( "trans_consume(lvalue={:?})" , lvalue) ;
241
+
242
+ let ty = self . monomorphized_lvalue_ty ( lvalue) ;
243
+ let layout = bcx. ccx . layout_of ( ty) ;
244
+
245
+ // ZSTs don't require any actual memory access.
246
+ if layout. is_zst ( ) {
247
+ return OperandRef :: new_zst ( bcx. ccx , layout) ;
248
+ }
249
+
250
+ if let Some ( o) = self . maybe_trans_consume_direct ( bcx, lvalue) {
251
+ return o;
252
+ }
253
+
229
254
// for most lvalues, to consume them we just load them
230
255
// out from their home
231
256
self . trans_lvalue ( bcx, lvalue) . load ( bcx)
0 commit comments