(*From Cminorgenproof*)
Remark val_inject_function_pointer:
  forall v fd j tv,
  Genv.find_funct ge v = Some fd ->
  globalfunction_ptr_inject j ->
  val_inject j v tv ->
  tv = v.(** ** Semantic preservation for the translation of expressions *)

(*LENB: translation of sp. Contrary to selection phase,
  the use of eval_operation (and the existing lemmas about
  eval_operation_inject) here suggests we should
  require sp=Vptr b Int.zero and sp' = Vptr b' Int.zero instead
  of sp=Vptr b i and sp' = Vptr b' i for some arbitrary i.
  Let's see whether this works...*)
Definition sp_preserved (j:meminj) (sp sp':val) :=
    exists b b', sp = Vptr b Int.zero /\ sp' = Vptr b' Int.zero /\
                j b = Some(b',0).

(* Specifications: *)
Lemma shift_stack_addressing_zero: forall addr, shift_stack_addressing (Int.repr 0) addr = addr.
Lemma transl_expr_Eop_correct: forall (le : letenv) (op : operation) (args : exprlist) (vargs : list val) (v : val), eval_exprlist ge sp e m le args vargs -> transl_exprlist_prop le args vargs -> eval_operation ge sp op vargs m = Some v -> transl_expr_prop le (Eop op args) v.
Lemma transl_expr_Eload_correct: forall (le : letenv) (chunk : memory_chunk) (addr : Op.addressing) (args : exprlist) (vargs : list val) (vaddr v : val), eval_exprlist ge sp e m le args vargs -> transl_exprlist_prop le args vargs -> Op.eval_addressing ge sp addr vargs = Some vaddr -> Mem.loadv chunk m vaddr = Some v -> transl_expr_prop le (Eload chunk addr args) v.
Lemma transl_expr_Econdition_correct: forall (le : letenv) (a: condexpr) (ifso ifnot : expr) (va : bool) (v : val), eval_condexpr ge sp e m le a va -> transl_condexpr_prop le a va -> eval_expr ge sp e m le (if va then ifso else ifnot) v -> transl_expr_prop le (if va then ifso else ifnot) v -> transl_expr_prop le (Econdition a ifso ifnot) v.
Lemma transl_expr_Elet_correct: forall (le : letenv) (a1 a2 : expr) (v1 v2 : val), eval_expr ge sp e m le a1 v1 -> transl_expr_prop le a1 v1 -> eval_expr ge sp e m (v1 :: le) a2 v2 -> transl_expr_prop (v1 :: le) a2 v2 -> transl_expr_prop le (Elet a1 a2) v2.
Lemma transl_expr_Eletvar_correct: forall (le : list val) (n : nat) (v : val), nth_error le n = Some v -> transl_expr_prop le (Eletvar n) v.
Lemma transl_expr_Ebuiltin_correct: forall le ef al vl v, eval_exprlist ge sp e m le al vl -> transl_exprlist_prop le al vl -> external_call ef ge vl m E0 v m -> transl_expr_prop le (Ebuiltin ef al) v.
Lemma transl_expr_Eexternal_correct: forall le id sg al b ef vl v, Genv.find_symbol ge id = Some b -> Genv.find_funct_ptr ge b = Some (External ef) -> ef_sig ef = sg -> eval_exprlist ge sp e m le al vl -> transl_exprlist_prop le al vl -> external_call ef ge vl m E0 v m -> transl_expr_prop le (Eexternal id sg al) v.
Lemma transl_exprlist_Enil_correct: forall (le : letenv), transl_exprlist_prop le Enil nil.
Lemma transl_exprlist_Econs_correct: forall (le : letenv) (a1 : expr) (al : exprlist) (v1 : val) (vl : list val), eval_expr ge sp e m le a1 v1 -> transl_expr_prop le a1 v1 -> eval_exprlist ge sp e m le al vl -> transl_exprlist_prop le al vl -> transl_exprlist_prop le (Econs a1 al) (v1 :: vl).
Lemma transl_condexpr_CEcond_correct: forall le cond al vl vb, eval_exprlist ge sp e m le al vl -> transl_exprlist_prop le al vl -> eval_condition cond vl m = Some vb -> transl_condexpr_prop le (CEcond cond al) vb.
Lemma transl_condexpr_CEcondition_correct: forall le a b c va v, eval_condexpr ge sp e m le a va -> transl_condexpr_prop le a va -> eval_condexpr ge sp e m le (if va then b else c) v -> transl_condexpr_prop le (if va then b else c) v -> transl_condexpr_prop le (CEcondition a b c) v.
Lemma transl_condexpr_CElet_correct: forall le a b v1 v2, eval_expr ge sp e m le a v1 -> transl_expr_prop le a v1 -> eval_condexpr ge sp e m (v1 :: le) b v2 -> transl_condexpr_prop (v1 :: le) b v2 -> transl_condexpr_prop le (CElet a b) v2.
Theorem transl_expr_correct: forall le a v, eval_expr ge sp e m le a v -> transl_expr_prop le a v.
Theorem transl_exprlist_correct: forall le a v, eval_exprlist ge sp e m le a v -> transl_exprlist_prop le a v.
Theorem transl_condexpr_correct: forall le a v, eval_condexpr ge sp e m le a v -> transl_condexpr_prop le a v.
Lemma Efftransl_expr_Eop_correct: forall (le : letenv) (op : operation) (args : exprlist) (vargs : list val) (v : val), eval_exprlist ge sp e m le args vargs -> Efftransl_exprlist_prop le args vargs -> eval_operation ge sp op vargs m = Some v -> Efftransl_expr_prop le (Eop op args) v.
Lemma Efftransl_expr_Eload_correct: forall (le : letenv) (chunk : memory_chunk) (addr : Op.addressing) (args : exprlist) (vargs : list val) (vaddr v : val), eval_exprlist ge sp e m le args vargs -> Efftransl_exprlist_prop le args vargs -> Op.eval_addressing ge sp addr vargs = Some vaddr -> Mem.loadv chunk m vaddr = Some v -> Efftransl_expr_prop le (Eload chunk addr args) v.
Lemma Efftransl_expr_Econdition_correct: forall (le : letenv) (a: condexpr) (ifso ifnot : expr) (va : bool) (v : val), eval_condexpr ge sp e m le a va -> Efftransl_condexpr_prop le a va -> eval_expr ge sp e m le (if va then ifso else ifnot) v -> Efftransl_expr_prop le (if va then ifso else ifnot) v -> Efftransl_expr_prop le (Econdition a ifso ifnot) v.
Lemma Efftransl_expr_Elet_correct: forall (le : letenv) (a1 a2 : expr) (v1 v2 : val), eval_expr ge sp e m le a1 v1 -> Efftransl_expr_prop le a1 v1 -> eval_expr ge sp e m (v1 :: le) a2 v2 -> Efftransl_expr_prop (v1 :: le) a2 v2 -> Efftransl_expr_prop le (Elet a1 a2) v2.
Lemma Efftransl_expr_Eletvar_correct: forall (le : list val) (n : nat) (v : val), nth_error le n = Some v -> Efftransl_expr_prop le (Eletvar n) v.
Lemma Efftransl_expr_Ebuiltin_correct: forall le ef al vl v, eval_exprlist ge sp e m le al vl -> Efftransl_exprlist_prop le al vl -> external_call ef ge vl m E0 v m -> Efftransl_expr_prop le (Ebuiltin ef al) v.
Lemma Efftransl_expr_Eexternal_correct: forall le id sg al b ef vl v, Genv.find_symbol ge id = Some b -> Genv.find_funct_ptr ge b = Some (External ef) -> ef_sig ef = sg -> eval_exprlist ge sp e m le al vl -> Efftransl_exprlist_prop le al vl -> external_call ef ge vl m E0 v m -> Efftransl_expr_prop le (Eexternal id sg al) v.
Lemma Efftransl_exprlist_Enil_correct: forall (le : letenv), Efftransl_exprlist_prop le Enil nil.
Lemma Efftransl_exprlist_Econs_correct: forall (le : letenv) (a1 : expr) (al : exprlist) (v1 : val) (vl : list val), eval_expr ge sp e m le a1 v1 -> Efftransl_expr_prop le a1 v1 -> eval_exprlist ge sp e m le al vl -> Efftransl_exprlist_prop le al vl -> Efftransl_exprlist_prop le (Econs a1 al) (v1 :: vl).
Lemma Efftransl_condexpr_CEcond_correct: forall le cond al vl vb, eval_exprlist ge sp e m le al vl -> Efftransl_exprlist_prop le al vl -> eval_condition cond vl m = Some vb -> Efftransl_condexpr_prop le (CEcond cond al) vb.
Lemma Efftransl_condexpr_CEcondition_correct: forall le a b c va v, eval_condexpr ge sp e m le a va -> Efftransl_condexpr_prop le a va -> eval_condexpr ge sp e m le (if va then b else c) v -> Efftransl_condexpr_prop le (if va then b else c) v -> Efftransl_condexpr_prop le (CEcondition a b c) v.
Lemma Efftransl_condexpr_CElet_correct: forall le a b v1 v2, eval_expr ge sp e m le a v1 -> Efftransl_expr_prop le a v1 -> eval_condexpr ge sp e m (v1 :: le) b v2 -> Efftransl_condexpr_prop (v1 :: le) b v2 -> Efftransl_condexpr_prop le (CElet a b) v2.
Theorem Efftransl_expr_correct: forall le a v, eval_expr ge sp e m le a v -> Efftransl_expr_prop le a v.
Theorem Efftransl_exprlist_correct: forall le a v, eval_exprlist ge sp e m le a v -> Efftransl_exprlist_prop le a v.
Theorem Efftransl_condexpr_correct: forall le a v, eval_condexpr ge sp e m le a v -> Efftransl_condexpr_prop le a v.