Definition Hrel n' m m' :=
    n' = level m' /\
    (level m' < level m)%nat /\
    pures_eq (m_phi m) (m_phi m').Inductive jsafeN_:
    nat -> Z -> C -> juicy_mem -> Prop :=
  | jsafeN_0: forall z c m, jsafeN_ O z c m
  | jsafeN_step:
      forall n z c m c' m',
      jstep Hcore c m c' m' ->
      jm_bupd z (jsafeN_ n z c') m' ->
      jsafeN_ (S n) z c m
  | jsafeN_external:
      forall n z c m e args x,
      j_at_external Hcore c m = Some (e,args) ->
      ext_spec_pre Hspec e x (genv_symb ge) (sig_args (ef_sig e)) args z m ->
      (forall ret m' z' n'
         (Hargsty : Val.has_type_list args (sig_args (ef_sig e)))
         (Hretty : has_opttyp ret (sig_res (ef_sig e))),
         (n' <= n)%nat ->
         Hrel n' m m' ->
         ext_spec_post Hspec e x (genv_symb ge) (sig_res (ef_sig e)) ret z' m' ->
         exists c',
           semantics.after_external Hcore ret c (m_dry m') = Some c' /\
           jm_bupd z' (jsafeN_ n' z' c') m') ->
      jsafeN_ (S n) z c m
  | jsafeN_halted:
      forall n z c m i,
      semantics.halted Hcore c i ->
      ext_spec_exit Hspec (Some (Vint i)) z m ->
      jsafeN_ n z c m.Inductive jsafeN_:
    nat -> Z -> C -> juicy_mem -> Prop :=
  | jsafeN_0: forall z c m, jsafeN_ O z c m
  | jsafeN_step:
      forall n z c m c' m',
      jstep Hcore c m c' m' ->
      jm_bupd z (jsafeN_ n z c') m' ->
      jsafeN_ (S n) z c m
  | jsafeN_external:
      forall n z c m e args x,
      j_at_external Hcore c m = Some (e,args) ->
      ext_spec_pre Hspec e x (genv_symb ge) (sig_args (ef_sig e)) args z m ->
      (forall ret m' z' n'
         (Hargsty : Val.has_type_list args (sig_args (ef_sig e)))
         (Hretty : has_opttyp ret (sig_res (ef_sig e))),
         (n' <= n)%nat ->
         Hrel n' m m' ->
         ext_spec_post Hspec e x (genv_symb ge) (sig_res (ef_sig e)) ret z' m' ->
         exists c',
           semantics.after_external Hcore ret c (m_dry m') = Some c' /\
           jm_bupd z' (jsafeN_ n' z' c') m') ->
      jsafeN_ (S n) z c m
  | jsafeN_halted:
      forall n z c m i,
      semantics.halted Hcore c i ->
      ext_spec_exit Hspec (Some (Vint i)) z m ->
      jsafeN_ n z c m.Inductive jsafeN_:
    nat -> Z -> C -> juicy_mem -> Prop :=
  | jsafeN_0: forall z c m, jsafeN_ O z c m
  | jsafeN_step:
      forall n z c m c' m',
      jstep Hcore c m c' m' ->
      jm_bupd z (jsafeN_ n z c') m' ->
      jsafeN_ (S n) z c m
  | jsafeN_external:
      forall n z c m e args x,
      j_at_external Hcore c m = Some (e,args) ->
      ext_spec_pre Hspec e x (genv_symb ge) (sig_args (ef_sig e)) args z m ->
      (forall ret m' z' n'
         (Hargsty : Val.has_type_list args (sig_args (ef_sig e)))
         (Hretty : has_opttyp ret (sig_res (ef_sig e))),
         (n' <= n)%nat ->
         Hrel n' m m' ->
         ext_spec_post Hspec e x (genv_symb ge) (sig_res (ef_sig e)) ret z' m' ->
         exists c',
           semantics.after_external Hcore ret c (m_dry m') = Some c' /\
           jm_bupd z' (jsafeN_ n' z' c') m') ->
      jsafeN_ (S n) z c m
  | jsafeN_halted:
      forall n z c m i,
      semantics.halted Hcore c i ->
      ext_spec_exit Hspec (Some (Vint i)) z m ->
      jsafeN_ n z c m.Inductive jsafeN_:
    nat -> Z -> C -> juicy_mem -> Prop :=
  | jsafeN_0: forall z c m, jsafeN_ O z c m
  | jsafeN_step:
      forall n z c m c' m',
      jstep Hcore c m c' m' ->
      jm_bupd z (jsafeN_ n z c') m' ->
      jsafeN_ (S n) z c m
  | jsafeN_external:
      forall n z c m e args x,
      j_at_external Hcore c m = Some (e,args) ->
      ext_spec_pre Hspec e x (genv_symb ge) (sig_args (ef_sig e)) args z m ->
      (forall ret m' z' n'
         (Hargsty : Val.has_type_list args (sig_args (ef_sig e)))
         (Hretty : has_opttyp ret (sig_res (ef_sig e))),
         (n' <= n)%nat ->
         Hrel n' m m' ->
         ext_spec_post Hspec e x (genv_symb ge) (sig_res (ef_sig e)) ret z' m' ->
         exists c',
           semantics.after_external Hcore ret c (m_dry m') = Some c' /\
           jm_bupd z' (jsafeN_ n' z' c') m') ->
      jsafeN_ (S n) z c m
  | jsafeN_halted:
      forall n z c m i,
      semantics.halted Hcore c i ->
      ext_spec_exit Hspec (Some (Vint i)) z m ->
      jsafeN_ n z c m.Inductive jsafeN_:
    nat -> Z -> C -> juicy_mem -> Prop :=
  | jsafeN_0: forall z c m, jsafeN_ O z c m
  | jsafeN_step:
      forall n z c m c' m',
      jstep Hcore c m c' m' ->
      jm_bupd z (jsafeN_ n z c') m' ->
      jsafeN_ (S n) z c m
  | jsafeN_external:
      forall n z c m e args x,
      j_at_external Hcore c m = Some (e,args) ->
      ext_spec_pre Hspec e x (genv_symb ge) (sig_args (ef_sig e)) args z m ->
      (forall ret m' z' n'
         (Hargsty : Val.has_type_list args (sig_args (ef_sig e)))
         (Hretty : has_opttyp ret (sig_res (ef_sig e))),
         (n' <= n)%nat ->
         Hrel n' m m' ->
         ext_spec_post Hspec e x (genv_symb ge) (sig_res (ef_sig e)) ret z' m' ->
         exists c',
           semantics.after_external Hcore ret c (m_dry m') = Some c' /\
           jm_bupd z' (jsafeN_ n' z' c') m') ->
      jsafeN_ (S n) z c m
  | jsafeN_halted:
      forall n z c m i,
      semantics.halted Hcore c i ->
      ext_spec_exit Hspec (Some (Vint i)) z m ->
      jsafeN_ n z c m.

(* Specifications: *)
Lemma jsafe_corestep_backward: forall c m c' m' n z, jstep Hcore c m c' m' -> jsafeN_ n z c' m' -> jsafeN_ (S n) z c m.
Lemma jsafe_downward1 : forall n c m z, jsafeN_ (S n) z c m -> jsafeN_ n z c m.
Lemma jsafe_downward : forall n n' c m z, le n' n -> jsafeN_ n z c m -> jsafeN_ n' z c m.
Lemma jsafe_step'_back2 : forall {ora st m st' m' n}, jstep Hcore st m st' m' -> jsafeN_ (n-1) ora st' m' -> jsafeN_ n ora st m.
Lemma jsafe_corestepN_backward: forall z c m c' m' n n0, semantics_lemmas.corestepN (juicy_core_sem Hcore) n0 c m c' m' -> jsafeN_ (n - n0) z c' m' -> jsafeN_ n z c m.
Lemma convergent_controls_jsafe : forall m q1 q2, (j_at_external Hcore q1 m = j_at_external Hcore q2 m) -> (forall ret m q', semantics.after_external Hcore ret q1 m = Some q' -> semantics.after_external Hcore ret q2 m = Some q') -> (semantics.halted Hcore q1 = semantics.halted Hcore q2) -> (forall q' m', jstep Hcore q1 m q' m' -> jstep Hcore q2 m q' m') -> (forall n z, jsafeN_ n z q1 m -> jsafeN_ n z q2 m).
Lemma wlog_jsafeN_gt0 : forall n z q m, (lt 0 n -> jsafeN_ n z q m) -> jsafeN_ n z q m.
Lemma make_join_ext : forall (ora : Z) a c n, join_sub (Some (ext_ref ora, NoneP) :: nil) c -> joins (ghost_fmap (approx n) (approx n) a) (ghost_fmap (approx n) (approx n) c) -> join_sub (Some (ext_ref ora, NoneP) :: nil) (make_join a c).
Lemma age_safe: forall jm jm0, age jm0 jm -> forall ora c, jsafeN_ (level jm0) ora c jm0 -> jsafeN_ (level jm) ora c jm.
Lemma juicy_core_sem_preserves_corestep_fun {C} (csem: @CoreSemantics C mem) : corestep_fun csem -> corestep_fun (juicy_core_sem csem).