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

Refactor handling of MIR bodies #765

Merged
merged 4 commits into from
May 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
90 changes: 57 additions & 33 deletions creusot/src/backend/place.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::{ctx::CloneMap, translation::LocalIdent};
use crate::{
ctx::{BodyId, CloneMap, TranslationCtx},
translation::LocalIdent,
};
use rustc_middle::{
mir::{Body, Local, Place},
mir::{tcx::PlaceTy, HasLocalDecls, Local, Place, PlaceRef},
ty::TyKind,
};
use why3::{
Expand All @@ -17,6 +20,35 @@ use why3::{

use super::Why3Generator;

impl<'tcx> Why3Generator<'tcx> {
pub(crate) fn place_ty(&mut self, body_id: BodyId, pl: PlaceRef<'tcx>) -> PlaceTy<'tcx> {
let local_decls = self.body(body_id).local_decls().clone();
pl.ty(&local_decls, self.tcx)
}
}

impl<'tcx> TranslationCtx<'tcx> {
pub(crate) fn translate_local(&mut self, body_id: BodyId, loc: Local) -> LocalIdent {
let body = self.body(body_id);

use rustc_middle::mir::VarDebugInfoContents::Place;
let debug_info: Vec<_> = body
.var_debug_info
.iter()
.filter(|var_info| match var_info.value {
Place(p) => p.as_local().map(|l| l == loc).unwrap_or(false),
_ => false,
})
.collect();

assert!(debug_info.len() <= 1, "expected at most one debug entry for local {:?}", loc);
match debug_info.get(0) {
Some(info) => LocalIdent::dbg(loc, *info),
None => LocalIdent::anon(loc),
}
}
}

/// Correctly translate an assignment from one place to another. The challenge here is correctly
/// construction the expression that assigns deep inside a structure.
/// (_1 as Some) = P ---> let _1 = P ??
Expand All @@ -31,7 +63,7 @@ use super::Why3Generator;
pub(crate) fn create_assign_inner<'tcx>(
ctx: &mut Why3Generator<'tcx>,
names: &mut CloneMap<'tcx>,
body: &Body<'tcx>,
body_id: BodyId,
lhs: &Place<'tcx>,
rhs: Exp,
) -> mlcfg::Statement {
Expand All @@ -50,7 +82,7 @@ pub(crate) fn create_assign_inner<'tcx>(
for (proj, elem) in lhs.iter_projections().rev() {
// twisted stuff
stump = &stump[0..stump.len() - 1];
let place_ty = proj.ty(body, ctx.tcx);
let place_ty = ctx.place_ty(body_id, proj);

match elem {
Deref => {
Expand All @@ -60,7 +92,7 @@ pub(crate) fn create_assign_inner<'tcx>(
if mutability == Mut {
inner = RecUp {
record: Box::new(translate_rplace_inner(
ctx, names, body, lhs.local, stump,
ctx, names, body_id, lhs.local, stump,
)),
label: "current".into(),
val: Box::new(inner),
Expand All @@ -85,7 +117,9 @@ pub(crate) fn create_assign_inner<'tcx>(
let ctor = names.constructor(variant.def_id, subst);
inner = Let {
pattern: ConsP(ctor.clone(), field_pats),
arg: Box::new(translate_rplace_inner(ctx, names, body, lhs.local, stump)),
arg: Box::new(translate_rplace_inner(
ctx, names, body_id, lhs.local, stump,
)),
body: Box::new(Constructor { ctor, args: varexps }),
}
}
Expand All @@ -103,7 +137,9 @@ pub(crate) fn create_assign_inner<'tcx>(

inner = Let {
pattern: TupleP(field_pats),
arg: Box::new(translate_rplace_inner(ctx, names, body, lhs.local, stump)),
arg: Box::new(translate_rplace_inner(
ctx, names, body_id, lhs.local, stump,
)),
body: Box::new(Tuple(varexps)),
}
}
Expand All @@ -122,7 +158,9 @@ pub(crate) fn create_assign_inner<'tcx>(

inner = Let {
pattern: ConsP(cons.clone(), field_pats),
arg: Box::new(translate_rplace_inner(ctx, names, body, lhs.local, stump)),
arg: Box::new(translate_rplace_inner(
ctx, names, body_id, lhs.local, stump,
)),
body: Box::new(Exp::Constructor { ctor: cons, args: varexps }),
}
}
Expand All @@ -131,11 +169,15 @@ pub(crate) fn create_assign_inner<'tcx>(
Downcast(_, _) => {}
Index(ix) => {
let set = Exp::impure_qvar(QName::from_string("Slice.set").unwrap());
let ix_exp = Exp::impure_var(translate_local(body, ix).ident());
let ix_exp = Exp::impure_var(ctx.translate_local(body_id, ix).ident());

inner = Call(
Box::new(set),
vec![translate_rplace_inner(ctx, names, body, lhs.local, stump), ix_exp, inner],
vec![
translate_rplace_inner(ctx, names, body_id, lhs.local, stump),
ix_exp,
inner,
],
)
}
ConstantIndex { .. } => unimplemented!("ConstantIndex"),
Expand All @@ -144,7 +186,7 @@ pub(crate) fn create_assign_inner<'tcx>(
}
}

let ident = translate_local(body, lhs.local);
let ident = ctx.translate_local(body_id, lhs.local);
Assign { lhs: ident.ident(), rhs: inner }
}

Expand All @@ -154,13 +196,13 @@ pub(crate) fn create_assign_inner<'tcx>(
pub(crate) fn translate_rplace_inner<'tcx>(
ctx: &mut Why3Generator<'tcx>,
names: &mut CloneMap<'tcx>,
body: &Body<'tcx>,
body_id: BodyId,
loc: Local,
proj: &[rustc_middle::mir::PlaceElem<'tcx>],
) -> Exp {
let mut inner = Exp::impure_var(translate_local(body, loc).ident());
let mut inner = Exp::impure_var(ctx.translate_local(body_id, loc).ident());
use rustc_middle::mir::ProjectionElem::*;
let mut place_ty = Place::ty_from(loc, &[], body, ctx.tcx);
let mut place_ty = ctx.place_ty(body_id, Place::from(loc).as_ref());

for elem in proj {
match elem {
Expand Down Expand Up @@ -203,7 +245,7 @@ pub(crate) fn translate_rplace_inner<'tcx>(
Downcast(_, _) => {}
Index(ix) => {
// TODO: Use [_] syntax
let ix_exp = Exp::impure_var(translate_local(body, *ix).ident());
let ix_exp = Exp::impure_var(ctx.translate_local(body_id, *ix).ident());
inner = Call(
Box::new(Exp::impure_qvar(QName::from_string("Slice.get").unwrap())),
vec![inner, ix_exp],
Expand All @@ -218,21 +260,3 @@ pub(crate) fn translate_rplace_inner<'tcx>(

inner
}

pub(crate) fn translate_local(body: &Body, loc: Local) -> LocalIdent {
use rustc_middle::mir::VarDebugInfoContents::Place;
let debug_info: Vec<_> = body
.var_debug_info
.iter()
.filter(|var_info| match var_info.value {
Place(p) => p.as_local().map(|l| l == loc).unwrap_or(false),
_ => false,
})
.collect();

assert!(debug_info.len() <= 1, "expected at most one debug entry for local {:?}", loc);
match debug_info.get(0) {
Some(info) => LocalIdent::dbg(loc, *info),
None => LocalIdent::anon(loc),
}
}
Loading