Module SimplExprspec


Relational specification of expression simplification.

Require Import Coqlib Maps Errors Integers Floats .
Require Import AST Linking Memory .
Require Import Ctypes Cop Csyntax Clight SimplExpr .

Section SPEC .

Variable ce : composite_env .

Local Open Scope gensym_monad_scope.

Relational specification of the translation.


Translation of expressions


This specification covers:
  • all cases of transl_lvalue and transl_rvalue;
  • two additional cases for Csyntax.Eparen, so that reductions of Csyntax.Econdition expressions are properly tracked;
  • three additional cases allowing Csyntax.Eval v C expressions to match any Clight expression a that evaluates to v in any environment matching the given temporary environment le.

Definition final (dst: destination ) (a: expr ) : list statement :=
match dst with
| For_val => nil
| For_effects => nil
| For_set sd => do_set sd a
end.

Definition tr_is_bitfield_access (l: expr ) (bf: bitfield ) : Prop :=
match l with
| Efield r f _ =>
exists co ofs,
match typeof r with
| Tstruct id _ =>
ce !id = Some co /\ field_offset ce f (co_members co) = OK (ofs, bf)
| Tunion id _ =>
ce !id = Some co /\ union_field_offset ce f (co_members co) = OK (ofs, bf)
| _ => False
end
| _ => bf = Full
end.

Inductive tr_rvalof : type -> expr -> list statement -> expr -> list ident -> Prop :=
| tr_rvalof_nonvol : forall ty a tmp,
type_is_volatile ty = false ->
tr_rvalof ty a nil a tmp
| tr_rvalof_vol : forall ty a t bf tmp,
type_is_volatile ty = true -> In t tmp ->
tr_is_bitfield_access a bf ->
tr_rvalof ty a (make_set bf t a :: nil ) (Etempvar t ty) tmp.

