Local Open Scope nat_scope.
Local Open Scope pred.
Definition closed_wrt_modvars c (F: assert) : Prop :=
closed_wrt_vars (modifiedvars c) F.
Definition genv_symb_injective {F V} (ge: Genv.t F V) : extspec.injective_PTree block.
Program Definition ext_compat {Z} (ora : Z) : mpred :=
fun w => joins (ghost_of w) (Some (ghost_PCM.ext_ref ora, NoneP) :: nil).
Next Obligation.
Inductive contx :=
| Stuck
| Cont: cont -> contx
| Ret: option val -> cont -> contx.
Definition assert_safe'_
(Espec : OracleKind)
(ge: genv) (f: function) (ve: env) (te: temp_env) (ctl: contx) (rho: environ)
(w : rmap) :=
forall ora (jm:juicy_mem),
ext_compat ora w ->
rho = construct_rho (filter_genv ge) ve te ->
m_phi jm = w ->
forall (LW: level w > O),
match ctl with
| Stuck => False
| Cont (Kseq s ctl') =>
jsafeN (@OK_spec Espec) ge (level w) ora (State f s ctl' ve te) jm
| Cont (Kloop1 body incr ctl') =>
jsafeN (@OK_spec Espec) ge (level w) ora (State f Sskip (Kloop1 body incr ctl') ve te) jm
| Cont (Kloop2 body incr ctl') =>
jsafeN (@OK_spec Espec) ge (level w) ora (State f (Sloop body incr) ctl' ve te) jm
| Cont (Kcall id' f' ve' te' k') =>
jsafeN (@OK_spec Espec) ge (level w) ora (State f (Sreturn None) (Kcall id' f' ve' te' k') ve te) jm
| Cont Kstop =>
jsafeN (@OK_spec Espec) ge (level w) ora (State f (Sreturn None) Kstop ve te) jm
| Cont _ => False
| Ret None ctl' =>
jsafeN (@OK_spec Espec) ge (level w) ora (State f (Sreturn None) ctl' ve te) jm
| Ret (Some v) ctl' =>  forall e v',
Clight.eval_expr ge ve te (m_dry jm) e v' ->
Cop.sem_cast v' (typeof e) (fn_return f) (m_dry jm) = Some v ->
jsafeN (@OK_spec Espec) ge (level w) ora (State f (Sreturn (Some e)) ctl' ve te) jm
end.
Program Definition assert_safe
(Espec : OracleKind) (ge: genv) (f: function) (ve: env) (te: temp_env)
(ctl: contx) : assert :=
fun rho => bupd (assert_safe'_ (Espec : OracleKind) ge f ve te ctl rho).
Next Obligation.
intro; intros.
hnf; intros.
subst.
destruct (oracle_unage _ _ H) as [jm0 [? ?]].
specialize (H0 ora jm0).
spec H0.
{simpl in H1|-*. erewrite age1_ghost_of in H1 by eauto.
eapply ext_join_unapprox; eauto. }
specialize (H0 (eq_refl _) H3).
spec H0. apply age_level in H. omega.
subst.
change (level (m_phi jm)) with (level jm).
change (level (m_phi jm0)) with (level jm0) in *.
destruct ctl; auto. destruct c; try contradiction.
eapply age_safe; eauto.
eapply age_safe; eauto.
eapply age_safe; eauto.
eapply age_safe; eauto.
destruct o; intros; auto;
eapply age_safe; eauto.
destruct o; intros; auto.
eapply age_safe; eauto.
apply (H0 e v'); auto;  rewrite (age_jm_dry H2); auto.
eapply age_safe; eauto.
Qed.
Definition list2opt {T: Type} (vl: list T) : option T :=
match vl with nil => None | x::_ => Some x end.
Definition match_venv (ve: venviron) (vars: list (ident * type)) :=
forall id, match ve id with Some (b,t) => In (id,t) vars | _ => True end.
Definition guard_environ (Delta: tycontext) (f: function) (rho: environ) : Prop :=
typecheck_environ Delta rho /\
match_venv (ve_of rho) (fn_vars f)
/\ ret_type Delta = fn_return f.
Definition weakest_pre {CS: compspecs} (Espec: OracleKind) (Delta: tycontext) c Q: assert :=
fun rho: environ =>
ALL gx: genv, ALL Delta': tycontext,
!! (tycontext_sub Delta Delta' /\ genv_cenv gx = cenv_cs) -->
unfash (believe Espec Delta' gx Delta') -->
ALL k: cont, ALL F: assert, ALL f: function,
unfash (!! (closed_wrt_modvars c F) && rguard Espec gx Delta' f (frame_ret_assert Q F) k) -->
ALL tx : Clight.temp_env, ALL vx : env,
(!! (rho = construct_rho (filter_genv gx) vx tx)) -->
((!! guard_environ Delta' f rho && funassert Delta' rho) -->
(F rho -* assert_safe Espec gx f vx tx (Cont (Kseq c k)) rho)).
Opaque semax'.
Definition semax {CS: compspecs} (Espec: OracleKind) (Delta: tycontext) P c Q :=
forall n, semax' Espec Delta P c Q n.
(* Copied from semax_switch. *)

Lemma unfash_imp:
forall {A} {NA: ageable A} (P Q: pred nat),
(@unfash A _ (P --> Q) = (@unfash A _ P) --> @unfash A _ Q)%pred.