From 31ab57305227576646174b952e30969907f98986 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sat, 1 Jun 2019 13:08:04 -0500 Subject: [PATCH 1/2] Add const-eval support for indirects --- src/librustc_mir/interpret/operand.rs | 2 +- src/librustc_mir/transform/const_prop.rs | 43 ++++++++++++++----- .../const_prop/const_prop_fails_gracefully.rs | 5 ++- src/test/mir-opt/const_prop/indirect.rs | 23 ++++++++++ 4 files changed, 59 insertions(+), 14 deletions(-) create mode 100644 src/test/mir-opt/const_prop/indirect.rs diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index 899cc40dc3206..5c75c323ddd7d 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -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, MemPlace>> { diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 728ea41a9d8e9..ded294ec290cd 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -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, }; @@ -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, }; @@ -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), @@ -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 + ), ], ); } @@ -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, + ); } } } diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs index 97d3abdcc6cbf..85ed8d55b243b 100644 --- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs +++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs @@ -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); // ... diff --git a/src/test/mir-opt/const_prop/indirect.rs b/src/test/mir-opt/const_prop/indirect.rs new file mode 100644 index 0000000000000..b4ee18ed1b53b --- /dev/null +++ b/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 From b2536781afd0eaef11f6b2f68924dde380cf18f2 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 4 Jun 2019 06:30:36 -0400 Subject: [PATCH 2/2] Whitespace fixes --- src/librustc_mir/transform/const_prop.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index ded294ec290cd..dbaa4e557c66f 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -523,14 +523,14 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> { 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"); // FIXME> figure out what tho do when try_read_immediate fails let imm = self.use_ecx(source_info, |this| {