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

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.