AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue,
Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem,
- SourceScope, SourceScopeLocalData, LocalDecl, Promoted,
+ SourceScope, SourceScopeLocalData, LocalDecl,
};
use rustc::mir::visit::{
Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext,
use rustc::ty::subst::InternalSubsts;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::ty::layout::{
- LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout, Size,
+ LayoutOf, TyLayout, LayoutError, HasTyCtxt, TargetDataLayout, HasDataLayout,
};
use crate::interpret::{
ImmTy, MemoryKind, StackPopCleanup, LocalValue, LocalState,
};
use crate::const_eval::{
- CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx,
+ CompileTimeInterpreter, error_to_const_error, mk_eval_cx,
};
use crate::transform::{MirPass, MirSource};
pub struct ConstProp;
-impl MirPass for ConstProp {
- fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
+impl<'tcx> MirPass<'tcx> for ConstProp {
+ fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) {
// will be evaluated by miri and produce its errors there
if source.promoted.is_some() {
return;
&mut body.source_scope_local_data,
ClearCrossCrate::Clear
);
- let promoted = std::mem::replace(
- &mut body.promoted,
- IndexVec::new()
- );
let dummy_body =
&Body::new(
body.basic_blocks().clone(),
Default::default(),
ClearCrossCrate::Clear,
- Default::default(),
None,
body.local_decls.clone(),
Default::default(),
body,
dummy_body,
source_scope_local_data,
- promoted,
tcx,
source
);
optimization_finder.visit_body(body);
// put back the data we stole from `mir`
- let (source_scope_local_data, promoted) = optimization_finder.release_stolen_data();
+ let source_scope_local_data = optimization_finder.release_stolen_data();
std::mem::replace(
&mut body.source_scope_local_data,
source_scope_local_data
);
- std::mem::replace(
- &mut body.promoted,
- promoted
- );
trace!("ConstProp done for {:?}", source.def_id());
}
param_env: ParamEnv<'tcx>,
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
- promoted: IndexVec<Promoted, Body<'tcx>>,
}
impl<'mir, 'tcx> LayoutOf for ConstPropagator<'mir, 'tcx> {
body: &Body<'tcx>,
dummy_body: &'mir Body<'tcx>,
source_scope_local_data: ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
- promoted: IndexVec<Promoted, Body<'tcx>>,
tcx: TyCtxt<'tcx>,
source: MirSource<'tcx>,
) -> ConstPropagator<'mir, 'tcx> {
source_scope_local_data,
//FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it
local_decls: body.local_decls.clone(),
- promoted,
}
}
- fn release_stolen_data(
- self,
- ) -> (
- ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>>,
- IndexVec<Promoted, Body<'tcx>>,
- ) {
- (self.source_scope_local_data, self.promoted)
+ fn release_stolen_data(self) -> ClearCrossCrate<IndexVec<SourceScope, SourceScopeLocalData>> {
+ self.source_scope_local_data
}
fn get_const(&self, local: Local) -> Option<Const<'tcx>> {
place.iterate(|place_base, place_projection| {
let mut eval = match place_base {
PlaceBase::Local(loc) => self.get_const(*loc).clone()?,
- PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..}) => {
+ PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted, _), ..}) => {
let generics = self.tcx.generics_of(self.source.def_id());
if generics.requires_monomorphization(self.tcx) {
// FIXME: can't handle code with generics
instance,
promoted: Some(*promoted),
};
- // cannot use `const_eval` here, because that would require having the MIR
- // for the current function available, but we're producing said MIR right now
let res = self.use_ecx(source_info, |this| {
- let body = &this.promoted[*promoted];
- eval_promoted(this.tcx, cid, body, this.param_env)
+ this.ecx.const_eval_raw(cid)
})?;
trace!("evaluated promoted {:?} to {:?}", promoted, res);
res.into()
if let ty::Slice(_) = mplace.layout.ty.sty {
let len = mplace.meta.unwrap().to_usize(&self.ecx).unwrap();
- Some(ImmTy {
- imm: Immediate::Scalar(
- Scalar::from_uint(
- len,
- Size::from_bits(
- self.tcx.sess.target.usize_ty.bit_width().unwrap() as u64
- )
- ).into(),
- ),
- layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
- }.into())
+ Some(ImmTy::from_uint(
+ len,
+ self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
+ ).into())
} else {
trace!("not slice: {:?}", mplace.layout.ty.sty);
None
},
Rvalue::NullaryOp(NullOp::SizeOf, ty) => {
type_size_of(self.tcx, self.param_env, ty).and_then(|n| Some(
- ImmTy {
- imm: Immediate::Scalar(
- Scalar::from_uint(n, self.tcx.data_layout.pointer_size).into()
- ),
- layout: self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
- }.into()
+ ImmTy::from_uint(
+ n,
+ self.tcx.layout_of(self.param_env.and(self.tcx.types.usize)).ok()?,
+ ).into()
))
}
Rvalue::UnaryOp(op, ref arg) => {
// Now run the actual operation.
this.ecx.unary_op(op, prim)
})?;
- let res = ImmTy {
- imm: Immediate::Scalar(val.into()),
- layout: place_layout,
- };
- Some(res.into())
+ Some(val.into())
}
Rvalue::CheckedBinaryOp(op, ref left, ref right) |
Rvalue::BinaryOp(op, ref left, ref right) => {
this.ecx.read_immediate(left)
})?;
trace!("const evaluating {:?} for {:?} and {:?}", op, left, right);
- let (val, overflow) = self.use_ecx(source_info, |this| {
- this.ecx.binary_op(op, l, r)
+ let (val, overflow, _ty) = self.use_ecx(source_info, |this| {
+ this.ecx.overflowing_binary_op(op, l, r)
})?;
let val = if let Rvalue::CheckedBinaryOp(..) = *rvalue {
Immediate::ScalarPair(