@@ -101,17 +101,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
101
101
& self ,
102
102
place : & mir:: Place < ' tcx > ,
103
103
) -> EvalResult < ' tcx , Option < Value > > {
104
- use rustc:: mir:: Place :: * ;
105
- match * place {
106
- // Might allow this in the future, right now there's no way to do this from Rust code anyway
107
- Local ( mir:: RETURN_PLACE ) => err ! ( ReadFromReturnPointer ) ,
108
- // Directly reading a local will always succeed
109
- Local ( local) => self . frame ( ) . locals [ local] . access ( ) . map ( Some ) ,
110
- // No fast path for statics. Reading from statics is rare and would require another
111
- // Machine function to handle differently in miri.
112
- Promoted ( _) |
113
- Static ( _) => Ok ( None ) ,
114
- Projection ( ref proj) => self . try_read_place_projection ( proj) ,
104
+ use rustc:: mir:: PlaceBase :: * ;
105
+
106
+ if let Some ( ( base_place, projection) ) = place. split_projection ( self . tcx ( ) ) {
107
+ self . try_read_place ( & base_place) ;
108
+ self . tr_read_place_projection ( & base_place, projection) ;
109
+ } else {
110
+ match place. base {
111
+ // Might allow this in the future, right now there's no way to do this from Rust code anyway
112
+ Local ( mir:: RETURN_PLACE ) => err ! ( ReadFromReturnPointer ) ,
113
+ // Directly reading a local will always succeed
114
+ Local ( local) => self . frame ( ) . locals [ local] . access ( ) . map ( Some ) ,
115
+ // No fast path for statics. Reading from statics is rare and would require another
116
+ // Machine function to handle differently in miri.
117
+ Promoted ( _) |
118
+ Static ( _) => Ok ( None ) ,
119
+ }
115
120
}
116
121
}
117
122
@@ -157,16 +162,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
157
162
158
163
fn try_read_place_projection (
159
164
& self ,
165
+ base_place : & mir:: Place < ' tcx > ,
160
166
proj : & mir:: PlaceProjection < ' tcx > ,
161
167
) -> EvalResult < ' tcx , Option < Value > > {
162
168
use rustc:: mir:: ProjectionElem :: * ;
163
- let base = match self . try_read_place ( & proj . base ) ? {
169
+ let base = match self . try_read_place ( base_place ) ? {
164
170
Some ( base) => base,
165
171
None => return Ok ( None ) ,
166
172
} ;
167
- let base_ty = self . place_ty ( & proj . base ) ;
173
+ let base_ty = self . place_ty ( base_place ) ;
168
174
let base_layout = self . layout_of ( base_ty) ?;
169
- match proj. elem {
175
+ match proj {
170
176
Field ( field, _) => Ok ( Some ( self . read_field ( base, None , field, base_layout) ?. 0 ) ) ,
171
177
// The NullablePointer cases should work fine, need to take care for normal enums
172
178
Downcast ( ..) |
@@ -204,53 +210,53 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
204
210
}
205
211
206
212
pub fn eval_place ( & mut self , mir_place : & mir:: Place < ' tcx > ) -> EvalResult < ' tcx , Place > {
207
- use rustc:: mir:: Place :: * ;
208
- let place = match * mir_place {
209
- Local ( mir:: RETURN_PLACE ) => self . frame ( ) . return_place ,
210
- Local ( local) => Place :: Local {
211
- frame : self . cur_frame ( ) ,
212
- local,
213
- } ,
213
+ use rustc:: mir:: PlaceBase :: * ;
214
214
215
- Promoted ( ref promoted) => {
216
- let instance = self . frame ( ) . instance ;
217
- let val = self . read_global_as_value ( GlobalId {
218
- instance,
219
- promoted : Some ( promoted. 0 ) ,
220
- } ) ?;
221
- if let Value :: ByRef ( ptr, align) = val {
222
- Place :: Ptr {
223
- ptr : ptr. into ( ) ,
224
- align,
225
- extra : PlaceExtra :: None ,
215
+ let place = if let Some ( ( base_place, projection) ) = mir_place. split_projection ( self . tcx ( ) ) {
216
+ let ty = self . place_ty ( & base_place) ;
217
+ let place = self . eval_place ( & base_place) ?;
218
+ self . eval_place_projection ( place, ty, projection)
219
+ } else {
220
+ match mir_place. base {
221
+ Local ( mir:: RETURN_PLACE ) => self . frame ( ) . return_place ,
222
+ Local ( local) => Place :: Local {
223
+ frame : self . cur_frame ( ) ,
224
+ local,
225
+ } ,
226
+
227
+ Promoted ( ref promoted) => {
228
+ let instance = self . frame ( ) . instance ;
229
+ let val = self . read_global_as_value ( GlobalId {
230
+ instance,
231
+ promoted : Some ( promoted. 0 ) ,
232
+ } ) ?;
233
+ if let Value :: ByRef ( ptr, align) = val {
234
+ Place :: Ptr {
235
+ ptr : ptr. into ( ) ,
236
+ align,
237
+ extra : PlaceExtra :: None ,
238
+ }
239
+ } else {
240
+ bug ! ( "evaluated promoted and got {:#?}" , val) ;
226
241
}
227
- } else {
228
- bug ! ( "evaluated promoted and got {:#?}" , val) ;
229
242
}
230
- }
231
243
232
- Static ( ref static_) => {
233
- let layout = self . layout_of ( self . place_ty ( mir_place) ) ?;
234
- let instance = ty:: Instance :: mono ( * self . tcx , static_. def_id ) ;
235
- let cid = GlobalId {
236
- instance,
237
- promoted : None
238
- } ;
239
- let alloc = Machine :: init_static ( self , cid) ?;
240
- Place :: Ptr {
241
- ptr : ScalarMaybeUndef :: Scalar ( Scalar :: Ptr ( alloc. into ( ) ) ) ,
242
- align : layout. align ,
243
- extra : PlaceExtra :: None ,
244
+ Static ( ref static_) => {
245
+ let layout = self . layout_of ( self . place_ty ( mir_place) ) ?;
246
+ let instance = ty:: Instance :: mono ( * self . tcx , static_. def_id ) ;
247
+ let cid = GlobalId {
248
+ instance,
249
+ promoted : None
250
+ } ;
251
+ let alloc = Machine :: init_static ( self , cid) ?;
252
+ Place :: Ptr {
253
+ ptr : ScalarMaybeUndef :: Scalar ( Scalar :: Ptr ( alloc. into ( ) ) ) ,
254
+ align : layout. align ,
255
+ extra : PlaceExtra :: None ,
256
+ }
244
257
}
245
258
}
246
-
247
- Projection ( ref proj) => {
248
- let ty = self . place_ty ( & proj. base ) ;
249
- let place = self . eval_place ( & proj. base ) ?;
250
- return self . eval_place_projection ( place, ty, & proj. elem ) ;
251
- }
252
259
} ;
253
-
254
260
self . dump_local ( place) ;
255
261
256
262
Ok ( place)
@@ -383,10 +389,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
383
389
& mut self ,
384
390
base : Place ,
385
391
base_ty : Ty < ' tcx > ,
386
- proj_elem : & mir:: ProjectionElem < ' tcx , mir :: Local , Ty < ' tcx > > ,
392
+ place_elem : & mir:: PlaceElem < ' tcx > ,
387
393
) -> EvalResult < ' tcx , Place > {
388
394
use rustc:: mir:: ProjectionElem :: * ;
389
- match * proj_elem {
395
+ match place_elem {
390
396
Field ( field, _) => {
391
397
let layout = self . layout_of ( base_ty) ?;
392
398
Ok ( self . place_field ( base, field, layout) ?. 0 )
0 commit comments