Section ext_trace.
Context {event : Type -> Type} {J : juicy_ext_spec (itree event unit)} {OS_state : Type}.
Variable prog : Clight.program.
Variable ext_sem : external_function -> list val -> OS_state -> option (OS_state * option val * @trace event unit).
Variable inj_mem : external_function -> list val -> mem -> @trace event unit -> OS_state -> Prop.
Variable extr_mem : external_function -> list val -> mem -> OS_state -> mem.
Variable OS_valid : OS_state -> Prop.
Notation ge := (globalenv prog).
Instance Espec : OracleKind := Build_OracleKind (itree event unit) J.
(* For any trace that the new itree (z) allows, that trace prefixed with the OS-generated trace (t) is allowed by the old itree (z0). *)
Definition consume_trace (z z' : itree event unit) (t : @trace event unit) :=
forall t', is_trace z' t' -> is_trace z (app_trace t t').
Inductive ext_safeN_trace : nat -> @trace event unit -> Ensemble (@trace event unit) -> OK_ty -> CC_core -> mem -> Prop :=
| ext_safeN_trace_0: forall z t c m, ext_safeN_trace O t (Singleton _ TEnd) z c m
| ext_safeN_trace_step:
forall n t traces z c m c' m',
cl_step ge c m c' m' ->
ext_safeN_trace n t traces z c' m' ->
ext_safeN_trace (S n) t traces z c m
| ext_safeN_trace_external:
forall n t traces z c m e args,
cl_at_external c = Some (e,args) ->
(forall s s' ret m' t' n'
(Hargsty : Val.has_type_list args (sig_args (ef_sig e)))
(Hretty : step_lemmas.has_opttyp ret (sig_res (ef_sig e))),
inj_mem e args m t s ->
ext_sem e args s = Some (s', ret, t') ->
m' = extr_mem e args m s' ->
(n' <= n)%nat ->
OS_valid s' /\ exists traces' z' c', consume_trace z z' t' /\
cl_after_external ret c = Some c' /\
ext_safeN_trace n' (app_trace t t') traces' z' c' m' /\
(forall t'', In _ traces' t'' -> In _ traces (app_trace t' t''))) ->
(forall t1, In _ traces t1 ->
exists s s' ret m' t' n', Val.has_type_list args (sig_args (ef_sig e)) /\
step_lemmas.has_opttyp ret (sig_res (ef_sig e)) /\
inj_mem e args m t s /\ ext_sem e args s = Some (s', ret, t') /\ m' = extr_mem e args m s' /\
(n' <= n)%nat /\ OS_valid s' /\ exists traces' z' c', consume_trace z z' t' /\
cl_after_external ret c = Some c' /\ ext_safeN_trace n' (app_trace t t') traces' z' c' m' /\
exists t'', In _ traces' t'' /\ t1 = app_trace t' t'') ->
ext_safeN_trace (S n) t traces z c m
| ext_safeN_trace_halted: forall n z t c m i,
halted (cl_core_sem ge) c i ->
ext_safeN_trace n t (Singleton _ TEnd) z c m.
Variable dryspec : ext_spec OK_ty.
Hypothesis extcalls_correct : forall e w b tl args z m t s, ext_spec_pre dryspec e w b tl args z m ->
inj_mem e args m t s ->
forall s' ret t', Some (s', ret, t') = ext_sem e args s ->
OS_valid s' /\ exists z', consume_trace z z' t' /\
ext_spec_post dryspec e w b (sig_res (ef_sig e)) ret z' (extr_mem e args m s').

Lemma safety_trace:
forall {CS: compspecs} (initial_oracle: OK_ty)
(EXIT: semax_prog.postcondition_allows_exit Espec tint)
(dessicate : forall (ef : external_function) jm,
ext_spec_type OK_spec ef ->
ext_spec_type dryspec ef)
(JDE: juicy_dry_ext_spec _ (@JE_spec OK_ty OK_spec) dryspec dessicate)
(DME: ext_spec_mem_evolve _ dryspec)
V G m,
@semax_prog Espec CS prog initial_oracle V G ->
Genv.init_mem prog = Some m ->
exists b, exists q, exists m',
Genv.find_symbol (Genv.globalenv prog) (prog_main prog) = Some b /\
initial_core  (cl_core_sem (globalenv prog))
0 m q m' (Vptr b Ptrofs.zero) nil /\
forall n, exists traces, ext_safeN_trace n TEnd traces initial_oracle q m'.