Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add const-eval support for indirects #61437

Merged
merged 2 commits into from
Jun 4, 2019
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add const-eval support for indirects
pvdrz committed Jun 4, 2019

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
commit 31ab57305227576646174b952e30969907f98986
2 changes: 1 addition & 1 deletion src/librustc_mir/interpret/operand.rs
Original file line number Diff line number Diff line change
@@ -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>>> {
43 changes: 32 additions & 11 deletions src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
@@ -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,
);
}
}
}
5 changes: 3 additions & 2 deletions src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
Original file line number Diff line number Diff line change
@@ -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);
// ...
23 changes: 23 additions & 0 deletions src/test/mir-opt/const_prop/indirect.rs
Original file line number Diff line number Diff line change
@@ -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