(*Require Import VST.floyd.unfold_data_at.*)
Local Open Scope logic.
Fixpoint fold_right_sepcon' (l: list(environ->mpred)) : environ -> mpred :=
match l with
| nil => emp
| b::nil => b
| b::r => b * fold_right_sepcon' r
end.
Definition zero_of_type (t: type) : val :=
match t with
| Tfloat _ _ => Vfloat Float.zero
| _ => Vint Int.zero
end.
Definition eval_sgvar (id: ident) (ty: type) (rho: environ) :=
match Map.get (ge_of rho) id with
| Some b => Vptr b Ptrofs.zero
| None => Vundef
end.
(* Lemma eval_sgvar_lemma1: forall (F: val -> mpred) ofs id t, F Vundef |-- FF -> `F (`(offset_val ofs) (eval_sgvar id t)) = (EX v:val, local (locald_denote (sgvar id v)) && `(F (offset_val ofs v))). *)
Definition init_data2pred' {cs: compspecs}
(Delta: tycontext) (gv: globals) (d: init_data)  (sh: share) (v: val) : mpred :=
match d with
| Init_int8 i => mapsto sh tuchar v (Vint (Int.zero_ext 8 i))
| Init_int16 i => mapsto sh tushort v (Vint (Int.zero_ext 16 i))
| Init_int32 i => mapsto sh tuint v (Vint i)
| Init_int64 i => mapsto sh tulong v (Vlong i)
| Init_float32 r =>  mapsto sh tfloat v (Vsingle r)
| Init_float64 r =>  mapsto sh tdouble v (Vfloat r)
| Init_space n =>  memory_block sh n v
| Init_addrof symb ofs =>
match (var_types Delta) ! symb, (glob_types Delta) ! symb with
| None, Some (Tarray t n' att) =>
mapsto sh (Tpointer t noattr) v (offset_val (Ptrofs.unsigned ofs) (gv symb))
| None, Some t => mapsto sh (Tpointer t noattr) v (offset_val (Ptrofs.unsigned ofs) (gv symb))
| Some _, Some _ => mapsto_ sh (Tpointer Tvoid noattr) v
| _, _ => TT
end
end.
Fixpoint id2pred_star   {cs: compspecs}
(Delta: tycontext) (gz: globals) (sh: share) (v: val) (dl: list init_data) : environ->mpred :=
match dl with
| d::dl' => `(init_data2pred' Delta gz d sh v)
* id2pred_star Delta gz sh (offset_val (init_data_size d) v) dl'
| nil => emp
end.
Arguments id2pred_star cs Delta gz sh v dl rho  / .
(* (complete_legal_cosu_type (gvar_info gv) && is_aligned cenv_cs ha_env_cs la_env_cs (gvar_info gv) 0)% bool = true -> *)
(*  (globvar_all_aligned gv = true) -> *)
(*   init_data_list_size (gvar_init gv) <= sizeof (gvar_info gv) <= Ptrofs.max_unsigned -> *)
Definition inttype2init_data (sz: intsize) : (int -> init_data) :=
match sz with
| IBool  =>  Init_int8
| I8  =>  Init_int8
| I16 =>  Init_int16
| I32 =>  Init_int32
end.
Definition notboolsize (sz: intsize) : Prop :=
match sz with IBool => False | _ => True end.
(*   globvar_all_aligned gv = true -> *)
(*       globvar_all_aligned gv = true -> *)
(*       globvar_all_aligned gv = true ->*)
Fixpoint init_datalist2pred' {cs: compspecs}
(Delta: tycontext) (gv: globals) (dl: list init_data)  (sh: share) (ofs: Z) (v: val) : mpred :=
match dl with
| d::dl' => init_data2pred' Delta gv d sh (offset_val ofs v)
* init_datalist2pred' Delta gv dl' sh (ofs + init_data_size d) v
| nil => emp
end.
Ltac process_one_globvar :=
first
[ simple eapply process_globvar_extern; [reflexivity | reflexivity | ]
| simple eapply process_globvar_space;
[simpl; reflexivity | reflexivity | reflexivity | reflexivity | reflexivity | reflexivity | simpl; computable | ]
| simple eapply process_globvar';
[reflexivity | reflexivity | reflexivity | reflexivity | reflexivity | reflexivity
| reflexivity | compute; congruence | ]
| simple eapply process_globvar_array;
[reflexivity | reflexivity | reflexivity | reflexivity | reflexivity | apply Coq.Init.Logic.I
| compute; clear; congruence
| repeat eapply map_instantiate; symmetry; apply map_nil
| compute; split; clear; congruence |  ]
| simple eapply process_globvar_star';
[reflexivity | reflexivity | reflexivity | reflexivity
| compute; split; clear; congruence
| simpl gvar_info; simpl gvar_readonly; simpl readonly2share;
change (Share.lub extern_retainer Tsh) with Ews
]
| simple eapply halfprocess_globvar_star;
[reflexivity | reflexivity | reflexivity | reflexivity|
simpl; compute; split; clear; congruence | ]
];
change (Share.lub extern_retainer _) with Ews;
change (Share.lub extern_retainer _) with Ers;
try change (Vint oo _) with (Vint oo id);
fold_types;
rewrite ?Combinators.compose_id_right.

Lemma move_globfield_into_SEP':
forall {cs: compspecs}{Espec: OracleKind} Delta P Q R
(f: val -> localdef)
(g: val -> mpred)
(h: val -> val) (S2 S3 S4: environ -> mpred) c Post,
(forall x: val,
semax Delta (PROPx P (LOCALx (f x :: Q) (SEPx ((g (h x))::R))) * S2 * S3 * S4) c Post) ->
semax Delta (PROPx P (LOCALx Q (SEPx R)) * ((EX x:val, local (locald_denote (f x)) && `(g (h x))) * S2) * S3 * S4) c Post.