Module ClightLocalize

Require Import Coqlib Maps Integers Values Memdata AST Globalenvs.
Require Import Blockset Footprint FMemOpFP GMemory FMemory FMemPerm FMemLemmas MemAux CUAST LDSimDefs Localize ValRels MemInterpolant val_casted Ctypes Floats.

Require Import AsmLocalize Clight ClightLang Clight_local ClightWD.

Lemma init_genv_iff: forall cu ge G,
    ClightLang.init_genv cu ge G <->
    G = {| Clight.genv_genv := ge; Clight.genv_cenv := cu_comp_env cu |} /\ ge_related ge (Genv.globalenv (mkprogram (cu_defs cu) (cu_public cu) 1%positive)).
Proof.
Hint Resolve FPlocalize_emp FPlocalize_union : fplocalize.
Lemma init_mem_valid_block:
  forall ge m,
    ClightLang.init_gmem ge m ->
    (forall b, Bset.belongsto (valid_block_bset m) b <-> Plt b (Genv.genv_next ge)).
Proof.

Definition env_rel (j:Bset.inj)(a b:block*type):=
  let (la,tya):=a in
  let (lb,tyb):=b in
  val_related j (Vptr la Ptrofs.zero)(Vptr lb Ptrofs.zero) /\ tya = tyb.
                 

