Skip to content

Commit 85a87a1

Browse files
committed
Try read Place
1 parent bd9f156 commit 85a87a1

File tree

1 file changed

+62
-56
lines changed

1 file changed

+62
-56
lines changed

src/librustc_mir/interpret/place.rs

Lines changed: 62 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -101,17 +101,22 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
101101
&self,
102102
place: &mir::Place<'tcx>,
103103
) -> 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+
}
115120
}
116121
}
117122

@@ -157,16 +162,17 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
157162

158163
fn try_read_place_projection(
159164
&self,
165+
base_place: &mir::Place<'tcx>,
160166
proj: &mir::PlaceProjection<'tcx>,
161167
) -> EvalResult<'tcx, Option<Value>> {
162168
use rustc::mir::ProjectionElem::*;
163-
let base = match self.try_read_place(&proj.base)? {
169+
let base = match self.try_read_place(base_place)? {
164170
Some(base) => base,
165171
None => return Ok(None),
166172
};
167-
let base_ty = self.place_ty(&proj.base);
173+
let base_ty = self.place_ty(base_place);
168174
let base_layout = self.layout_of(base_ty)?;
169-
match proj.elem {
175+
match proj {
170176
Field(field, _) => Ok(Some(self.read_field(base, None, field, base_layout)?.0)),
171177
// The NullablePointer cases should work fine, need to take care for normal enums
172178
Downcast(..) |
@@ -204,53 +210,53 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
204210
}
205211

206212
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::*;
214214

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);
226241
}
227-
} else {
228-
bug!("evaluated promoted and got {:#?}", val);
229242
}
230-
}
231243

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+
}
244257
}
245258
}
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-
}
252259
};
253-
254260
self.dump_local(place);
255261

256262
Ok(place)
@@ -383,10 +389,10 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
383389
&mut self,
384390
base: Place,
385391
base_ty: Ty<'tcx>,
386-
proj_elem: &mir::ProjectionElem<'tcx, mir::Local, Ty<'tcx>>,
392+
place_elem: &mir::PlaceElem<'tcx>,
387393
) -> EvalResult<'tcx, Place> {
388394
use rustc::mir::ProjectionElem::*;
389-
match *proj_elem {
395+
match place_elem {
390396
Field(field, _) => {
391397
let layout = self.layout_of(base_ty)?;
392398
Ok(self.place_field(base, field, layout)?.0)

0 commit comments

Comments
 (0)