Section CLN_SEM.
Definition F: Type := fundef.
Definition V: Type := type.
Definition G := genv.
Definition C := corestate.
Definition getEnv (g:G): Genv.t F V := genv_genv g.
(* We might want to define this properly or factor the machines so we don't need events here. *)
(** Transition relation *)
Inductive cl_evstep (ge: Clight.genv): forall (q: corestate) (m: mem) (T:list mem_event) (q': corestate) (m': mem), Prop :=
| evstep_assign: forall ve te k m a1 a2 loc ofs v2 v m' T1 T2 T3,
type_is_volatile (typeof a1) = false ->
eval_lvalueT ge ve te m a1 loc ofs T1 ->
eval_exprT ge ve te m a2 v2 T2 ->
Cop.sem_cast v2 (typeof a2) (typeof a1) m = Some v ->
assign_locT ge (typeof a1) m loc ofs v m' T3 ->
cl_evstep ge (State ve te (Kseq (Sassign a1 a2):: k)) m (T1++T2++T3) (State ve te k) m'
| evstep_set:   forall ve te k m id a v T,
eval_exprT ge ve te m a v T ->
cl_evstep ge (State ve te (Kseq (Sset id a) :: k)) m T (State ve (PTree.set id v te) k) m
| evstep_call_internal:   forall ve te k m optid a al tyargs tyres cc vf vargs f m1 ve' le' T1 T2 T3,
Cop.classify_fun (typeof a) = Cop.fun_case_f tyargs tyres cc ->
eval_exprT ge ve te m a vf T1 ->
eval_exprTlist ge ve te m al tyargs vargs T2 ->
Genv.find_funct ge vf = Some (Internal f) ->
type_of_function f = Tfunction tyargs tyres cc ->
list_norepet (var_names f.(fn_params) ++ var_names f.(fn_temps)) ->
forall (NRV: list_norepet (var_names f.(fn_vars))),
alloc_variablesT ge empty_env m (f.(fn_vars)) ve' m1 T3 ->
bind_parameter_temps f.(fn_params) vargs (create_undef_temps f.(fn_temps)) = Some
le' ->
cl_evstep ge (State ve te (Kseq (Scall optid a al) :: k)) m (T1++T2++T3)
(State ve' le' (Kseq f.(fn_body) :: Kseq (Sreturn None) :: Kcall optid f ve te :: k)) m1
| evstep_call_external:   forall ve te k m optid a al tyargs tyres cc vf vargs ef T1 T2,
Cop.classify_fun (typeof a) = Cop.fun_case_f tyargs tyres cc ->
eval_exprT ge ve te m a vf T1 ->
eval_exprTlist ge ve te m al tyargs vargs T2 ->
Genv.find_funct ge vf = Some (External ef tyargs tyres cc) ->
cl_evstep ge (State ve te (Kseq (Scall optid a al) :: k)) m (T1++T2) (ExtCall ef vargs optid ve te k) m
| evstep_seq: forall ve te k m s1 s2 st' m' T,
cl_evstep ge (State ve te (Kseq s1 :: Kseq s2 :: k)) m T st' m' ->
cl_evstep ge (State ve te (Kseq (Ssequence s1 s2) :: k)) m T st' m'
| evstep_skip: forall ve te k m st' m' T,
cl_evstep ge (State ve te k) m T st' m' ->
cl_evstep ge (State ve te (Kseq Sskip :: k)) m T st' m'
| evstep_continue: forall ve te k m st' m' T,
cl_evstep ge (State ve te (continue_cont k)) m T st' m' ->
cl_evstep ge (State ve te (Kseq Scontinue :: k)) m T st' m'
| evstep_break: forall ve te k m st' m' T,
cl_evstep ge (State ve te (break_cont k)) m T st' m' ->
cl_evstep ge (State ve te (Kseq Sbreak :: k)) m T st' m'
| evstep_ifthenelse:  forall ve te k m a s1 s2 v1 b T,
eval_exprT ge ve te m a v1 T ->
Cop.bool_val v1 (typeof a) m = Some b ->
cl_evstep ge (State ve te (Kseq (Sifthenelse a s1 s2) :: k)) m T (State ve te  (Kseq (if b then s1 else s2) :: k)) m
| evstep_for: forall ve te k m s1 s2,
cl_evstep ge (State ve te (Kseq (Sloop s1 s2) :: k)) m nil
(State ve te (Kseq s1 :: Kseq Scontinue :: Kloop1 s1 s2 :: k)) m
| evstep_loop2: forall ve te k m a3 s,
cl_evstep ge (State ve te (Kloop2 s a3 :: k)) m nil
(State ve te (Kseq s :: Kseq Scontinue :: Kloop1 s a3 :: k)) m
| evstep_return: forall f ve te optexp optid k m v' m' ve' te' te'' k' T,
call_cont k = Kcall optid f ve' te' :: k' ->
Mem.free_list m (Clight.blocks_of_env ge ve) = Some m' ->
match optexp with None => v' = Vundef /\ T=nil
| Some a => exists v, eval_exprT ge ve te m a v T
/\ Cop.sem_cast v (typeof a) f.(fn_return) m = Some v'
end ->
match optid with None => True /\ te''=te'
| Some id => True /\ te'' = PTree.set id v' te'
end ->
cl_evstep ge (State ve te (Kseq (Sreturn optexp) :: k)) m
(T ++ (Free (Clight.blocks_of_env ge ve)::nil))
(State ve' te'' k') m'
| evstep_switch: forall ve te k m a sl v n T,
eval_exprT ge ve te m a v T ->
Cop.sem_switch_arg v (typeof a) = Some n ->
cl_evstep ge (State ve te (Kseq (Sswitch a sl) :: k)) m T
(State ve te (Kseq (seq_of_labeled_statement (select_switch n sl)) :: Kswitch :: k)) m
| evstep_label: forall ve te k m lbl s st' m' T,
cl_evstep ge (State ve te (Kseq s :: k)) m T st' m' ->
cl_evstep ge (State ve te (Kseq (Slabel lbl s) :: k)) m T st' m'
| evstep_goto: forall f ve te k m lbl k'
(* make sure to take a step here, so that every loop ticks the clock *)
(CUR: current_function k = Some f),
find_label lbl f.(fn_body) (Kseq (Sreturn None) :: (call_cont k)) = Some k' ->
cl_evstep ge (State ve te (Kseq (Sgoto lbl) :: k)) m nil (State ve te k') m.

Lemma CLN_evstep_elim ge : forall c m T c' m' (K: cl_evstep ge c m T c' m'),
ev_elim m T m'.