Hint Rewrite subst_eval_id_eq : subst.
Hint Rewrite subst_eval_id_neq using safe_auto_with_closed : subst.
(* Lemma subst_temp_eq: forall i v w, subst i `v (temp i w) = `(eq w v).  Lemma subst_temp_neq: forall i j v w, i<>j -> subst i v (temp j w) = temp j w.  Lemma subst_var: forall i j v t w,  subst i v (var j t w) = var j t w.  Hint Rewrite subst_var : subst. Hint Rewrite subst_temp_eq : subst. Hint Rewrite subst_temp_neq using safe_auto_with_closed : subst. *)
Fixpoint subst_eval_expr  {cs: compspecs}  (j: ident) (v: environ -> val) (e: expr) : environ -> val :=
match e with
| Econst_int i ty => `(Vint i)
| Econst_long i ty => `(Vlong i)
| Econst_float f ty => `(Vfloat f)
| Econst_single f ty => `(Vsingle f)
| Etempvar id ty => if eqb_ident j id then v else eval_id id
| Eaddrof a ty => subst_eval_lvalue j v a
| Eunop op a ty =>  `(eval_unop op (typeof a)) (subst_eval_expr j v a)
| Ebinop op a1 a2 ty =>
`(eval_binop op (typeof a1) (typeof a2)) (subst_eval_expr j v a1) (subst_eval_expr j v a2)
| Ecast a ty => `(eval_cast (typeof a) ty) (subst_eval_expr j v a)
| Evar id ty => eval_var id ty
| Ederef a ty => subst_eval_expr j v a
| Efield a i ty => `(eval_field (typeof a) i) (subst_eval_lvalue j v a)
| Esizeof t ty => `(Vptrofs (Ptrofs.repr (sizeof t)))
| Ealignof t ty => `(Vptrofs (Ptrofs.repr (alignof t)))
end
with subst_eval_lvalue {cs: compspecs} (j: ident) (v: environ -> val) (e: expr) : environ -> val :=
match e with
| Evar id ty => eval_var id ty
| Ederef a ty => subst_eval_expr j v a
| Efield a i ty => `(eval_field (typeof a) i) (subst_eval_lvalue j v a)
| _  => `Vundef
end.

(* Specifications: *)
Lemma subst_eval_expr_eq:
forall {cs: compspecs} j v e, subst j v (eval_expr e) = subst_eval_expr j v e
with subst_eval_lvalue_eq:
forall {cs: compspecs} j v e, subst j v (eval_lvalue e) = subst_eval_lvalue j v e.