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.

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).