Inductive tr_expr : temp_env -> destination -> Csyntax.expr -> list statement -> expr -> list ident -> Prop :=
| tr_var : forall le dst id ty tmp,
tr_expr le dst (Csyntax.Evar id ty)
(final dst (Evar id ty)) (Evar id ty) tmp
| tr_deref : forall le dst e1 ty sl1 a1 tmp,
tr_expr le For_val e1 sl1 a1 tmp ->
tr_expr le dst (Csyntax.Ederef e1 ty)
(sl1 ++ final dst (Ederef' a1 ty)) (Ederef' a1 ty) tmp
| tr_field : forall le dst e1 f ty sl1 a1 tmp,
tr_expr le For_val e1 sl1 a1 tmp ->
tr_expr le dst (Csyntax.Efield e1 f ty)
(sl1 ++ final dst (Efield a1 f ty)) (Efield a1 f ty) tmp
| tr_val_effect : forall le v ty any tmp,
tr_expr le For_effects (Csyntax.Eval v ty) nil any tmp
| tr_val_value : forall le v ty a tmp,
typeof a = ty ->
(forall tge e le' m,
(forall id, In id tmp -> le'!id = le!id) ->
eval_expr tge e le' m a v) ->
tr_expr le For_val (Csyntax.Eval v ty)
nil a tmp
| tr_val_set : forall le sd v ty a any tmp,
typeof a = ty ->
(forall tge e le' m,
(forall id, In id tmp -> le'!id = le!id) ->
eval_expr tge e le' m a v) ->
tr_expr le (For_set sd) (Csyntax.Eval v ty)
(do_set sd a) any tmp
| tr_sizeof : forall le dst ty' ty tmp,
tr_expr le dst (Csyntax.Esizeof ty' ty)
(final dst (Esizeof ty' ty))
(Esizeof ty' ty) tmp
| tr_alignof : forall le dst ty' ty tmp,
tr_expr le dst (Csyntax.Ealignof ty' ty)
(final dst (Ealignof ty' ty))
(Ealignof ty' ty) tmp
| tr_valof : forall le dst e1 ty tmp sl1 a1 tmp1 sl2 a2 tmp2,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_rvalof (Csyntax.typeof e1) a1 sl2 a2 tmp2 ->
list_disjoint tmp1 tmp2 -> incl tmp1 tmp -> incl tmp2 tmp ->
tr_expr le dst (Csyntax.Evalof e1 ty)
(sl1 ++ sl2 ++ final dst a2)
a2 tmp
| tr_addrof : forall le dst e1 ty tmp sl1 a1,
tr_expr le For_val e1 sl1 a1 tmp ->
tr_expr le dst (Csyntax.Eaddrof e1 ty)
(sl1 ++ final dst (Eaddrof' a1 ty))
(Eaddrof' a1 ty) tmp
| tr_unop : forall le dst op e1 ty tmp sl1 a1,
tr_expr le For_val e1 sl1 a1 tmp ->
tr_expr le dst (Csyntax.Eunop op e1 ty)
(sl1 ++ final dst (Eunop op a1 ty))
(Eunop op a1 ty) tmp
| tr_binop : forall le dst op e1 e2 ty sl1 a1 tmp1 sl2 a2 tmp2 tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le For_val e2 sl2 a2 tmp2 ->
list_disjoint tmp1 tmp2 -> incl tmp1 tmp -> incl tmp2 tmp ->
tr_expr le dst (Csyntax.Ebinop op e1 e2 ty)
(sl1 ++ sl2 ++ final dst (Ebinop op a1 a2 ty))
(Ebinop op a1 a2 ty) tmp
| tr_cast_effects : forall le e1 ty sl1 a1 any tmp,
tr_expr le For_effects e1 sl1 a1 tmp ->
tr_expr le For_effects (Csyntax.Ecast e1 ty)
sl1
any tmp
| tr_cast_val : forall le dst e1 ty sl1 a1 tmp,
tr_expr le For_val e1 sl1 a1 tmp ->
tr_expr le dst (Csyntax.Ecast e1 ty)
(sl1 ++ final dst (Ecast a1 ty))
(Ecast a1 ty) tmp
| tr_seqand_val : forall le e1 e2 ty sl1 a1 tmp1 t sl2 a2 tmp2 tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le (For_set (SDbase type_bool ty t)) e2 sl2 a2 tmp2 ->
list_disjoint tmp1 tmp2 ->
incl tmp1 tmp -> incl tmp2 tmp -> In t tmp ->
tr_expr le For_val (Csyntax.Eseqand e1 e2 ty)
(sl1 ++ makeif a1 (makeseq sl2)
(Sset t (Econst_int Int.zero ty)) :: nil )
(Etempvar t ty) tmp
| tr_seqand_effects : forall le e1 e2 ty sl1 a1 tmp1 sl2 a2 tmp2 any tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le For_effects e2 sl2 a2 tmp2 ->
list_disjoint tmp1 tmp2 ->
incl tmp1 tmp -> incl tmp2 tmp ->
tr_expr le For_effects (Csyntax.Eseqand e1 e2 ty)
(sl1 ++ makeif a1 (makeseq sl2) Sskip :: nil )
any tmp
| tr_seqand_set : forall le sd e1 e2 ty sl1 a1 tmp1 t sl2 a2 tmp2 any tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le (For_set (SDcons type_bool ty t sd)) e2 sl2 a2 tmp2 ->
list_disjoint tmp1 tmp2 ->
incl tmp1 tmp -> incl tmp2 tmp -> In t tmp ->
tr_expr le (For_set sd) (Csyntax.Eseqand e1 e2 ty)
(sl1 ++ makeif a1 (makeseq sl2)
(makeseq (do_set sd (Econst_int Int.zero ty))) :: nil )
any tmp
| tr_seqor_val : forall le e1 e2 ty sl1 a1 tmp1 t sl2 a2 tmp2 tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le (For_set (SDbase type_bool ty t)) e2 sl2 a2 tmp2 ->
list_disjoint tmp1 tmp2 ->
incl tmp1 tmp -> incl tmp2 tmp -> In t tmp ->
tr_expr le For_val (Csyntax.Eseqor e1 e2 ty)
(sl1 ++ makeif a1 (Sset t (Econst_int Int.one ty))
(makeseq sl2) :: nil )
(Etempvar t ty) tmp
| tr_seqor_effects : forall le e1 e2 ty sl1 a1 tmp1 sl2 a2 tmp2 any tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le For_effects e2 sl2 a2 tmp2 ->
list_disjoint tmp1 tmp2 ->
incl tmp1 tmp -> incl tmp2 tmp ->
tr_expr le For_effects (Csyntax.Eseqor e1 e2 ty)
(sl1 ++ makeif a1 Sskip (makeseq sl2) :: nil )
any tmp
| tr_seqor_set : forall le sd e1 e2 ty sl1 a1 tmp1 t sl2 a2 tmp2 any tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le (For_set (SDcons type_bool ty t sd)) e2 sl2 a2 tmp2 ->
list_disjoint tmp1 tmp2 ->
incl tmp1 tmp -> incl tmp2 tmp -> In t tmp ->
tr_expr le (For_set sd) (Csyntax.Eseqor e1 e2 ty)
(sl1 ++ makeif a1 (makeseq (do_set sd (Econst_int Int.one ty)))
(makeseq sl2) :: nil )
any tmp
| tr_condition_val : forall le e1 e2 e3 ty sl1 a1 tmp1 sl2 a2 tmp2 sl3 a3 tmp3 t tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le (For_set (SDbase ty ty t)) e2 sl2 a2 tmp2 ->
tr_expr le (For_set (SDbase ty ty t)) e3 sl3 a3 tmp3 ->
list_disjoint tmp1 tmp2 ->
list_disjoint tmp1 tmp3 ->
incl tmp1 tmp -> incl tmp2 tmp -> incl tmp3 tmp -> In t tmp ->
tr_expr le For_val (Csyntax.Econdition e1 e2 e3 ty)
(sl1 ++ makeif a1 (makeseq sl2) (makeseq sl3) :: nil )
(Etempvar t ty) tmp
| tr_condition_effects : forall le e1 e2 e3 ty sl1 a1 tmp1 sl2 a2 tmp2 sl3 a3 tmp3 any tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le For_effects e2 sl2 a2 tmp2 ->
tr_expr le For_effects e3 sl3 a3 tmp3 ->
list_disjoint tmp1 tmp2 ->
list_disjoint tmp1 tmp3 ->
incl tmp1 tmp -> incl tmp2 tmp -> incl tmp3 tmp ->
tr_expr le For_effects (Csyntax.Econdition e1 e2 e3 ty)
(sl1 ++ makeif a1 (makeseq sl2) (makeseq sl3) :: nil )
any tmp
| tr_condition_set : forall le sd t e1 e2 e3 ty sl1 a1 tmp1 sl2 a2 tmp2 sl3 a3 tmp3 any tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le (For_set (SDcons ty ty t sd)) e2 sl2 a2 tmp2 ->
tr_expr le (For_set (SDcons ty ty t sd)) e3 sl3 a3 tmp3 ->
list_disjoint tmp1 tmp2 ->
list_disjoint tmp1 tmp3 ->
incl tmp1 tmp -> incl tmp2 tmp -> incl tmp3 tmp -> In t tmp ->
tr_expr le (For_set sd) (Csyntax.Econdition e1 e2 e3 ty)
(sl1 ++ makeif a1 (makeseq sl2) (makeseq sl3) :: nil )
any tmp
| tr_assign_effects : forall le e1 e2 ty sl1 a1 tmp1 sl2 a2 tmp2 bf any tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le For_val e2 sl2 a2 tmp2 ->
list_disjoint tmp1 tmp2 ->
incl tmp1 tmp -> incl tmp2 tmp ->
tr_is_bitfield_access a1 bf ->
tr_expr le For_effects (Csyntax.Eassign e1 e2 ty)
(sl1 ++ sl2 ++ make_assign bf a1 a2 :: nil )
any tmp
| tr_assign_val : forall le dst e1 e2 ty sl1 a1 tmp1 sl2 a2 tmp2 t tmp ty1 ty2 bf,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le For_val e2 sl2 a2 tmp2 ->
incl tmp1 tmp -> incl tmp2 tmp ->
list_disjoint tmp1 tmp2 ->
In t tmp -> ~In t tmp1 -> ~In t tmp2 ->
ty1 = Csyntax.typeof e1 ->
ty2 = Csyntax.typeof e2 ->
tr_is_bitfield_access a1 bf ->
tr_expr le dst (Csyntax.Eassign e1 e2 ty)
(sl1 ++ sl2 ++
Sset t (Ecast a2 ty1) ::
make_assign bf a1 (Etempvar t ty1) ::
final dst (make_assign_value bf (Etempvar t ty1)))
(make_assign_value bf (Etempvar t ty1)) tmp
| tr_assignop_effects : forall le op e1 e2 tyres ty ty1 sl1 a1 tmp1 sl2 a2 tmp2 bf sl3 a3 tmp3 any tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le For_val e2 sl2 a2 tmp2 ->
ty1 = Csyntax.typeof e1 ->
tr_rvalof ty1 a1 sl3 a3 tmp3 ->
list_disjoint tmp1 tmp2 -> list_disjoint tmp1 tmp3 -> list_disjoint tmp2 tmp3 ->
incl tmp1 tmp -> incl tmp2 tmp -> incl tmp3 tmp ->
tr_is_bitfield_access a1 bf ->
tr_expr le For_effects (Csyntax.Eassignop op e1 e2 tyres ty)
(sl1 ++ sl2 ++ sl3 ++ make_assign bf a1 (Ebinop op a3 a2 tyres) :: nil )
any tmp
| tr_assignop_val : forall le dst op e1 e2 tyres ty sl1 a1 tmp1 sl2 a2 tmp2 sl3 a3 tmp3 t bf tmp ty1,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_expr le For_val e2 sl2 a2 tmp2 ->
tr_rvalof ty1 a1 sl3 a3 tmp3 ->
list_disjoint tmp1 tmp2 -> list_disjoint tmp1 tmp3 -> list_disjoint tmp2 tmp3 ->
incl tmp1 tmp -> incl tmp2 tmp -> incl tmp3 tmp ->
In t tmp -> ~In t tmp1 -> ~In t tmp2 -> ~In t tmp3 ->
ty1 = Csyntax.typeof e1 ->
tr_is_bitfield_access a1 bf ->
tr_expr le dst (Csyntax.Eassignop op e1 e2 tyres ty)
(sl1 ++ sl2 ++ sl3 ++
Sset t (Ecast (Ebinop op a3 a2 tyres) ty1) ::
make_assign bf a1 (Etempvar t ty1) ::
final dst (make_assign_value bf (Etempvar t ty1)))
(make_assign_value bf (Etempvar t ty1)) tmp
| tr_postincr_effects : forall le id e1 ty ty1 sl1 a1 tmp1 sl2 a2 tmp2 bf any tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_rvalof ty1 a1 sl2 a2 tmp2 ->
ty1 = Csyntax.typeof e1 ->
incl tmp1 tmp -> incl tmp2 tmp ->
list_disjoint tmp1 tmp2 ->
tr_is_bitfield_access a1 bf ->
tr_expr le For_effects (Csyntax.Epostincr id e1 ty)
(sl1 ++ sl2 ++ make_assign bf a1 (transl_incrdecr id a2 ty1) :: nil )
any tmp
| tr_postincr_val : forall le dst id e1 ty sl1 a1 tmp1 bf t ty1 tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
incl tmp1 tmp -> In t tmp -> ~In t tmp1 ->
ty1 = Csyntax.typeof e1 ->
tr_is_bitfield_access a1 bf ->
tr_expr le dst (Csyntax.Epostincr id e1 ty)
(sl1 ++ make_set bf t a1 ::
make_assign bf a1 (transl_incrdecr id (Etempvar t ty1) ty1) ::
final dst (Etempvar t ty1))
(Etempvar t ty1) tmp
| tr_comma : forall le dst e1 e2 ty sl1 a1 tmp1 sl2 a2 tmp2 tmp,
tr_expr le For_effects e1 sl1 a1 tmp1 ->
tr_expr le dst e2 sl2 a2 tmp2 ->
list_disjoint tmp1 tmp2 ->
incl tmp1 tmp -> incl tmp2 tmp ->
tr_expr le dst (Csyntax.Ecomma e1 e2 ty) (sl1 ++ sl2) a2 tmp
| tr_call_effects : forall le e1 el2 ty sl1 a1 tmp1 sl2 al2 tmp2 any tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_exprlist le el2 sl2 al2 tmp2 ->
list_disjoint tmp1 tmp2 ->
incl tmp1 tmp -> incl tmp2 tmp ->
tr_expr le For_effects (Csyntax.Ecall e1 el2 ty)
(sl1 ++ sl2 ++ Scall None a1 al2 :: nil )
any tmp
| tr_call_val : forall le dst e1 el2 ty sl1 a1 tmp1 sl2 al2 tmp2 t tmp,
dst <> For_effects ->
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_exprlist le el2 sl2 al2 tmp2 ->
list_disjoint tmp1 tmp2 -> In t tmp ->
incl tmp1 tmp -> incl tmp2 tmp ->
tr_expr le dst (Csyntax.Ecall e1 el2 ty)
(sl1 ++ sl2 ++ Scall (Some t) a1 al2 :: final dst (Etempvar t ty))
(Etempvar t ty) tmp
| tr_builtin_effects : forall le ef tyargs el ty sl al tmp1 any tmp,
tr_exprlist le el sl al tmp1 ->
incl tmp1 tmp ->
tr_expr le For_effects (Csyntax.Ebuiltin ef tyargs el ty)
(sl ++ Sbuiltin None ef tyargs al :: nil )
any tmp
| tr_builtin_val : forall le dst ef tyargs el ty sl al tmp1 t tmp,
dst <> For_effects ->
tr_exprlist le el sl al tmp1 ->
In t tmp -> incl tmp1 tmp ->
tr_expr le dst (Csyntax.Ebuiltin ef tyargs el ty)
(sl ++ Sbuiltin (Some t) ef tyargs al :: final dst (Etempvar t ty))
(Etempvar t ty) tmp
| tr_paren_val : forall le e1 tycast ty sl1 a1 t tmp,
tr_expr le (For_set (SDbase tycast ty t)) e1 sl1 a1 tmp ->
In t tmp ->
tr_expr le For_val (Csyntax.Eparen e1 tycast ty)
sl1
(Etempvar t ty) tmp
| tr_paren_effects : forall le e1 tycast ty sl1 a1 tmp any,
tr_expr le For_effects e1 sl1 a1 tmp ->
tr_expr le For_effects (Csyntax.Eparen e1 tycast ty) sl1 any tmp
| tr_paren_set : forall le t sd e1 tycast ty sl1 a1 tmp any,
tr_expr le (For_set (SDcons tycast ty t sd)) e1 sl1 a1 tmp ->
In t tmp ->
tr_expr le (For_set sd) (Csyntax.Eparen e1 tycast ty) sl1 any tmp

with tr_exprlist : temp_env -> Csyntax.exprlist -> list statement -> list expr -> list ident -> Prop :=
| tr_nil : forall le tmp,
tr_exprlist le Csyntax.Enil nil nil tmp
| tr_cons : forall le e1 el2 sl1 a1 tmp1 sl2 al2 tmp2 tmp,
tr_expr le For_val e1 sl1 a1 tmp1 ->
tr_exprlist le el2 sl2 al2 tmp2 ->
list_disjoint tmp1 tmp2 ->
incl tmp1 tmp -> incl tmp2 tmp ->
tr_exprlist le (Csyntax.Econs e1 el2) (sl1 ++ sl2) (a1 :: al2) tmp.

Scheme tr_expr_ind2 := Minimality for tr_expr Sort Prop
with tr_exprlist_ind2 := Minimality for tr_exprlist Sort Prop.
Combined Scheme tr_expr_exprlist from tr_expr_ind2 , tr_exprlist_ind2 .

Useful invariance properties.

Lemma tr_expr_invariant :
forall le dst r sl a tmps, tr_expr le dst r sl a tmps ->
forall le', (forall x, In x tmps -> le'!x = le!x) ->
tr_expr le' dst r sl a tmps
with tr_exprlist_invariant :
forall le rl sl al tmps, tr_exprlist le rl sl al tmps ->
forall le', (forall x, In x tmps -> le'!x = le!x) ->
tr_exprlist le' rl sl al tmps.
Proof.
induction 1; intros; econstructor; eauto.
intros. apply H0. intros. transitivity (le'!id); auto.
intros. apply H0. auto. intros. transitivity (le'!id); auto.
induction 1; intros; econstructor; eauto.
Qed.

Lemma tr_rvalof_monotone :
forall ty a sl b tmps, tr_rvalof ty a sl b tmps ->
forall tmps', incl tmps tmps' -> tr_rvalof ty a sl b tmps'.
Proof.
induction 1; intros; econstructor; unfold incl in *; eauto.
Qed.

Lemma tr_expr_monotone :
forall le dst r sl a tmps, tr_expr le dst r sl a tmps ->
forall tmps', incl tmps tmps' -> tr_expr le dst r sl a tmps'
with tr_exprlist_monotone :
forall le rl sl al tmps, tr_exprlist le rl sl al tmps ->
forall tmps', incl tmps tmps' -> tr_exprlist le rl sl al tmps'.
Proof.
specialize tr_rvalof_monotone . intros RVALOF.
induction 1; intros; econstructor; unfold incl in *; eauto.
induction 1; intros; econstructor; unfold incl in *; eauto.
Qed.

Top-level translation


The "top-level" translation is equivalent to tr_expr above for source terms. It brings additional flexibility in the matching between Csyntax values and Cminor expressions: in the case of tr_expr, the Cminor expression must not depend on memory, while in the case of tr_top it can depend on the current memory state.

Section TR_TOP .

Variable ge : genv .
Variable e : env .
Variable le : temp_env .
Variable m : mem .

Inductive tr_top : destination -> Csyntax.expr -> list statement -> expr -> list ident -> Prop :=
| tr_top_val_val : forall v ty a tmp,
typeof a = ty -> eval_expr ge e le m a v ->
tr_top For_val (Csyntax.Eval v ty) nil a tmp
| tr_top_base : forall dst r sl a tmp,
tr_expr le dst r sl a tmp ->
tr_top dst r sl a tmp.

End TR_TOP .

Translation of statements


Inductive tr_expression : Csyntax.expr -> statement -> expr -> Prop :=
| tr_expression_intro : forall r sl a tmps,
(forall ge e le m, tr_top ge e le m For_val r sl a tmps) ->
tr_expression r (makeseq sl) a.

Inductive tr_expr_stmt : Csyntax.expr -> statement -> Prop :=
| tr_expr_stmt_intro : forall r sl a tmps,
(forall ge e le m, tr_top ge e le m For_effects r sl a tmps) ->
tr_expr_stmt r (makeseq sl).

Inductive tr_if : Csyntax.expr -> statement -> statement -> statement -> Prop :=
| tr_if_intro : forall r s1 s2 sl a tmps,
(forall ge e le m, tr_top ge e le m For_val r sl a tmps) ->
tr_if r s1 s2 (makeseq (sl ++ makeif a s1 s2 :: nil )).

Inductive tr_stmt : Csyntax.statement -> statement -> Prop :=
| tr_skip :
tr_stmt Csyntax.Sskip Sskip
| tr_do : forall r s,
tr_expr_stmt r s ->
tr_stmt (Csyntax.Sdo r) s
| tr_seq : forall s1 s2 ts1 ts2,
tr_stmt s1 ts1 -> tr_stmt s2 ts2 ->
tr_stmt (Csyntax.Ssequence s1 s2) (Ssequence ts1 ts2)
| tr_ifthenelse_empty : forall r s' a,
tr_expression r s' a ->
tr_stmt (Csyntax.Sifthenelse r Csyntax.Sskip Csyntax.Sskip ) (Ssequence s' Sskip )
| tr_ifthenelse : forall r s1 s2 s' a ts1 ts2,
tr_expression r s' a ->
tr_stmt s1 ts1 -> tr_stmt s2 ts2 ->
tr_stmt (Csyntax.Sifthenelse r s1 s2) (Ssequence s' (Sifthenelse a ts1 ts2))
| tr_while : forall r s1 s' ts1,
tr_if r Sskip Sbreak s' ->
tr_stmt s1 ts1 ->
tr_stmt (Csyntax.Swhile r s1)
(Sloop (Ssequence s' ts1) Sskip )
| tr_dowhile : forall r s1 s' ts1,
tr_if r Sskip Sbreak s' ->
tr_stmt s1 ts1 ->
tr_stmt (Csyntax.Sdowhile r s1)
(Sloop ts1 s')
| tr_for_1 : forall r s3 s4 s' ts3 ts4,
tr_if r Sskip Sbreak s' ->
tr_stmt s3 ts3 ->
tr_stmt s4 ts4 ->
tr_stmt (Csyntax.Sfor Csyntax.Sskip r s3 s4)
(Sloop (Ssequence s' ts4) ts3)
| tr_for_2 : forall s1 r s3 s4 s' ts1 ts3 ts4,
tr_if r Sskip Sbreak s' ->
s1 <> Csyntax.Sskip ->
tr_stmt s1 ts1 ->
tr_stmt s3 ts3 ->
tr_stmt s4 ts4 ->
tr_stmt (Csyntax.Sfor s1 r s3 s4)
(Ssequence ts1 (Sloop (Ssequence s' ts4) ts3))
| tr_break :
tr_stmt Csyntax.Sbreak Sbreak
| tr_continue :
tr_stmt Csyntax.Scontinue Scontinue
| tr_return_none :
tr_stmt (Csyntax.Sreturn None ) (Sreturn None )
| tr_return_some : forall r s' a,
tr_expression r s' a ->
tr_stmt (Csyntax.Sreturn (Some r)) (Ssequence s' (Sreturn (Some a)))
| tr_switch : forall r ls s' a tls,
tr_expression r s' a ->
tr_lblstmts ls tls ->
tr_stmt (Csyntax.Sswitch r ls) (Ssequence s' (Sswitch a tls))
| tr_label : forall lbl s ts,
tr_stmt s ts ->
tr_stmt (Csyntax.Slabel lbl s) (Slabel lbl ts)
| tr_goto : forall lbl,
tr_stmt (Csyntax.Sgoto lbl) (Sgoto lbl)

with tr_lblstmts : Csyntax.labeled_statements -> labeled_statements -> Prop :=
| tr_ls_nil :
tr_lblstmts Csyntax.LSnil LSnil
| tr_ls_cons : forall c s ls ts tls,
tr_stmt s ts ->
tr_lblstmts ls tls ->
tr_lblstmts (Csyntax.LScons c s ls) (LScons c ts tls).

Correctness proof with respect to the specification.


Properties of the monad


Remark bind_inversion :
forall (A B: Type) (f: mon A) (g: A -> mon B) (y: B) (z1 z3: generator ) I,
bind f g z1 = Res y z3 I ->
exists x, exists z2, exists I1, exists I2,
f z1 = Res x z2 I1 /\ g x z2 = Res y z3 I2.
Proof.
intros until I. unfold bind . destruct (f z1).
congruence.
caseEq (g a g'); intros; inv H0.
econstructor; econstructor; econstructor; econstructor; eauto.
Qed.

Remark bind2_inversion :
forall (A B Csyntax: Type) (f: mon (A*B)) (g: A -> B -> mon Csyntax) (y: Csyntax) (z1 z3: generator ) I,
bind2 f g z1 = Res y z3 I ->
exists x1, exists x2, exists z2, exists I1, exists I2,
f z1 = Res (x1,x2) z2 I1 /\ g x1 x2 z2 = Res y z3 I2.
Proof.
unfold bind2 . intros.
exploit bind_inversion ; eauto.
intros [[x1 x2] [z2 [I1 [I2 [P Q]]]]]. simpl in Q.
exists x1; exists x2; exists z2; exists I1; exists I2; auto.
Qed.

Ltac monadInv1 H :=
match type of H with
| (Res _ _ _ = Res _ _ _) =>
inversion H; clear H; try subst
| (@ret _ _ _ = Res _ _ _) =>
inversion H; clear H; try subst
| (@error _ _ _ = Res _ _ _) =>
inversion H
| (bind ?F ?G ?Z = Res ?X ?Z' ?I) =>
let x := fresh "x" in (
let z := fresh "z" in (
let I1 := fresh "I" in (
let I2 := fresh "I" in (
let EQ1 := fresh "EQ" in (
let EQ2 := fresh "EQ" in (
destruct (bind_inversion _ _ F G X Z Z' I H) as [x [z [I1 [I2 [EQ1 EQ2]]]]];
clear H;
try (monadInv1 EQ2)))))))
| (bind2 ?F ?G ?Z = Res ?X ?Z' ?I) =>
let x := fresh "x" in (
let y := fresh "y" in (
let z := fresh "z" in (
let I1 := fresh "I" in (
let I2 := fresh "I" in (
let EQ1 := fresh "EQ" in (
let EQ2 := fresh "EQ" in (
destruct (bind2_inversion _ _ _ F G X Z Z' I H) as [x [y [z [I1 [I2 [EQ1 EQ2]]]]]];
clear H;
try (monadInv1 EQ2))))))))
end.

Ltac monadInv H :=
match type of H with
| (@ret _ _ _ = Res _ _ _) => monadInv1 H
| (@error _ _ _ = Res _ _ _) => monadInv1 H
| (bind ?F ?G ?Z = Res ?X ?Z' ?I) => monadInv1 H
| (bind2 ?F ?G ?Z = Res ?X ?Z' ?I) => monadInv1 H
| (?F _ _ _ _ _ _ _ _ = Res _ _ _) =>
((progress simpl in H) || unfold F in H); monadInv1 H
| (?F _ _ _ _ _ _ _ = Res _ _ _) =>
((progress simpl in H) || unfold F in H); monadInv1 H
| (?F _ _ _ _ _ _ = Res _ _ _) =>
((progress simpl in H) || unfold F in H); monadInv1 H
| (?F _ _ _ _ _ = Res _ _ _) =>
((progress simpl in H) || unfold F in H); monadInv1 H
| (?F _ _ _ _ = Res _ _ _) =>
((progress simpl in H) || unfold F in H); monadInv1 H
| (?F _ _ _ = Res _ _ _) =>
((progress simpl in H) || unfold F in H); monadInv1 H
| (?F _ _ = Res _ _ _) =>
((progress simpl in H) || unfold F in H); monadInv1 H
| (?F _ = Res _ _ _) =>
((progress simpl in H) || unfold F in H); monadInv1 H
end.

Freshness and separation properties.


Definition within (id: ident ) (g1 g2: generator ) : Prop :=
Ple (gen_next g1) id /\ Plt id (gen_next g2).

Lemma gensym_within :
forall ty g1 id g2 I,
gensym ty g1 = Res id g2 I -> within id g1 g2.
Proof.
intros. monadInv H. split. apply Ple_refl . apply Plt_succ .
Qed.

Lemma within_widen :
forall id g1 g2 g1' g2',
within id g1 g2 ->
Ple (gen_next g1') (gen_next g1) ->
Ple (gen_next g2) (gen_next g2') ->
within id g1' g2'.
Proof.
intros. destruct H. split.
eapply Ple_trans ; eauto.
eapply Plt_Ple_trans ; eauto.
Qed.

Definition contained (l: list ident ) (g1 g2: generator ) : Prop :=
forall id, In id l -> within id g1 g2.

Lemma contained_nil :
forall g1 g2, contained nil g1 g2.
Proof.
intros; red; intros; contradiction.
Qed.

Lemma contained_widen :
forall l g1 g2 g1' g2',
contained l g1 g2 ->
Ple (gen_next g1') (gen_next g1) ->
Ple (gen_next g2) (gen_next g2') ->
contained l g1' g2'.
Proof.
intros; red; intros. eapply within_widen ; eauto.
Qed.

Lemma contained_cons :
forall id l g1 g2,
within id g1 g2 -> contained l g1 g2 -> contained (id :: l) g1 g2.
Proof.
intros; red; intros. simpl in H1; destruct H1. subst id0. auto. auto.
Qed.

Lemma contained_app :
forall l1 l2 g1 g2,
contained l1 g1 g2 -> contained l2 g1 g2 -> contained (l1 ++ l2) g1 g2.
Proof.
intros; red; intros. destruct (in_app_or _ _ _ H1); auto.
Qed.

Lemma contained_disjoint :
forall g1 l1 g2 l2 g3,
contained l1 g1 g2 -> contained l2 g2 g3 -> list_disjoint l1 l2.
Proof.
intros; red; intros. red; intro; subst y.
exploit H; eauto. intros [A B]. exploit H0; eauto. intros [C D].
elim (Plt_strict x). apply Plt_Ple_trans with (gen_next g2); auto.
Qed.

Lemma contained_notin :
forall g1 l g2 id g3,
contained l g1 g2 -> within id g2 g3 -> ~In id l.
Proof.
intros; red; intros. exploit H; eauto. intros [C D]. destruct H0 as [A B].
elim (Plt_strict id). apply Plt_Ple_trans with (gen_next g2); auto.
Qed.

Hint Resolve gensym_within within_widen contained_widen
contained_cons contained_app contained_disjoint
contained_notin contained_nil
incl_refl incl_tl incl_app incl_appl incl_appr incl_same_head incl_cons
in_eq in_cons in_or_app
Ple_trans Ple_refl: gensym.

Properties of destinations


Definition dest_below (dst: destination ) (g: generator ) : Prop :=
match dst with
| For_set sd => Plt (sd_temp sd) g.(gen_next )
| _ => True
end.

Lemma dest_below_le :
forall dst g1 g2,
dest_below dst g1 -> Ple g1.(gen_next ) g2.(gen_next ) -> dest_below dst g2.
Proof.
intros. destruct dst; simpl in *; eauto using Plt_Ple_trans .
Qed.

Remark dest_for_val_below : forall g, dest_below For_val g.
Proof.
intros; simpl; auto. Qed.

Remark dest_for_effect_below : forall g, dest_below For_effects g.
Proof.
intros; simpl; auto. Qed.

Lemma dest_for_set_base_below : forall tmp tycast ty g1 g2,
within tmp g1 g2 -> dest_below (For_set (SDbase tycast ty tmp)) g2.
Proof.
intros. destruct H. auto.
Qed.

Hint Resolve dest_below_le dest_for_set_base_below : gensym.
Local Hint Resolve dest_for_val_below dest_for_effect_below : core.

Properties of temp_for_sd


Definition good_temp_for_sd (ty: type ) (tmp: ident ) (sd: set_destination ) (g1 g2 g3: generator ) : Prop :=
Plt (sd_temp sd) g1.(gen_next )
/\ Ple g1.(gen_next ) g2.(gen_next )
/\ Ple g2.(gen_next ) g3.(gen_next )
/\ if type_eq ty (sd_head_type sd) then tmp = sd_temp sd else within tmp g2 g3.

Lemma temp_for_sd_charact : forall ty tmp sd g1 g2 g3 I,
dest_below (For_set sd) g1 ->
temp_for_sd ty sd g2 = Res tmp g3 I ->
Ple g1.(gen_next ) g2.(gen_next ) ->
good_temp_for_sd ty tmp sd g1 g2 g3.
Proof.
unfold temp_for_sd , good_temp_for_sd ; intros. destruct type_eq .
- inv H0. tauto.
- eauto with gensym.
Qed.

Lemma dest_for_set_cons_below : forall tycast ty tmp sd g1 g2 g3,
good_temp_for_sd ty tmp sd g1 g2 g3 ->
dest_below (For_set (SDcons tycast ty tmp sd)) g3.
Proof.
intros until g3; intros (P & Q & R & S). simpl. destruct type_eq .
- subst tmp. unfold Ple , Plt in *; lia.
- destruct S; auto.
Qed.

Lemma sd_temp_notin :
forall sd g1 g2 l, dest_below (For_set sd) g1 -> contained l g1 g2 -> ~In (sd_temp sd) l.
Proof.
intros. simpl in H. red; intros. exploit H0; eauto. intros [A B].
elim (Plt_strict (sd_temp sd)). apply Plt_Ple_trans with (gen_next g1); auto.
Qed.

Definition used_temp_for_sd (ty: type ) (tmp: ident ) (sd: set_destination ) : list ident :=
if type_eq ty (sd_head_type sd) then nil else tmp :: nil .

Lemma temp_for_sd_disj : forall tmp1 tmp2 ty t sd g1 g2 g3 g4,
good_temp_for_sd ty t sd g1 g2 g3 ->
contained tmp1 g1 g2 ->
contained tmp2 g3 g4 ->
list_disjoint tmp1 (t :: tmp2).
Proof.
intros. destruct H as (P & Q & R & S).
apply list_disjoint_cons_r ; eauto with gensym.
destruct type_eq .
- subst t. eapply sd_temp_notin ; eauto.
- eauto with gensym.
Qed.

Lemma temp_for_sd_in : forall tmp ty t sd g1 g2 g3,
good_temp_for_sd ty t sd g1 g2 g3 ->
In t (sd_temp sd :: used_temp_for_sd ty t sd ++ tmp).
Proof.
intros. destruct H as (P & Q & R & S). unfold used_temp_for_sd . destruct type_eq .
- subst t. auto with coqlib.
- simpl; auto.
Qed.

Lemma temp_for_sd_contained : forall ty t sd g1 g2 g3,
good_temp_for_sd ty t sd g1 g2 g3 ->
contained (used_temp_for_sd ty t sd) g2 g3.
Proof.
intros. destruct H as (P & Q & R & S). unfold used_temp_for_sd .
destruct type_eq ; eauto with gensym.
Qed.

Hint Resolve temp_for_sd_charact dest_for_set_cons_below
sd_temp_notin temp_for_sd_disj temp_for_sd_in temp_for_sd_contained: gensym.

Correctness of the translation functions


Lemma finish_meets_spec_1 :
forall dst sl a sl' a',
finish dst sl a = (sl', a') -> sl' = sl ++ final dst a.
Proof.
intros. destruct dst; simpl in *; inv H; rewrite ? app_nil_r ; auto.
Qed.

Lemma finish_meets_spec_2 :
forall dst sl a sl' a',
finish dst sl a = (sl', a') -> a' = a.
Proof.
intros. destruct dst; simpl in *; inv H; auto.
Qed.

Ltac UseFinish :=
match goal with
| [ H: finish _ _ _ = (_, _) |- _ ] =>
try (rewrite (finish_meets_spec_2 _ _ _ _ _ H));
try (rewrite (finish_meets_spec_1 _ _ _ _ _ H));
repeat rewrite app_ass
end.

Definition add_dest (dst: destination ) (tmps: list ident ) :=
match dst with
| For_set sd => sd_temp sd :: tmps
| _ => tmps
end.

Lemma add_dest_incl :
forall dst tmps, incl tmps (add_dest dst tmps).
Proof.
intros. destruct dst; simpl; eauto with coqlib.
Qed.

Lemma tr_expr_add_dest :
forall le dst r sl a tmps,
tr_expr le dst r sl a tmps ->
tr_expr le dst r sl a (add_dest dst tmps).
Proof.
intros. apply tr_expr_monotone with tmps; auto. apply add_dest_incl .
Qed.


Lemma is_bitfield_access_meets_spec : forall l g bf g' I,
is_bitfield_access ce l g = Res bf g' I ->
tr_is_bitfield_access l bf.
Proof.
unfold is_bitfield_access ; intros; red. destruct l; try (monadInv H; auto).
assert (AUX: forall fn id,
is_bitfield_access_aux ce fn id i g = Res bf g' I ->
exists co ofs,
ce !id = Some co /\ fn ce i (co_members co) = OK (ofs, bf)).
{ unfold is_bitfield_access_aux ; intros.
destruct ce !id as [co|]; try discriminate.
destruct (fn ce i (co_members co)) as [[ofs1 bf1]|] eqn:FN; inv H0.
exists co, ofs1; auto. }
destruct (typeof l); try discriminate; apply AUX; auto.
Qed.

Lemma transl_valof_meets_spec :
forall ty a g sl b g' I,
transl_valof ce ty a g = Res (sl, b) g' I ->
exists tmps, tr_rvalof ty a sl b tmps /\ contained tmps g g'.
Proof.
unfold transl_valof ; intros.
destruct (type_is_volatile ty) eqn:?; monadInv H.
exists (x :: nil ); split; eauto with gensym.
econstructor; eauto using is_bitfield_access_meets_spec with coqlib.
exists (@nil ident ); split; eauto with gensym. constructor; auto.
Qed.

Scheme expr_ind2 := Induction for Csyntax.expr Sort Prop
with exprlist_ind2 := Induction for Csyntax.exprlist Sort Prop.
Combined Scheme expr_exprlist_ind from expr_ind2 , exprlist_ind2 .

Lemma transl_meets_spec :
(forall r dst g sl a g' I,
transl_expr ce dst r g = Res (sl, a) g' I ->
dest_below dst g ->
exists tmps, (forall le, tr_expr le dst r sl a (add_dest dst tmps)) /\ contained tmps g g')
/\
(forall rl g sl al g' I,
transl_exprlist ce rl g = Res (sl, al) g' I ->
exists tmps, (forall le, tr_exprlist le rl sl al tmps) /\ contained tmps g g').
Proof.
apply expr_exprlist_ind ; simpl add_dest ; intros.
- (* val *)
simpl in H. destruct v; monadInv H; exists (@nil ident ); split; auto with gensym.
Opaque makeif .
+ intros. destruct dst; simpl in *; inv H2.
constructor. auto. intros; constructor.
constructor.
constructor. auto. intros; constructor.
+ intros. destruct dst; simpl in *; inv H2.
constructor. auto. intros; constructor.
constructor.
constructor. auto. intros; constructor.
+ intros. destruct dst; simpl in *; inv H2.
constructor. auto. intros; constructor.
constructor.
constructor. auto. intros; constructor.
+ intros. destruct dst; simpl in *; inv H2.
constructor. auto. intros; constructor.
constructor.
constructor. auto. intros; constructor.
- (* var *)
monadInv H; econstructor; split; auto with gensym. UseFinish. constructor.
- (* field *)
monadInv H0. exploit H; eauto. auto. intros [tmp [A B]]. UseFinish.
econstructor; split; eauto. intros; apply tr_expr_add_dest . constructor; auto.
- (* valof *)
monadInv H0. exploit H; eauto. intros [tmp1 [A B]].
exploit transl_valof_meets_spec ; eauto. intros [tmp2 [C D]]. UseFinish.
exists (tmp1 ++ tmp2); split.
intros; apply tr_expr_add_dest . econstructor; eauto with gensym.
eauto with gensym.
- (* deref *)
monadInv H0. exploit H; eauto. intros [tmp [A B]]. UseFinish.
econstructor; split; eauto. intros; apply tr_expr_add_dest . constructor; auto.
- (* addrof *)
monadInv H0. exploit H; eauto. intros [tmp [A B]]. UseFinish.
econstructor; split; eauto. intros; apply tr_expr_add_dest . econstructor; eauto.
- (* unop *)
monadInv H0. exploit H; eauto. intros [tmp [A B]]. UseFinish.
econstructor; split; eauto. intros; apply tr_expr_add_dest . constructor; auto.
- (* binop *)
monadInv H1. exploit H; eauto. intros [tmp1 [A B]].
exploit H0; eauto. intros [tmp2 [C D]]. UseFinish.
exists (tmp1 ++ tmp2); split.
intros; apply tr_expr_add_dest . econstructor; eauto with gensym.
eauto with gensym.
- (* cast *)
destruct dst.
+ (* for value *)
monadInv H0. exploit H; eauto. intros [tmp [A B]].
econstructor; split; eauto. intros; apply tr_expr_add_dest .
rewrite <- (app_nil_r sl).
apply tr_cast_val with (dst := For_val ); auto.
+ (* for effects *)
exploit H; eauto. intros [tmp [A B]].
econstructor; split; eauto. intros; eapply tr_cast_effects ; eauto.
+ (* for set *)
monadInv H0. exploit H; eauto. intros [tmp [A B]].
econstructor; split; eauto. intros; apply tr_expr_add_dest .
apply tr_cast_val with (dst := For_set sd); auto.
- (* seqand *)
monadInv H1. exploit H; eauto. intros [tmp1 [A B]].
destruct dst; monadInv EQ0.
+ (* for value *)
exploit H0; eauto with gensym. intros [tmp2 [C D]].
simpl add_dest in *.
exists (x0 :: tmp1 ++ tmp2); split.
intros; eapply tr_seqand_val ; eauto with gensym.
apply list_disjoint_cons_r ; eauto with gensym.
apply contained_cons . eauto with gensym.
apply contained_app ; eauto with gensym.
+ (* for effects *)
exploit H0; eauto with gensym. intros [tmp2 [C D]].
simpl add_dest in *.
exists (tmp1 ++ tmp2); split.
intros; eapply tr_seqand_effects ; eauto with gensym.
apply contained_app ; eauto with gensym.
+ (* for set *)
exploit H0; eauto with gensym. intros [tmp2 [C D]].
simpl add_dest in *.
exists (used_temp_for_sd ty x0 sd ++ tmp1 ++ tmp2); split.
intros; eapply tr_seqand_set ; eauto 4 with gensym; eauto 7 with gensym.
apply contained_app . eauto with gensym.
apply contained_app ; eauto with gensym.
- (* seqor *)
monadInv H1. exploit H; eauto. intros [tmp1 [A B]].
destruct dst; monadInv EQ0.
+ (* for value *)
exploit H0; eauto with gensym. intros [tmp2 [C D]].
simpl add_dest in *.
exists (x0 :: tmp1 ++ tmp2); split.
intros; eapply tr_seqor_val ; eauto with gensym.
apply list_disjoint_cons_r ; eauto with gensym.
apply contained_cons . eauto with gensym.
apply contained_app ; eauto with gensym.
+ (* for effects *)
exploit H0; eauto with gensym. intros [tmp2 [C D]].
simpl add_dest in *.
exists (tmp1 ++ tmp2); split.
intros; eapply tr_seqor_effects ; eauto with gensym.
apply contained_app ; eauto with gensym.
+ (* for set *)
exploit H0; eauto with gensym. intros [tmp2 [C D]].
simpl add_dest in *.
exists (used_temp_for_sd ty x0 sd ++ tmp1 ++ tmp2); split.
intros; eapply tr_seqor_set ; eauto 4 with gensym; eauto 7 with gensym.
apply contained_app . eauto with gensym.
apply contained_app ; eauto with gensym.
- (* condition *)
monadInv H2. exploit H; eauto. intros [tmp1 [A B]].
destruct dst; monadInv EQ0.
+ (* for value *)
exploit H0; eauto with gensym. intros [tmp2 [C D]].
exploit H1; eauto with gensym. intros [tmp3 [E F]].
simpl add_dest in *.
exists (x0 :: tmp1 ++ tmp2 ++ tmp3); split.
simpl; intros; eapply tr_condition_val ; eauto with gensym.
apply list_disjoint_cons_r ; eauto with gensym.
apply list_disjoint_cons_r ; eauto with gensym.
apply contained_cons . eauto with gensym.
apply contained_app . eauto with gensym.
apply contained_app ; eauto with gensym.
+ (* for effects *)
exploit H0; eauto. intros [tmp2 [C D]].
exploit H1; eauto. intros [tmp3 [E F]].
simpl add_dest in *.
exists (tmp1 ++ tmp2 ++ tmp3); split.
intros; eapply tr_condition_effects ; eauto with gensym.
apply contained_app ; eauto with gensym.
+ (* for test *)
exploit H0; eauto with gensym. intros [tmp2 [C D]].
exploit H1; eauto 6 with gensym. intros [tmp3 [E F]].
simpl add_dest in *.
exists (used_temp_for_sd ty x0 sd ++ tmp1 ++ tmp2 ++ tmp3); split.
intros; eapply tr_condition_set ; eauto 4 with gensym.
apply incl_cons ; eauto with gensym.
apply incl_cons ; eauto with gensym.
apply contained_app ; eauto with gensym.
apply contained_app ; eauto with gensym.
apply contained_app ; eauto with gensym.
- (* sizeof *)
monadInv H. UseFinish.
exists (@nil ident ); split; auto with gensym. constructor.
- (* alignof *)
monadInv H. UseFinish.
exists (@nil ident ); split; auto with gensym. constructor.
- (* assign *)
monadInv H1. exploit H; eauto. intros [tmp1 [A B]].
exploit H0; eauto. intros [tmp2 [C D]].
apply is_bitfield_access_meets_spec in EQ0.
destruct dst; monadInv EQ3; simpl add_dest in *.
+ (* for value *)
exists (x2 :: tmp1 ++ tmp2); split.
intros. eapply tr_assign_val with (dst := For_val ); eauto with gensym.
apply contained_cons . eauto with gensym.
apply contained_app ; eauto with gensym.
+ (* for effects *)
exists (tmp1 ++ tmp2); split.
econstructor; eauto with gensym.
apply contained_app ; eauto with gensym.
+ (* for set *)
exists (x2 :: tmp1 ++ tmp2); split.
repeat rewrite app_ass . simpl.
intros. eapply tr_assign_val with (dst := For_set sd); eauto with gensym.
apply contained_cons . eauto with gensym.
apply contained_app ; eauto with gensym.
- (* assignop *)
monadInv H1. exploit H; eauto. intros [tmp1 [A B]].
exploit H0; eauto. intros [tmp2 [C D]].
exploit transl_valof_meets_spec ; eauto. intros [tmp3 [E F]].
apply is_bitfield_access_meets_spec in EQ2.
destruct dst; monadInv EQ4; simpl add_dest in *.
+ (* for value *)
exists (x3 :: tmp1 ++ tmp2 ++ tmp3); split.
intros. eapply tr_assignop_val with (dst := For_val ); eauto 6 with gensym.
apply contained_cons . eauto 6 with gensym.
apply contained_app ; eauto 6 with gensym.
+ (* for effects *)
exists (tmp1 ++ tmp2 ++ tmp3); split.
econstructor; eauto with gensym.
apply contained_app ; eauto with gensym.
+ (* for set *)
exists (x3 :: tmp1 ++ tmp2 ++ tmp3); split.
repeat rewrite app_ass . simpl.
intros. eapply tr_assignop_val with (dst := For_set sd); eauto 6 with gensym.
apply contained_cons . eauto 6 with gensym.
apply contained_app ; eauto 6 with gensym.
- (* postincr *)
monadInv H0. exploit H; eauto. intros [tmp1 [A B]].
apply is_bitfield_access_meets_spec in EQ1.
destruct dst; monadInv EQ2; simpl add_dest in *.
+ (* for value *)
exists (x1 :: tmp1); split.
econstructor; eauto with gensym.
apply contained_cons ; eauto with gensym.
+ (* for effects *)
exploit transl_valof_meets_spec ; eauto. intros [tmp2 [C D]].
exists (tmp1 ++ tmp2); split.
econstructor; eauto with gensym.
eauto with gensym.
+ (* for set *)
repeat rewrite app_ass ; simpl.
exists (x1 :: tmp1); split.
econstructor; eauto with gensym.
apply contained_cons ; eauto with gensym.
- (* comma *)
monadInv H1. exploit H; eauto. intros [tmp1 [A B]].
exploit H0; eauto with gensym. intros [tmp2 [C D]].
exists (tmp1 ++ tmp2); split.
econstructor; eauto with gensym.
destruct dst; simpl; eauto with gensym.
apply list_disjoint_cons_r ; eauto with gensym.
simpl. eapply incl_tran . 2: apply add_dest_incl . auto with gensym.
destruct dst; simpl; auto with gensym.
apply contained_app ; eauto with gensym.
- (* call *)
monadInv H1. exploit H; eauto. intros [tmp1 [A B]].
exploit H0; eauto. intros [tmp2 [C D]].
destruct dst; monadInv EQ2; simpl add_dest in *.
+ (* for value *)
exists (x1 :: tmp1 ++ tmp2); split.
econstructor; eauto with gensym. congruence.
apply contained_cons . eauto with gensym.
apply contained_app ; eauto with gensym.
+ (* for effects *)
exists (tmp1 ++ tmp2); split.
econstructor; eauto with gensym.
apply contained_app ; eauto with gensym.
+ (* for set *)
exists (x1 :: tmp1 ++ tmp2); split.
repeat rewrite app_ass . econstructor; eauto with gensym. congruence.
apply contained_cons . eauto with gensym.
apply contained_app ; eauto with gensym.
- (* builtin *)
monadInv H0. exploit H; eauto. intros [tmp1 [A B]].
destruct dst; monadInv EQ0; simpl add_dest in *.
+ (* for value *)
exists (x0 :: tmp1); split.
econstructor; eauto with gensym. congruence.
apply contained_cons ; eauto with gensym.
+ (* for effects *)
exists tmp1; split.
econstructor; eauto with gensym.
auto.
+ (* for set *)
exists (x0 :: tmp1); split.
repeat rewrite app_ass . econstructor; eauto with gensym. congruence.
apply contained_cons ; eauto with gensym.
- (* loc *)
monadInv H.
- (* paren *)
monadInv H0.
- (* nil *)
monadInv H; exists (@nil ident ); split; auto with gensym. constructor.
- (* cons *)
monadInv H1. exploit H; eauto. intros [tmp1 [A B]].
exploit H0; eauto. intros [tmp2 [C D]].
exists (tmp1 ++ tmp2); split.
econstructor; eauto with gensym.
eauto with gensym.
Qed.

Lemma transl_expr_meets_spec :
forall r dst g sl a g' I,
transl_expr ce dst r g = Res (sl, a) g' I ->
dest_below dst g ->
exists tmps, forall ge e le m, tr_top ge e le m dst r sl a tmps.
Proof.
intros. exploit (proj1 transl_meets_spec ); eauto. intros [tmps [A B]].
exists (add_dest dst tmps); intros. apply tr_top_base . auto.
Qed.

Lemma transl_expression_meets_spec :
forall r g s a g' I,
transl_expression ce r g = Res (s, a) g' I ->
tr_expression r s a.
Proof.
intros. monadInv H. exploit transl_expr_meets_spec ; eauto.
intros [tmps A]. econstructor; eauto.
Qed.

Lemma transl_expr_stmt_meets_spec :
forall r g s g' I,
transl_expr_stmt ce r g = Res s g' I ->
tr_expr_stmt r s.
Proof.
intros. monadInv H. exploit transl_expr_meets_spec ; eauto.
intros [tmps A]. econstructor; eauto.
Qed.

Lemma transl_if_meets_spec :
forall r s1 s2 g s g' I,
transl_if ce r s1 s2 g = Res s g' I ->
tr_if r s1 s2 s.
Proof.
intros. monadInv H. exploit transl_expr_meets_spec ; eauto.
intros [tmps A]. econstructor; eauto.
Qed.

Lemma transl_stmt_meets_spec :
forall s g ts g' I, transl_stmt ce s g = Res ts g' I -> tr_stmt s ts
with transl_lblstmt_meets_spec :
forall s g ts g' I, transl_lblstmt ce s g = Res ts g' I -> tr_lblstmts s ts.
Proof.
generalize transl_expression_meets_spec transl_expr_stmt_meets_spec transl_if_meets_spec ; intros T1 T2 T3.
Opaque transl_expression transl_expr_stmt .
clear transl_stmt_meets_spec.
induction s; simpl; intros until I; intros TR;
try (monadInv TR); try (constructor; eauto).
destruct (is_Sskip s1); destruct (is_Sskip s2) eqn:?; monadInv EQ3; try (constructor; eauto).
eapply tr_ifthenelse_empty ; eauto.
destruct (is_Sskip s1); monadInv EQ4.
apply tr_for_1 ; eauto.
apply tr_for_2 ; eauto.
destruct o; monadInv TR; constructor; eauto.
clear transl_lblstmt_meets_spec.
induction s; simpl; intros until I; intros TR;
monadInv TR; constructor; eauto.
Qed.

Relational presentation for the transformation of functions, fundefs, and variables.

Inductive tr_function : Csyntax.function -> Clight.function -> Prop :=
| tr_function_intro : forall f tf,
tr_stmt f.(Csyntax.fn_body ) tf.(fn_body ) ->
fn_return tf = Csyntax.fn_return f ->
fn_callconv tf = Csyntax.fn_callconv f ->
fn_params tf = Csyntax.fn_params f ->
fn_vars tf = Csyntax.fn_vars f ->
tr_function f tf.

Lemma transl_function_spec :
forall f tf,
transl_function ce f = OK tf ->
tr_function f tf.
Proof.
unfold transl_function ; intros.
destruct (transl_stmt ce (Csyntax.fn_body f) (initial_generator tt )) eqn:T; inv H.
constructor; auto. simpl. eapply transl_stmt_meets_spec ; eauto.
Qed.

End SPEC .

Inductive tr_fundef (p: Csyntax.program ): Csyntax.fundef -> Clight.fundef -> Prop :=
| tr_internal : forall f tf,
tr_function p.(prog_comp_env ) f tf ->
tr_fundef p (Internal f) (Internal tf)
| tr_external : forall ef targs tres cconv,
tr_fundef p (External ef targs tres cconv) (External ef targs tres cconv).

Lemma transl_fundef_spec :
forall p fd tfd,
transl_fundef p.(prog_comp_env ) fd = OK tfd ->
tr_fundef p fd tfd.
Proof.
unfold transl_fundef ; intros.
destruct fd; Errors.monadInv H.
+ constructor. eapply transl_function_spec ; eauto.
+ constructor.
Qed.

Generated by coq2html

AltStyle によって変換されたページ (->オリジナル) /