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 (Vptrofs (Ptrofs.repr (sizeof t)))
| Ealignof t _ => Some (Vptrofs (Ptrofs.repr (alignof t)))
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.

(* Specifications: *)
Lemma msubst_eval_expr_eq_aux:
forall {cs: compspecs} (Delta: tycontext) (T1: PTree.t val) (T2: PTree.t (type * val)) (GV: option globals) e rho v,
(forall i v, T1 ! i = Some v -> eval_id i rho = v) ->
(forall i t v,
eval_vardesc i t Delta T2 GV  = Some v -> eval_var i t rho = v) ->
msubst_eval_expr Delta T1 T2 GV e = Some v ->
eval_expr e rho = v
with msubst_eval_lvalue_eq_aux:
forall {cs: compspecs} (Delta: tycontext) (T1: PTree.t val) (T2: PTree.t (type * val)) (GV: option globals) e rho v,
(forall i v, T1 ! i = Some v -> eval_id i rho = v) ->
(forall i t v,
eval_vardesc i t Delta T2 GV = Some v -> eval_var i t rho = v) ->
msubst_eval_lvalue Delta T1 T2 GV e = Some v ->
eval_lvalue e rho = v.
Lemma msubst_eval_eq_aux {cs: compspecs}: forall Delta T1 T2 GV rho,
tc_environ Delta rho ->
fold_right `(and) `(True) (map locald_denote (LocalD T1 T2 GV)) rho ->
(forall i v, T1 ! i = Some v -> eval_id i rho = v) /\
(forall i t v, eval_vardesc i t Delta T2 GV = Some v ->
eval_var i t rho = v).
Lemma msubst_eval_lvar_eq_aux {cs: compspecs}: forall Delta T1 T2 GV rho,
tc_environ Delta rho ->
fold_right `(and) `(True) (map locald_denote (LocalD T1 T2 GV)) rho ->
(forall i t v, eval_lvardesc i t Delta T2 = Some v ->
eval_lvar i t rho = v).
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)).
Lemma msubst_eval_lvalue_eq: forall {cs: compspecs} Delta P T1 T2 GV R e v,
msubst_eval_lvalue Delta T1 T2 GV e = Some v ->
ENTAIL Delta, PROPx P (LOCALx (LocalD T1 T2 GV) (SEPx R)) |--
local (`(eq v) (eval_lvalue e)).
Lemma msubst_eval_LR_eq: forall {cs: compspecs} Delta P T1 T2 GV R e v lr,
msubst_eval_LR Delta T1 T2 GV e lr = Some v ->
ENTAIL Delta, PROPx P (LOCALx (LocalD T1 T2 GV) (SEPx R)) |--
local (`(eq v) (eval_LR e lr)).
Lemma msubst_eval_exprlist_eq:
forall {cs: compspecs} Delta P T1 T2 GV R tys el vl,
force_list
(map (msubst_eval_expr Delta T1 T2 GV)
(explicit_cast_exprlist tys el)) = Some vl ->
ENTAIL Delta, PROPx P (LOCALx (LocalD T1 T2 GV) (SEPx R)) |--
local (`(eq vl) (eval_exprlist tys el)).
Lemma msubst_eval_lvar_eq: forall {cs: compspecs} Delta P T1 T2 GV R i t v,
msubst_eval_lvar Delta T2 i t = Some v ->
ENTAIL Delta, PROPx P (LOCALx (LocalD T1 T2 GV) (SEPx R)) |--
local (`(eq v) (eval_lvar i t)).