Local Open Scope logic.
Definition eval_vardesc (id: ident) (ty: type) (Delta: tycontext) (T2: PTree.t (type * val)) (GV: option globals) : option val :=
match (var_types Delta) ! id with
| Some _ => match T2 ! id with
| Some (ty', v) =>
if eqb_type ty ty'
then Some v
else None
| None => None
end
| None => match GV with
| Some gv => Some (gv id)
| None => None
end
end.
Definition eval_lvardesc (id: ident) (ty: type) (Delta: tycontext) (T2: PTree.t (type * val)) : option val :=
match (var_types Delta) ! id with
| Some _ => match T2 ! id with
| Some (ty', v) =>
if eqb_type ty ty'
then Some v
else None
| None => None
end
| None => None
end.
Fixpoint msubst_eval_expr {cs: compspecs} (Delta: tycontext) (T1: PTree.t val) (T2: PTree.t (type * val)) (GV: option globals) (e: Clight.expr) : option val :=
match e with
| Econst_int i ty => Some (Vint i)
| Econst_long i ty => Some (Vlong i)
| Econst_float f ty => Some (Vfloat f)
| Econst_single f ty => Some (Vsingle f)
| Etempvar id ty => PTree.get id T1
| Eaddrof a ty => msubst_eval_lvalue Delta T1 T2 GV a
| Eunop op a ty => option_map (eval_unop op (typeof a))
(msubst_eval_expr Delta T1 T2 GV a)
| Ebinop op a1 a2 ty =>
match (msubst_eval_expr Delta T1 T2 GV a1), (msubst_eval_expr Delta T1 T2 GV a2) with
| Some v1, Some v2 => Some (eval_binop op (typeof a1) (typeof a2) v1 v2)
| _, _ => None
end
| Ecast a ty => option_map (eval_cast (typeof a) ty) (msubst_eval_expr Delta T1 T2 GV a)
| Evar id ty => eval_vardesc id ty Delta T2 GV
| Ederef a ty => msubst_eval_expr Delta T1 T2 GV a
| Efield a i ty => option_map (eval_field (typeof a) i) (msubst_eval_lvalue Delta T1 T2 GV a)
| Esizeof t _ => Some (if complete_type cenv_cs t
then Vptrofs (Ptrofs.repr (sizeof t))
else Vundef)
| Ealignof t _ => Some (if complete_type cenv_cs t
then Vptrofs (Ptrofs.repr (alignof t))
else Vundef)
end
with msubst_eval_lvalue {cs: compspecs} (Delta: tycontext) (T1: PTree.t val) (T2: PTree.t (type * val)) (GV: option globals) (e: Clight.expr) : option val :=
match e with
| Evar id ty => eval_vardesc id ty Delta T2 GV
| Ederef a ty => msubst_eval_expr Delta T1 T2 GV a
| Efield a i ty => option_map (eval_field (typeof a) i)
(msubst_eval_lvalue Delta T1 T2 GV a)
| _  => Some Vundef
end.
Definition msubst_eval_LR {cs: compspecs} Delta T1 T2 GV e (lr: LLRR) :=
match lr with
| LLLL => msubst_eval_lvalue Delta T1 T2 GV e
| RRRR => msubst_eval_expr Delta T1 T2 GV e
end.
Definition msubst_eval_lvar {cs: compspecs} Delta T2 i t :=
eval_lvardesc i t Delta T2.

Lemma msubst_eval_expr_eq: forall {cs: compspecs} Delta P T1 T2 GV R e v,
msubst_eval_expr Delta T1 T2 GV e = Some v ->
ENTAIL Delta, PROPx P (LOCALx (LocalD T1 T2 GV) (SEPx R)) |--
local (`(eq v) (eval_expr e)).