Definition env_related (j:Bset.inj)(e e':env):Prop:=
  forall id,
  option_rel (fun (a b:block*type)=> let (la,tya):=a in let (lb,tyb):=b in val_related j (Vptr la Ptrofs.zero)(Vptr lb Ptrofs.zero) /\ tya = tyb) (e!id)(e'!id).
Definition tenv_related (j:Bset.inj)(e e':temp_env):Prop:=
  forall id, option_rel (val_related j)(e ! id)(e' ! id).
Ltac det :=
  match goal with
  | [H1: eval_expr ?ge ?sp ?e ?m ?a ?v1,
         H2: eval_expr ?ge ?sp ?e ?m ?a ?v2
     |- _ ] => pose proof (eval_expr_det _ _ _ _ _ _ H1 _ H2);
             subst v1; clear H1
  | [H1: eval_expr_fp ?ge ?sp ?e ?m ?a ?v1,
         H2: eval_expr_fp ?ge ?sp ?e ?m ?a ?v2
     |- _ ] => pose proof (eval_expr_fp_det _ _ _ _ _ _ H1 _ H2);
             subst v1; clear H1
  | [H1: ?x = ?y1, H2: ?x = ?y2 |- _] => rewrite H1 in H2; inv H2
  end.
Ltac inv_eq:=
  repeat match goal with
         | H:?P , H1: ?P |- _ => clear H
         | H: context[match ?x with _ => _ end] |- _ => destruct x eqn:?; inversion H ;subst
         | H:?P = ?Q, H1:context [ ?P ] |- _ => rewrite H in H1
         | H:?P = ?Q |- context [ ?P ] => rewrite H
         | H:Some ?P = Some ?Q |- _ => inv H
         end;
  simpl in *;subst;try contradiction;try discriminate.



Definition trans_c_fundef_ast (f:fundef): (AST.fundef function):=
  match f with
    Ctypes.Internal x => AST.Internal x
  | Ctypes.External x _ _ _ => AST.External x
  end.

Fixpoint trans_cu_defs_ast_defs (l:list (ident * globdef fundef Ctypes.type)) : list (ident * globdef (AST.fundef function) Ctypes.type):=
  match l with
    nil => nil
  | (id,x)::ls => cons (match x with
                         Gfun y => (id, Gfun (trans_c_fundef_ast y))
                       | Gvar y => (id,Gvar y)
                       end) (trans_cu_defs_ast_defs ls)
  end.
Fixpoint ef_name_notin (name:String.string)(ids:list (ident* globdef fundef type)) : bool :=
  match ids with
  | nil => true
  | (id, gd) :: ids' =>
    match gd_ef_fun_name gd with
    | Some name' => if String.string_dec name name' then false
                   else ef_name_notin name ids'
    | _ => ef_name_notin name ids'
    end
  end.
Lemma ef_name_notin_correct:
  forall name defs,
    ef_name_notin name defs = true ->
    forall id gd name',
      In (id,gd) defs ->
      gd_ef_fun_name gd = Some name' ->
      name <> name'.
Proof.
Fixpoint nodup_ef ids : bool :=
  match ids with
  | nil => true
  | (id, gd) :: ids' =>
    match gd_ef_fun_name gd with
    | Some name => ef_name_notin name ids' && nodup_ef ids'
    | None => nodup_ef ids'
    end
  end.

Lemma nodup_ef_correct:
  forall ids,
    nodup_ef ids = true ->
    forall n1 n2 id1 gd1 id2 gd2 name1 name2,
      n1 <> n2 ->
      nth_error ids n1 = Some (id1, gd1) ->
      nth_error ids n2 = Some (id2, gd2) ->
      gd_ef_fun_name gd1 = Some name1 ->
      gd_ef_fun_name gd2 = Some name2 ->
      name1 <> name2.
Proof.

Definition wdcu (cu: clight_comp_unit) : Prop :=
  nodup_ef (cu_defs cu) = true /\ nodup_gd_ident (cu_defs cu) = true.

Definition transge cu := (Genv.globalenv {|AST.prog_defs := cu_defs cu; AST.prog_public := cu_public cu; AST.prog_main := 1%positive |}).
Lemma norepet_defs_gd_ident_exists:
  forall cu,
    list_norepet (map fst (cu_defs cu)) ->
    forall b gd,
      PTree.get b (Genv.genv_defs (transge cu)) = Some gd ->
      exists id, PTree.get id (Genv.genv_symb (transge cu)) = Some b.
Proof.

Lemma nodup_gd_ident_exists:
  forall cu,
    nodup_gd_ident (cu_defs cu) = true ->
    forall b gd,
      PTree.get b (Genv.genv_defs (transge cu)) = Some gd ->
      exists id, PTree.get id (Genv.genv_symb (transge cu)) = Some b.
Proof.

Lemma nodup_gd_ident_exists':
  forall cu,
    nodup_gd_ident (cu_defs cu) = true ->
    forall b gd,
      PTree.get b (Genv.genv_defs (transge cu)) = Some gd ->
      exists id, In (id, gd) (cu_defs cu) /\ PTree.get id (Genv.genv_symb (transge cu)) = Some b.
Proof.
Lemma wdcu_goodge:
  forall cu (R:wdcu cu) b gd, (Genv.genv_defs (transge cu)) ! b = Some gd -> exists id, (Genv.genv_symb (transge cu)) ! id = Some b.
Proof.

Lemma nodup_ef_ge_norep_ef_name:
  forall cu,
    wdcu cu->
    norep_ef_name (transge cu).
Proof.
Lemma weak_valid_pointer_related:
  forall (j : Bset.inj) (bound : block) (fl : freelist)
    (m : Memory.Mem.mem) (m' : mem) (b b' : block) (ofs : Z),
    mem_related j bound fl (strip m') m ->
    construct_inj j bound fl b = Some b' ->
    Memory.Mem.weak_valid_pointer m b ofs = Mem.weak_valid_pointer m' b' ofs.
Proof.
Lemma env_related_set:
  forall j e e',
    env_related j e e'->
    forall id b b' ty,
      val_related j (Vptr b Ptrofs.zero)(Vptr b' Ptrofs.zero)->
      env_related j (PTree.set id (b,ty) e)(PTree.set id (b',ty) e').
Proof.
Section EXPR.
  Variable sge tge:Clight.genv.
  Variable j:Bset.inj.
  Hypothesis GEMATCH: ge_match_strict j (genv_genv sge)(genv_genv tge).
  Hypothesis GEQ: genv_cenv sge = genv_cenv tge.
  Definition bound:=(Genv.genv_next(genv_genv sge)).
  Hypothesis INJECT : Bset.inject j (fun b : block => Plt b bound) (fun b : block => Plt b bound).
Section SEM_EXPR.
  Variable e e':env.
  Variable le le':temp_env.
  Variable fm:FMemory.mem.
  Variable m:Memory.mem.
  Definition fl:=FMemory.Mem.freelist fm.
  Hypothesis MEMREL: mem_related j bound fl (strip fm) m.
  Definition j' := construct_inj j bound fl.
  Hypothesis ENVREL: env_related j' e' e.
  Hypothesis TENVREL: tenv_related j' le' le.
  Hypothesis NOREP: norep fl.
  Hypothesis NOOVERLAP: no_overlap fl (fun b=>Plt b bound).

  
  Lemma injective_j':
    forall b b0 b',
      j' b = Some b' ->
      j' b0 = Some b' ->
      b = b0.
Proof.
  
  Lemma bool_val_related:
    forall v ty b v',
      val_related j' v' v->
      FCop.bool_val v ty fm = Some b->
      Cop.bool_val v' ty m = Some b .
Proof.
  Lemma bool_val_fp_related:
    forall v ty b v',
      val_related j' v' v->
      Cop_fp.bool_val_fp v ty fm = Some b->
      exists b',
        Cop_fp_local.bool_val_fp v' ty m = Some b'/\FPlocalize j' b b'.
Proof.
  Lemma sem_unary_operation_localize:
    forall v v',
      val_related j' v' v->
      forall op ty resv,
        FCop.sem_unary_operation op v ty fm = Some resv->
        exists resv',
          Cop.sem_unary_operation op v' ty m = Some resv' /\
          val_related j' resv' resv.
Proof.
  Lemma sem_unary_operation_fp_localize:
    forall v v',
      val_related j' v' v->
      forall op ty,
        option_rel (FPlocalize j') (Cop_fp.sem_unary_operation_fp op v ty fm)(Cop_fp_local.sem_unary_operation_fp op v' ty m).
Proof.
  Lemma sizeof_eq:
    forall ty,
      Ctypes.sizeof sge ty = Ctypes.sizeof tge ty.
Proof.
  Lemma alignof_eq:
    forall ty,
      Ctypes.alignof sge ty = Ctypes.alignof tge ty.
Proof.
  Definition binary_related_correct
             (sem: val->type->val->type->mem->option val)
             (sem2: val->type->val->type->Memory.Mem.mem->option val) :Prop:=
    forall va tya vb tyb v,
      sem va tya vb tyb fm = Some v->
      forall va' vb',
        val_related j' va' va ->
        val_related j' vb' vb ->
        exists v',
          sem2 va' tya vb' tyb m = Some v' /\ val_related j' v' v.
  Definition binary_fp_related_correct
             (semfp: val->type->val->type->mem->option FP.t)
             (semfp2: val->type->val->type->Memory.Mem.mem->option FP.t) :Prop:=
    forall va tya vb tyb fp,
      semfp va tya vb tyb fm = Some fp->
      forall va' vb',
        val_related j' va' va->
        val_related j' vb' vb->
        exists fp',semfp2 va' tya vb' tyb m = Some fp' /\ FPlocalize j' fp fp'.
  Section MAKE_BIN.
    Variable sem_int: signedness -> int -> int -> option val.
    Variable sem_long: signedness -> int64 -> int64 -> option val.
    Variable sem_float: float -> float -> option val.
    Variable sem_single: float32 -> float32 -> option val.
    Definition notptr v:=
      match v with
      | Vptr _ _ => false
      | _ => true
      end = true.
    Hypothesis sem_int_rel:
      forall sg a b i, sem_int sg a b = Some i-> notptr i.
    Hypothesis sem_long_rel:
      forall sg a b i, sem_long sg a b = Some i-> notptr i.
    Hypothesis sem_float_rel:
      forall a b i, sem_float a b = Some i-> notptr i.
    Hypothesis sem_single_rel:
      forall a b i, sem_single a b = Some i-> notptr i.
    Lemma sem_cast_related:
      forall va va',
        val_related j' va' va->
        forall tya ty res,
          FCop.sem_cast va tya ty fm = Some res ->
          exists res',
            Cop.sem_cast va' tya ty m = Some res' /\ val_related j' res' res.
Proof.
    Lemma sem_cast_fp_related:
      forall va va',
        val_related j' va' va->
        forall tya ty fp,
          Cop_fp.sem_cast_fp va tya ty fm = Some fp ->
          exists fp', Cop_fp_local.sem_cast_fp va' tya ty m = Some fp' /\ FPlocalize j' fp fp'.
Proof.
    Lemma sem_cast_related2:
      forall va va',
        val_related j' va' va->
        forall tya ty,
          FCop.sem_cast va tya ty fm =None->
          Cop.sem_cast va' tya ty m = None.
Proof.
    Lemma sem_binarith_correct:
      binary_related_correct (FCop.sem_binarith sem_int sem_long sem_float sem_single)(Cop.sem_binarith sem_int sem_long sem_float sem_single).
Proof.

    Lemma sem_binarith_fp_correct:
      binary_fp_related_correct (Cop_fp.sem_binarith_fp sem_int sem_long sem_float sem_single)(Cop_fp_local.sem_binarith_fp sem_int sem_long sem_float sem_single).
Proof.
  End MAKE_BIN.


  
  Lemma sem_add_correct:
    binary_related_correct (FCop.sem_add sge)(Cop.sem_add tge).
Proof.
  Lemma sem_add_fp_correct:
    binary_fp_related_correct (Cop_fp.sem_add_fp sge)(Cop_fp_local.sem_add_fp tge).
Proof.
  Lemma sem_sub_correct:
    binary_related_correct (FCop.sem_sub sge)(Cop.sem_sub tge).
Proof.

  Lemma sem_sub_fp_correct:
    binary_fp_related_correct (Cop_fp.sem_sub_fp sge)(Cop_fp_local.sem_sub_fp tge).
Proof.
  Lemma sem_mul_correct:
    binary_related_correct FCop.sem_mul Cop.sem_mul .
Proof.
  Lemma sem_mul_fp_correct:
    binary_fp_related_correct Cop_fp.sem_mul_fp Cop_fp_local.sem_mul_fp .
Proof.
  Lemma sem_div_correct:
    binary_related_correct FCop.sem_div Cop.sem_div.
Proof.
  Lemma sem_div_fp_correct:
    binary_fp_related_correct Cop_fp.sem_div_fp Cop_fp_local.sem_div_fp .
Proof.
  Lemma sem_mod_correct:
    binary_related_correct FCop.sem_mod Cop.sem_mod.
Proof.
  Lemma sem_mod_fp_correct:
    binary_fp_related_correct Cop_fp.sem_mod_fp Cop_fp_local.sem_mod_fp .
Proof.
  Lemma sem_and_correct:
    binary_related_correct FCop.sem_and Cop.sem_and.
Proof.
  Lemma sem_and_fp_correct:
    binary_fp_related_correct Cop_fp.sem_and_fp Cop_fp_local.sem_and_fp .
Proof.
  Lemma sem_or_correct:
    binary_related_correct FCop.sem_or Cop.sem_or.
Proof.
  Lemma sem_or_fp_correct:
    binary_fp_related_correct Cop_fp.sem_or_fp Cop_fp_local.sem_or_fp .
Proof.
  Lemma sem_xor_correct:
    binary_related_correct FCop.sem_xor Cop.sem_xor.
Proof.
  Lemma sem_xor_fp_correct:
    binary_fp_related_correct Cop_fp.sem_xor_fp Cop_fp_local.sem_xor_fp .
Proof.
  Lemma cmp_ptr_correct:
    forall v1 v1' v2 v2',
      val_related j' v1' v1->
      val_related j' v2' v2->
      forall op res,
        FCop.cmp_ptr fm op v1 v2 = Some res->
        exists res', Cop.cmp_ptr m op v1' v2' = Some res' /\ val_related j' res' res.
Proof.
  Lemma cmp_ptr_fp_correct:
    forall v1 v1' v2 v2',
      val_related j' v1' v1->
      val_related j' v2' v2->
      forall op res,
        Cop_fp.cmp_ptr_fp fm op v1 v2 = Some res->
        exists res', Cop_fp_local.cmp_ptr_fp m op v1' v2' = Some res' /\ FPlocalize j' res res'.
Proof.
  Ltac inv_val_rel:=
    match goal with
    | H: val_related _ _ _ |- _ => inv H;try discriminate
    end.
  Ltac goal_destruct:=
    match goal with
    | H:_ |- context[if ?x then Vtrue else Vfalse] => destruct x
    end.
  Ltac solv_cmp:=
    unfold FCop.sem_cmp,Cop.sem_cmp in *;
    destruct Cop.classify_cmp eqn:?;try discriminate;
    try(eapply sem_binarith_correct;eauto;intros;inv_eq;unfold notptr,Val.of_bool;
        goal_destruct;auto;fail);
    try(inv_val_rel;inv_val_rel;inv_eq;try(eapply cmp_ptr_correct;eauto;constructor);fail).
  Lemma sem_binary_operation_localize:
    forall v1 v2 v1' v2',
      val_related j' v1' v1 ->
      val_related j' v2' v2 ->
      forall op res t1 t2,
        FCop.sem_binary_operation sge op v1 t1 v2 t2 fm = Some res ->
        exists res',
          Cop.sem_binary_operation tge op v1' t1 v2' t2 m = Some res' /\
          val_related j' res' res.
Proof.
  Lemma deref_loc_related:
    forall ty loc ofs v,
      deref_loc ty fm loc ofs v ->
      forall loc' ofs',
        val_related j' (Vptr loc' ofs')(Vptr loc ofs) ->
        exists v', Clight.deref_loc ty m loc' ofs' v' /\ val_related j' v' v.
Proof.
  Lemma sem_binary_operation_fp_localize:
    forall v1 v2 v1' v2',
      val_related j' v1' v1 ->
      val_related j' v2' v2 ->
      forall op res t1 t2,
        Cop_fp.sem_binary_operation_fp sge op v1 t1 v2 t2 fm = Some res ->
        exists res',
          Cop_fp_local.sem_binary_operation_fp tge op v1' t1 v2' t2 m = Some res' /\
          FPlocalize j' res res'.
Proof.
  Lemma eval_expr_lvalue_localize:
    (forall a v,
        ClightLang.eval_expr sge e le fm a v ->
        exists v',
          Clight.eval_expr tge e' le' m a v' /\
          val_related j' v' v) /\
    (forall a b ofs,
        ClightLang.eval_lvalue sge e le fm a b ofs ->
        exists b' ofs',
          Clight.eval_lvalue tge e' le' m a b' ofs' /\
          val_related j' (Vptr b' ofs')(Vptr b ofs)).
Proof.

  Lemma eval_expr_localize:
    forall a v,
      ClightLang.eval_expr sge e le fm a v ->
      exists v',
        Clight.eval_expr tge e' le' m a v' /\
        val_related j' v' v.
Proof.

  
  Lemma eval_lvalue_localize:
    forall a b ofs,
      ClightLang.eval_lvalue sge e le fm a b ofs ->
      exists b' ofs',
        Clight.eval_lvalue tge e' le' m a b' ofs' /\
        val_related j' (Vptr b' ofs')(Vptr b ofs).
Proof.

  Lemma deref_loc_fp_related:
    forall ty loc ofs fp,
      ClightLang.deref_loc_fp ty loc ofs fp->
      forall loc' ofs',
        val_related j' (Vptr loc' ofs')(Vptr loc ofs)->
        exists fp', Clight_local.deref_loc_fp ty loc' ofs' fp' /\ FPlocalize j' fp fp'.
Proof.
  Lemma eval_expr_lvalue_fp_localize:
    (forall a fp,
        ClightLang.eval_expr_fp sge e le fm a fp ->
        forall v (EX:ClightLang.eval_expr sge e le fm a v),
          exists fp',
            Clight_local.eval_expr_fp tge e' le' m a fp'/\ FPlocalize j' fp fp') /\
    (forall a v,
        ClightLang.eval_lvalue_fp sge e le fm a v ->
         forall b ofs (EX:ClightLang.eval_lvalue sge e le fm a b ofs),
           exists v',
             Clight_local.eval_lvalue_fp tge e' le' m a v' /\
             FPlocalize j' v v').
Proof.
  Lemma eval_expr_fp_localize:
    forall a fp,
      ClightLang.eval_expr_fp sge e le fm a fp ->
      forall v (EX:ClightLang.eval_expr sge e le fm a v),
      exists fp',
        Clight_local.eval_expr_fp tge e' le' m a fp'/\ FPlocalize j' fp fp'.
Proof.

  
  Lemma eval_lvalue_fp_localize:
    forall a v,
      ClightLang.eval_lvalue_fp sge e le fm a v ->
      forall b ofs (EX:ClightLang.eval_lvalue sge e le fm a b ofs),
      exists v',
        Clight_local.eval_lvalue_fp tge e' le' m a v' /\
        FPlocalize j' v v'.
Proof.

  Lemma eval_exprlist_localize:
    forall la tyl lv,
      ClightLang.eval_exprlist sge e le fm la tyl lv ->
      exists lv', Clight.eval_exprlist tge e' le' m la tyl lv' /\ list_forall2 (val_related j') lv' lv.
Proof.

  Lemma eval_exprlist_fp_localize:
    forall la tyl fp,
      ClightLang.eval_exprlist_fp sge e le fm la tyl fp->
      exists fp', Clight_local.eval_exprlist_fp tge e' le' m la tyl fp' /\ FPlocalize j' fp fp'.
Proof.

  Lemma assign_loc_related:
    forall loc ofs loc' ofs' v v',
      val_related j' v' v->
      val_related j' (Vptr loc' ofs')(Vptr loc ofs)->
      forall ty fm',
        ClightLang.assign_loc sge ty fm loc ofs v fm'->
        exists m',
          Clight.assign_loc tge ty m loc' ofs' v' m' /\ mem_related j bound fl (strip fm') m'.
Proof.

  Lemma assign_loc_fp_related:
    forall loc ofs loc' ofs' v v',
      val_related j' (Vptr loc' ofs')(Vptr loc ofs)->
      forall ty fp,
        ClightLang.assign_loc_fp sge ty loc ofs v fp ->
        exists fp', Clight_local.assign_loc_fp tge ty loc' ofs' v' fp' /\ FPlocalize j' fp fp'.
Proof.
End SEM_EXPR.
 
  Definition binj_to_bofsinj (f:block->option block)(x y:block*Z*Z):Prop:=
    let (tx,hi):=x in
    let (b,lo):=tx in
    let (ty,hi'):=y in
    let (b',lo'):=ty in
    f b = Some b' /\ lo = lo' /\ hi = hi'.

  Lemma env_related_l:
    forall f e e',
      env_related f e e'->
       list_forall2
         (fun i_x i_y : positive * (block * type) =>
          fst i_x = fst i_y /\
          (let (la, tya) := snd i_x in
           let (lb, tyb) := snd i_y in
           val_related f (Vptr la Ptrofs.zero) (Vptr lb Ptrofs.zero) /\ tya = tyb))
         (PTree.elements e) (PTree.elements e').
Proof.

  Lemma block_of_binding_mapping:
    forall f (x y:positive *(block*type)),
      fst x = fst y ->
      let (la, tya) := snd x in
      let (lb, tyb) := snd y in
      val_related f (Vptr la Ptrofs.zero) (Vptr lb Ptrofs.zero) /\ tya = tyb->
      binj_to_bofsinj f (block_of_binding tge x)(block_of_binding sge y).
Proof.

  Lemma env_related_l2:
    forall f e e',
      env_related f e e'->
      list_forall2 (binj_to_bofsinj f)(blocks_of_env tge e)(blocks_of_env sge e').
Proof.



  Lemma freelist_related:
    forall fm e fm' (NOREP':norep (Mem.freelist fm))(NOOVERLAP': no_overlap (Mem.freelist fm) (fun b=>Plt b bound)),
      FMemory.Mem.free_list fm (blocks_of_env sge e) = Some fm'->
      forall e' m,
        mem_related j bound (Mem.freelist fm)(strip fm) m->
        env_related (j' fm) e' e ->
        exists m',
          Memory.Mem.free_list m (blocks_of_env tge e') = Some m' /\ mem_related j bound (Mem.freelist fm)(strip fm') m'.
Proof.

  Lemma freelist_fp_related:
    forall m e1 e2 (NOREP':norep (Mem.freelist m))(NOOVERLAP': no_overlap (Mem.freelist m) (fun b=>Plt b bound)),
      env_related (j' m) e1 e2 ->
      FPlocalize (j' m) (free_list_fp (blocks_of_env sge e2)) (free_list_fp (blocks_of_env tge e1)).
Proof.
  Lemma alloc_variables_related:
    forall v fm e e' fm' (NOREP':norep (Mem.freelist fm)),
      alloc_variables sge e fm v e' fm'->
      forall m e2,
        mem_related j bound (Mem.freelist fm) (strip fm) m->
        env_related (j' fm) e2 e->
        exists e2' m', Clight.alloc_variables tge e2 m v e2' m' /\
                  mem_related j bound (Mem.freelist fm) (strip fm') m' /\
                  env_related (j' fm) e2' e'.
Proof.
  Lemma alloc_variables_fp_related:
    forall v fm fp (NOREP':norep (Mem.freelist fm))(NOOVERLAP': no_overlap (Mem.freelist fm) (fun b=>Plt b bound)),
      ClightLang.alloc_variables_fp sge fm v fp->
      forall m,
        mem_related j bound (Mem.freelist fm) (strip fm) m->
        exists fp', Clight_local.alloc_variables_fp tge m v fp' /\
               FPlocalize (j' fm) fp fp'.
Proof.
  Opaque Memory.Mem.alloc.
  Lemma tenv_related_setid:
    forall j te1 te2,
      tenv_related j te1 te2->
      forall id v v',
        val_related j v v'->
        tenv_related j (PTree.set id v te1)(PTree.set id v' te2).
Proof.
  Lemma bind_parameter_temps_related:
    forall p vargs t le,
      bind_parameter_temps p vargs t = Some le ->
      forall j vargs' t',
        list_forall2 (val_related j) vargs' vargs ->
        tenv_related j t' t->
        exists le', bind_parameter_temps p vargs' t' = Some le' /\ tenv_related j le' le.
Proof.
  Lemma env_related_empty_env:
    forall j,
      env_related j empty_env empty_env.
Proof.
  Lemma tenv_related_temps:
    forall j t,
      tenv_related j (create_undef_temps t) (create_undef_temps t).
Proof.
  Lemma function_entry2_related:
    forall fm f vargs e le fm' (NOREP':norep (Mem.freelist fm)),
      ClightLang.function_entry2 sge f vargs fm e le fm'->
      forall vargs' m,
        list_forall2 (val_related (j' fm)) vargs' vargs->
        mem_related j bound (fl fm) (strip fm) m ->
        exists e' m' le', Clight_local.function_entry2 tge f vargs' m e' le' m' /\
                     env_related (j' fm) e' e /\
                     tenv_related (j' fm) le' le /\
                     mem_related j bound (fl fm) (strip fm') m'.
Proof.
  Lemma function_entry2_fp_related:
    forall fm f vargs e fp (NOREP':norep (Mem.freelist fm))(NOOVERLAP': no_overlap (Mem.freelist fm) (fun b=>Plt b bound)),
      ClightLang.function_entry2_fp sge f vargs fm e fp->
      forall e' vargs' m,
        list_forall2 (val_related (j' fm)) vargs' vargs->
        mem_related j bound (fl fm) (strip fm) m ->
        exists fp', Clight_local.function_entry2_fp tge f vargs' m e' fp' /\
               FPlocalize (j' fm) fp fp'.
Proof.
End EXPR.

Inductive match_cont (j: Bset.inj):cont->cont->Prop:=
| match_stop: match_cont j Kstop Kstop
| match_seq:
    forall k1 k1' s,
      match_cont j k1 k1'->
      match_cont j (Kseq s k1)(Kseq s k1')
| match_loop1:
    forall k k' s1 s2,
      match_cont j k k'->
      match_cont j (Kloop1 s1 s2 k)(Kloop1 s1 s2 k')
| match_loop2:
    forall k k' s1 s2,
      match_cont j k k'->
      match_cont j (Kloop2 s1 s2 k)(Kloop2 s1 s2 k')
| match_switch:
    forall k k',
      match_cont j k k'->
      match_cont j (Kswitch k)(Kswitch k')
| match_call:
    forall id f v v' e e' k k',
      match_cont j k k'->
      env_related j v v'->
      tenv_related j e e'->
      match_cont j (Kcall id f v e k)(Kcall id f v' e' k').

Lemma find_label_match_cont_case1:
  forall j s t k k',
      match_cont j k k'->
      find_label s t k' = None ->
      find_label s t k= None
with find_label_ls_match_cont_case1:
       forall j s t k k',
         match_cont j k k'->
         find_label_ls s t k' = None ->
         find_label_ls s t k = None.
Proof.

Lemma find_label_match_cont_case2:
  forall t j s k k' ,
    match_cont j k k'->
    match find_label s t k with
    | None => find_label s t k' = None
    | Some (s2,k2) =>
      exists k3,
      find_label s t k' = Some (s2,k3) /\ match_cont j k2 k3
    end
      
with find_label_ls_match_cont_case2:
       forall t j s k k' ,
         match_cont j k k'->
         match find_label_ls s t k with
         | None => find_label_ls s t k' = None
         | Some (s2,k2) =>
           exists k3,
           find_label_ls s t k' = Some (s2,k3) /\ match_cont j k2 k3
         end.
Proof.
      
Lemma call_cont_match:
  forall k k' j,
    match_cont j k k'->
    match_cont j (call_cont k)(call_cont k').
Proof.
Inductive match_core (j: Bset.inj) : core -> core -> Prop :=
| match_state_intro:
    forall f s k1 k2 e1 e2 te1 te2,
      match_cont j k1 k2 ->
      env_related j e1 e2->
      tenv_related j te1 te2->
      match_core j (Core_State f s k1 e1 te1)
                 (Core_State f s k2 e2 te2)
| match_state_call:
    forall fd args1 args2 k1 k2,
      match_cont j k1 k2 ->
      list_forall2 (val_related j) args1 args2 ->
      match_core j (Core_Callstate fd args1 k1)
                 (Core_Callstate fd args2 k2)
| match_state_return:
    forall res1 res2 k1 k2,
      match_cont j k1 k2 ->
      val_related j res1 res2 ->
      match_core j (Core_Returnstate res1 k1)
                 (Core_Returnstate res2 k2).
Lemma freelist_fleq:
  forall l m m',
    Mem.free_list m l = Some m'->
    Mem.freelist m' = Mem.freelist m.
Proof.
Theorem clight_localize: LangLocalize clight_comp_unit wdcu Clight_IS_2 Clight_IS_2_local.
Proof.