Skip to content

Commit 164ed08

Browse files
committed
[const-prop] Move local storage into a Frame on InterpCx
This moves us closer to just using `InterpCx` for interpretation.
1 parent 573b61a commit 164ed08

File tree

2 files changed

+88
-23
lines changed

2 files changed

+88
-23
lines changed

src/librustc_mir/interpret/eval_context.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
319319
t: T,
320320
) -> InterpResult<'tcx, T> {
321321
match self.stack.last() {
322-
Some(frame) => Ok(self.monomorphize_with_substs(t, frame.instance.substs)),
322+
Some(frame) => Ok(self.monomorphize_with_substs(t, frame.instance.substs)?),
323323
None => if t.needs_subst() {
324324
err!(TooGeneric).into()
325325
} else {
@@ -332,11 +332,16 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
332332
&self,
333333
t: T,
334334
substs: SubstsRef<'tcx>
335-
) -> T {
335+
) -> InterpResult<'tcx, T> {
336336
// miri doesn't care about lifetimes, and will choke on some crazy ones
337337
// let's simply get rid of them
338338
let substituted = t.subst(*self.tcx, substs);
339-
self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substituted)
339+
340+
if substituted.needs_subst() {
341+
return err!(TooGeneric);
342+
}
343+
344+
Ok(self.tcx.normalize_erasing_regions(ty::ParamEnv::reveal_all(), substituted))
340345
}
341346

