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.

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).