Skip to content

Commit

Permalink
Add const-eval support for indirects
Browse files Browse the repository at this point in the history
  • Loading branch information
pvdrz committed Jun 4, 2019
1 parent 3a6bef0 commit 31ab573
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/operand.rs
Expand Up @@ -268,7 +268,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M>
/// Note that for a given layout, this operation will either always fail or always
/// succeed! Whether it succeeds depends on whether the layout can be represented
/// in a `Immediate`, not on which data is stored there currently.
pub(super) fn try_read_immediate(
pub(crate) fn try_read_immediate(
&self,
src: OpTy<'tcx, M::PointerTag>,
) -> EvalResult<'tcx, Result<Immediate<M::PointerTag>, MemPlace<M::PointerTag>>> {
Expand Down
43 changes: 32 additions & 11 deletions src/librustc_mir/transform/const_prop.rs
Expand Up @@ -3,8 +3,8 @@

use rustc::hir::def::DefKind;
use rustc::mir::{
AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local,
NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind,
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,
};
Expand All @@ -21,7 +21,9 @@ use rustc::ty::layout::{
HasTyCtxt, TargetDataLayout, HasDataLayout,
};

use crate::interpret::{self, InterpretCx, ScalarMaybeUndef, Immediate, OpTy, ImmTy, MemoryKind};
use crate::interpret::{
self, InterpretCx, ScalarMaybeUndef, Immediate, OpTy, ImmTy, MemoryKind,
};
use crate::const_eval::{
CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx,
};
Expand Down Expand Up @@ -516,19 +518,30 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
))
}

fn replace_with_const(&self, rval: &mut Rvalue<'tcx>, value: Const<'tcx>, span: Span) {
fn replace_with_const(
&mut self,
rval: &mut Rvalue<'tcx>,
value: Const<'tcx>,
source_info: SourceInfo,
) {
trace!("attepting to replace {:?} with {:?}", rval, value);
self.ecx.validate_operand(
value,
vec![],
None,
true,
).expect("value should already be a valid const");
).expect("value should already be a valid const");

if let interpret::Operand::Immediate(im) = *value {
match im {
// FIXME> figure out what tho do when try_read_immediate fails
let imm = self.use_ecx(source_info, |this| {
this.ecx.try_read_immediate(value)
});

if let Some(Ok(imm)) = imm {
match imm {
interpret::Immediate::Scalar(ScalarMaybeUndef::Scalar(scalar)) => {
*rval = Rvalue::Use(self.operand_from_scalar(scalar, value.layout.ty, span));
*rval = Rvalue::Use(
self.operand_from_scalar(scalar, value.layout.ty, source_info.span));
},
Immediate::ScalarPair(
ScalarMaybeUndef::Scalar(one),
Expand All @@ -539,8 +552,12 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
*rval = Rvalue::Aggregate(
Box::new(AggregateKind::Tuple),
vec![
self.operand_from_scalar(one, substs[0].expect_ty(), span),
self.operand_from_scalar(two, substs[1].expect_ty(), span),
self.operand_from_scalar(
one, substs[0].expect_ty(), source_info.span
),
self.operand_from_scalar(
two, substs[1].expect_ty(), source_info.span
),
],
);
}
Expand Down Expand Up @@ -655,7 +672,11 @@ impl<'b, 'a, 'tcx> MutVisitor<'tcx> for ConstPropagator<'b, 'a, 'tcx> {
self.places[local] = Some(value);

if self.should_const_prop() {
self.replace_with_const(rval, value, statement.source_info.span);
self.replace_with_const(
rval,
value,
statement.source_info,
);
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
Expand Up @@ -23,8 +23,9 @@ fn main() {
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
// _3 = _4;
// _2 = move _3 as *const i32 (Misc);
// _4 = const Scalar(AllocId(1).0x0) : &i32;
// _3 = const Scalar(AllocId(1).0x0) : &i32;
// _2 = const Scalar(AllocId(1).0x0) : *const i32;
// ...
// _1 = move _2 as usize (Misc);
// ...
Expand Down
23 changes: 23 additions & 0 deletions src/test/mir-opt/const_prop/indirect.rs
@@ -0,0 +1,23 @@
// compile-flags: -C overflow-checks=on

fn main() {
let x = (2u32 as u8) + 1;
}

// END RUST SOURCE
// START rustc.main.ConstProp.before.mir
// bb0: {
// ...
// _2 = const 2u32 as u8 (Misc);
// _3 = CheckedAdd(move _2, const 1u8);
// assert(!move (_3.1: bool), "attempt to add with overflow") -> bb1;
//}
// END rustc.main.ConstProp.before.mir
// START rustc.main.ConstProp.after.mir
// bb0: {
// ...
// _2 = const 2u8;
// _3 = (const 3u8, const false);
// assert(!const false, "attempt to add with overflow") -> bb1;
// }
// END rustc.main.ConstProp.after.mir

0 comments on commit 31ab573

Please sign in to comment.