342347
pub fn layout_of_local(
@@ -349,7 +354,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpretCx<'mir, 'tcx, M> {
349354
None => {
350355
let layout = crate::interpret::operand::from_known_layout(layout, || {
351356
let local_ty = frame.body.local_decls[local].ty;
352-
let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs);
357+
let local_ty = self.monomorphize_with_substs(local_ty, frame.instance.substs)?;
353358
self.layout_of(local_ty)
354359
})?;
355360
// Layouts of locals are requested a lot, so we cache them.

src/librustc_mir/transform/const_prop.rs

+79-19
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
//! Propagates constants for early reporting of statically known
22
//! assertion failures
33
4+
use std::cell::Cell;
5+
46
use rustc::hir::def::DefKind;
57
use rustc::mir::{
68
AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue,
@@ -21,7 +23,8 @@ use rustc::ty::layout::{
2123
};
2224

2325
use crate::interpret::{
24-
self, InterpretCx, ScalarMaybeUndef, Immediate, OpTy, ImmTy, MemoryKind,
26+
self, InterpretCx, ScalarMaybeUndef, Immediate, OpTy,
27+
ImmTy, MemoryKind, StackPopCleanup, LocalValue, LocalState,
2528
};
2629
use crate::const_eval::{
2730
CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx,
@@ -56,21 +59,54 @@ impl MirPass for ConstProp {
5659

5760
trace!("ConstProp starting for {:?}", source.def_id());
5861

62+
// steal some data we need from `body`
63+
let source_scope_local_data = std::mem::replace(
64+
&mut body.source_scope_local_data,
65+
ClearCrossCrate::Clear
66+
);
67+
let promoted = std::mem::replace(
68+
&mut body.promoted,
69+
IndexVec::new()
70+
);
71+
72+
let dummy_body =
73+
&Body::new(
74+
body.basic_blocks().clone(),
75+
Default::default(),
76+
ClearCrossCrate::Clear,
77+
Default::default(),
78+
None,
79+
body.local_decls.clone(),
80+
Default::default(),
81+
body.arg_count,
82+
Default::default(),
83+
tcx.def_span(source.def_id()),
84+
Default::default(),
85+
);
86+
5987
// FIXME(oli-obk, eddyb) Optimize locals (or even local paths) to hold
6088
// constants, instead of just checking for const-folding succeeding.
6189
// That would require an uniform one-def no-mutation analysis
6290
// and RPO (or recursing when needing the value of a local).
63-
let mut optimization_finder = ConstPropagator::new(body, tcx, source);
91+
let mut optimization_finder = ConstPropagator::new(
92+
body,
93+
dummy_body,
94+
source_scope_local_data,
95+
promoted,
96+
tcx,
97+
source
98+
);
6499
optimization_finder.visit_body(body);
65100

66101
// put back the data we stole from `mir`
102+
let (source_scope_local_data, promoted) = optimization_finder.release_stolen_data();
67103
std::mem::replace(
68104
&mut body.source_scope_local_data,
69-
optimization_finder.source_scope_local_data
105+
source_scope_local_data
70106
);
71107
std::mem::replace(
72108
&mut body.promoted,
73-
optimization_finder.promoted
109+
promoted
74110
);
75111

76112
trace!("ConstProp done for {:?}", source.def_id());
@@ -84,7 +120,6 @@ struct ConstPropagator<'mir, 'tcx> {
84120
ecx: InterpretCx<'mir, 'tcx, CompileTimeInterpreter<'mir, 'tcx>>,
85121
tcx: TyCtxt<'tcx>,
86122
source: MirSource<'tcx>,
87-
places: IndexVec<Local, Option<Const<'tcx>>>,
88123
can_const_prop: IndexVec<Local, bool>,
89124
param_env: ParamEnv<'tcx>,
90125
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
@@ -117,42 +152,67 @@ impl<'mir, 'tcx> HasTyCtxt<'tcx> for ConstPropagator<'mir, 'tcx> {
117152

118153
impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
119154
fn new(
120-
body: &mut Body<'tcx>,
155+
body: &Body<'tcx>,
156+
dummy_body: &'mir Body<'tcx>,
157+
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
158+
promoted: IndexVec<Promoted, Body<'tcx>>,
121159
tcx: TyCtxt<'tcx>,
122160
source: MirSource<'tcx>,
123161
) -> ConstPropagator<'mir, 'tcx> {
124-
let param_env = tcx.param_env(source.def_id());
125-
let ecx = mk_eval_cx(tcx, tcx.def_span(source.def_id()), param_env);
162+
let def_id = source.def_id();
163+
let param_env = tcx.param_env(def_id);
164+
let span = tcx.def_span(def_id);
165+
let mut ecx = mk_eval_cx(tcx, span, param_env);
126166
let can_const_prop = CanConstProp::check(body);
127-
let source_scope_local_data = std::mem::replace(
128-
&mut body.source_scope_local_data,
129-
ClearCrossCrate::Clear
130-
);
131-
let promoted = std::mem::replace(
132-
&mut body.promoted,
133-
IndexVec::new()
134-
);
167+
168+
ecx.push_stack_frame(
169+
Instance::new(def_id, &InternalSubsts::identity_for_item(tcx, def_id)),
170+
span,
171+
dummy_body,
172+
None,
173+
StackPopCleanup::None {
174+
cleanup: false,
175+
},
176+
).expect("failed to push initial stack frame");
135177

136178
ConstPropagator {
137179
ecx,
138180
tcx,
139181
source,
140182
param_env,
141183
can_const_prop,
142-
places: IndexVec::from_elem(None, &body.local_decls),
143184
source_scope_local_data,
144185
//FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
145186
local_decls: body.local_decls.clone(),
146187
promoted,
147188
}
148189
}
149190

191+
fn release_stolen_data(self) ->
192+
(ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
193+
IndexVec<Promoted, Body<'tcx>>)
194+
{
195+
(self.source_scope_local_data, self.promoted)
196+
}
197+
150198
fn get_const(&self, local: Local) -> Option<Const<'tcx>> {
151-
self.places[local]
199+
let l = &self.ecx.frame().locals[local];
200+
if l.value == LocalValue::Uninitialized || l.value == LocalValue::Dead {
201+
return None;
202+
}
203+
204+
self.ecx.access_local(self.ecx.frame(), local, None).ok()
152205
}
153206

154207
fn set_const(&mut self, local: Local, c: Option<Const<'tcx>>) {
155-
self.places[local] = c;
208+
self.ecx.frame_mut().locals[local] =
209+
match c {
210+
Some(op_ty) => LocalState {
211+
value: LocalValue::Live(*op_ty),
212+
layout: Cell::new(Some(op_ty.layout)),
213+
},
214+
None => LocalState { value: LocalValue::Uninitialized, layout: Cell::new(None) },
215+
};
156216
}
157217

158218
fn use_ecx<F, T>(

0 commit comments

Comments
 (0)