Definition has_opttyp (v : option val) (t : option typ) :=
  match v, t with
    None, None => True
  | Some v, Some t => Val.has_type v t
  | _, _ => False
  end.Inductive safeN_ : nat -> Z -> C -> M -> Prop :=
  | safeN_0: forall z c m, safeN_ O z c m
  | safeN_step:
      forall n z c m c' m',
      corestep Hcore c m c' m' ->
      safeN_ n z c' m' ->
      safeN_ (S n) z c m
  | safeN_external:
      forall n z c m e args x,
      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',
           after_external Hcore ret c m' = Some c' /\
           safeN_ n' z' c' m') ->
      safeN_ (S n) z c m
  | safeN_halted:
      forall n z c m i,
      halted Hcore c i ->
      ext_spec_exit Hspec (Some (Vint i)) z m ->
      safeN_ n z c m.Inductive safeN_ : nat -> Z -> C -> M -> Prop :=
  | safeN_0: forall z c m, safeN_ O z c m
  | safeN_step:
      forall n z c m c' m',
      corestep Hcore c m c' m' ->
      safeN_ n z c' m' ->
      safeN_ (S n) z c m
  | safeN_external:
      forall n z c m e args x,
      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',
           after_external Hcore ret c m' = Some c' /\
           safeN_ n' z' c' m') ->
      safeN_ (S n) z c m
  | safeN_halted:
      forall n z c m i,
      halted Hcore c i ->
      ext_spec_exit Hspec (Some (Vint i)) z m ->
      safeN_ n z c m.Inductive safeN_ : nat -> Z -> C -> M -> Prop :=
  | safeN_0: forall z c m, safeN_ O z c m
  | safeN_step:
      forall n z c m c' m',
      corestep Hcore c m c' m' ->
      safeN_ n z c' m' ->
      safeN_ (S n) z c m
  | safeN_external:
      forall n z c m e args x,
      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',
           after_external Hcore ret c m' = Some c' /\
           safeN_ n' z' c' m') ->
      safeN_ (S n) z c m
  | safeN_halted:
      forall n z c m i,
      halted Hcore c i ->
      ext_spec_exit Hspec (Some (Vint i)) z m ->
      safeN_ n z c m.Inductive safeN_ : nat -> Z -> C -> M -> Prop :=
  | safeN_0: forall z c m, safeN_ O z c m
  | safeN_step:
      forall n z c m c' m',
      corestep Hcore c m c' m' ->
      safeN_ n z c' m' ->
      safeN_ (S n) z c m
  | safeN_external:
      forall n z c m e args x,
      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',
           after_external Hcore ret c m' = Some c' /\
           safeN_ n' z' c' m') ->
      safeN_ (S n) z c m
  | safeN_halted:
      forall n z c m i,
      halted Hcore c i ->
      ext_spec_exit Hspec (Some (Vint i)) z m ->
      safeN_ n z c m.Inductive safeN_ : nat -> Z -> C -> M -> Prop :=
  | safeN_0: forall z c m, safeN_ O z c m
  | safeN_step:
      forall n z c m c' m',
      corestep Hcore c m c' m' ->
      safeN_ n z c' m' ->
      safeN_ (S n) z c m
  | safeN_external:
      forall n z c m e args x,
      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',
           after_external Hcore ret c m' = Some c' /\
           safeN_ n' z' c' m') ->
      safeN_ (S n) z c m
  | safeN_halted:
      forall n z c m i,
      halted Hcore c i ->
      ext_spec_exit Hspec (Some (Vint i)) z m ->
      safeN_ n z c m.Definition corestep_fun  :=
       forall m q m1 q1 m2 q2 ,
       corestep Hcore q m q1 m1 ->
       corestep Hcore q m q2 m2 ->
       (q1, m1) = (q2, m2).

(* Specifications: *)
Lemma safe_corestep_forward: corestep_fun -> forall c m c' m' n z, corestep Hcore c m c' m' -> safeN_ (S n) z c m -> safeN_ n z c' m'.
Lemma safe_corestep_backward: forall c m c' m' n z, corestep Hcore c m c' m' -> safeN_ n z c' m' -> safeN_ (S n) z c m.
Lemma safe_downward1 : forall n c m z, safeN_ (S n) z c m -> safeN_ n z c m.
Lemma safe_downward : forall n n' c m z, le n' n -> safeN_ n z c m -> safeN_ n' z c m.
Lemma safe_corestepN_forward: corestep_fun -> forall z c m c' m' n n0, corestepN Hcore n0 c m c' m' -> safeN_ (n + S n0) z c m -> safeN_ n z c' m'.
Lemma safe_step'_back2 : forall {ora st m st' m' n}, corestep Hcore st m st' m' -> safeN_ (n-1) ora st' m' -> safeN_ n ora st m.
Lemma safe_corestepN_backward: forall z c m c' m' n n0, corestepN Hcore n0 c m c' m' -> safeN_ (n - n0) z c' m' -> safeN_ n z c m.
Lemma convergent_controls_safe : forall m q1 q2, (at_external Hcore q1 m = at_external Hcore q2 m) -> (forall ret m q', after_external Hcore ret q1 m = Some q' -> after_external Hcore ret q2 m = Some q') -> (halted Hcore q1 = halted Hcore q2) -> (forall q' m', corestep Hcore q1 m q' m' -> corestep Hcore q2 m q' m') -> (forall n z, safeN_ n z q1 m -> safeN_ n z q2 m).
Lemma wlog_safeN_gt0 : forall n z q m, (lt 0 n -> safeN_ n z q m) -> safeN_ n z q m.