Inductive step (ge:genv) : state -> trace -> state -> Prop :=
  | step_corestep : forall c m c' m',
    corestep Sem ge c m c' m' ->
    step ge (c,m) E0 (c',m')

  | step_ext_step : forall c m c' m' ef args tr ret,
    at_external Sem c = Some (ef,ef_sig ef,args) ->
    external_call ef ge args m tr ret m' ->
    after_external Sem (Some ret) c = Some c' ->
    step ge (c,m) tr (c',m').Inductive step (ge:genv) : state -> trace -> state -> Prop :=
  | step_corestep : forall c m c' m',
    corestep Sem ge c m c' m' ->
    step ge (c,m) E0 (c',m')

  | step_ext_step : forall c m c' m' ef args tr ret,
    at_external Sem c = Some (ef,ef_sig ef,args) ->
    external_call ef ge args m tr ret m' ->
    after_external Sem (Some ret) c = Some c' ->
    step ge (c,m) tr (c',m').Inductive step (ge:genv) : state -> trace -> state -> Prop :=
  | step_corestep : forall c m c' m',
    corestep Sem ge c m c' m' ->
    step ge (c,m) E0 (c',m')

  | step_ext_step : forall c m c' m' ef args tr ret,
    at_external Sem c = Some (ef,ef_sig ef,args) ->
    external_call ef ge args m tr ret m' ->
    after_external Sem (Some ret) c = Some c' ->
    step ge (c,m) tr (c',m').Definition main_sig : signature := mksignature (nil) (Some AST.Tint).Definition initial_state (st:state) : Prop :=
    exists b, exists vals,
      Forall2 (val_inject (Mem.flat_inj (Mem.nextblock (snd st)))) vals vals /\
      Forall2 Val.has_type vals (sig_args main_sig) /\
      Genv.find_symbol (Genv.globalenv prog) (prog_main prog) = Some b /\
      initial_core Sem (Genv.globalenv prog) (Vptr b Int.zero) vals = Some (fst st) /\
      Genv.init_mem prog = Some (snd st).(*Require that return values are int here - that's what we need below for mk_semantics*)
  Definition final_state (st:state) (i:int) : Prop :=
    halted Sem (fst st) = Some (Vint i).Definition mk_semantics: semantics :=
    Semantics step initial_state final_state (Genv.globalenv prog).

(* Specifications: *)
Lemma corestep_plus_step: forall ge c m c' m', corestep Sem ge c m c' m' -> plus step ge (c, m) E0 (c', m').
Lemma corestep_plus_plus_step: forall ge c m c' m', corestep_plus Sem ge c m c' m' -> plus step ge (c, m) E0 (c', m').
Lemma corestep_star_star_step: forall ge c m c' m', corestep_star Sem ge c m c' m' -> star step ge (c, m) E0 (c', m').
Theorem CoreCorrectness_implies_CompcertForwardSimulation: forall F1 C1 V1 F2 C2 V2 (Sem1: CoreSemantics (Genv.t F1 V1) C1 mem) (Sem2: CoreSemantics (Genv.t F2 V2) C2 mem) P1 P2 ExternIdents epts, In (P1.(prog_main), CompilerCorrectness.extern_func main_sig) ExternIdents -> P1.(prog_main) = P2.(prog_main) -> CompilerCorrectness.core_correctness (fun F C V Sem P => True) (*was: (fun F C V Sem P => (forall x, Genv.init_mem P = Some x <-> initial_mem Sem (Genv.globalenv P) x P.(prog_defs)))*) ExternIdents epts F1 C1 V1 F2 C2 V2 Sem1 Sem2 P1 P2 -> forward_simulation (mk_semantics F1 C1 V1 Sem1 P1) (mk_semantics F2 C2 V2 Sem2 P2).
Lemma transl_program_block_volatile: forall {F FF V} (P: AST.program F V) (transf: F -> FF) b, block_is_volatile (Genv.globalenv (AST.transform_program transf P)) b = block_is_volatile (Genv.globalenv P) b.
Theorem CoreCorrectnessT_implies_CompcertForwardSimulation: forall F1 C1 V1 F2 C2 (Sem1: CoreSemantics (Genv.t F1 V1) C1 mem) (Sem2: CoreSemantics (Genv.t F2 V1) C2 mem) P1 P2 ExternIdents epts (EXT: In (P1.(prog_main), CompilerCorrectness.extern_func main_sig) ExternIdents), CompilerCorrectness.core_correctnessT (fun F C V Sem P => True) (*was: (fun F C V Sem P => (forall x, Genv.init_mem P = Some x <-> initial_mem Sem (Genv.globalenv P) x P.(prog_defs)))*) ExternIdents epts F1 C1 V1 F2 C2 Sem1 Sem2 P1 P2 -> forward_simulation (mk_semantics F1 C1 V1 Sem1 P1) (mk_semantics F2 C2 V1 Sem2 P2).