Ltac simple_value v :=
match v with
| Vundef => idtac
| Vint _ => idtac
| Vlong _ => idtac
| Vfloat _ => idtac
| Vsingle _ => idtac
| Vptr _ _ => idtac
| list_repeat (Z.to_nat _) ?v' => simple_value v'
end.
Inductive undo_and_first__assert_PROP: Prop -> Prop := .
Ltac default_entailer_for_store_tac := try solve [entailer!].
Ltac entailer_for_store_tac := default_entailer_for_store_tac.
Ltac load_tac :=
ensure_normal_ret_assert;
hoist_later_in_pre;
first [sc_set_load_store.cast_load_tac | sc_set_load_store.load_tac].
Ltac simpl_proj_reptype :=
progress
match goal with |- context [@proj_reptype ?cs ?t ?gfs ?v] =>
let d := fresh "d" in let Hd := fresh "Hd" in
remember (@proj_reptype cs t gfs v) as d eqn:Hd;
unfold proj_reptype, proj_gfield_reptype, unfold_reptype,
nested_field_type, nested_field_rec in Hd;
rewrite ?eq_rect_r_eq, <- ?eq_rect_eq in Hd;
simpl proj_struct in Hd;
rewrite ?eq_rect_r_eq, <- ?eq_rect_eq in Hd;
subst d
end.
Ltac store_tac :=
ensure_open_normal_ret_assert;
hoist_later_in_pre;
sc_set_load_store.store_tac.
(* END new semax_load and semax_store tactics *************************)
Ltac forward0 :=  (* USE FOR DEBUGGING *)
match goal with
| |- @semax _ _ _ ?PQR (Ssequence ?c1 ?c2) ?PQR' =>
let Post := fresh "Post" in
evar (Post : environ->mpred);
apply semax_seq' with Post;
[
| unfold Post; clear Post ]
end.
(* Lemma normal_ret_assert_derives'': forall P Q R, P |-- R ->  normal_ret_assert (local Q && P) |-- normal_ret_assert R. *)
(* Lemma frame_ret_assert_derives P Q: P |-- Q -> frame_ret_assert P |-- frame_ret_assert Q.  (* Lemma function_body_ret_assert_derives t P Q: P |-- Q -> function_body_ret_assert t P |-- function_body_ret_assert t Q. *)
Ltac entailer_for_return := entailer.
Ltac solve_return_outer_gen := solve [repeat constructor].
Ltac solve_return_inner_gen :=
match goal with
| |- return_inner_gen _ ?v ?P _ =>
match P with
| exp _ =>
simple apply return_inner_gen_EX;
let a := fresh "a" in
intro a;
eexists;
split;
[ solve_return_inner_gen
| build_func_abs_right
]
| PROPx _ (LOCALx _ (SEPx _)) =>
match v with
| Some _ => first [ simple apply return_inner_gen_canon_Some;
unfold VST_floyd_app; reflexivity
| simple apply return_inner_gen_canon_nil;
unfold VST_floyd_app; reflexivity
| fail 1000 "the LOCAL clauses of this POSTCONDITION should only contain ret_temp. Other variables appears there now."]
| None   => first [ simple apply return_inner_gen_canon_nil;
unfold VST_floyd_app; reflexivity
| fail 1000 "the LOCAL clauses of this POSTCONDITION should not contain any variable."]
end
| _ => first [ simple apply return_inner_gen_main
| fail 1000 "the POSTCONDITION should be in an existential canonical form."
"One possible cause of this is some 'simpl in *' command which destroys the existential form in POSTCONDITION."]
end
end.
Inductive fn_data_at {cs: compspecs} (Delta: tycontext) (T2: PTree.t (type * val)): ident * type -> mpred -> Prop :=
| fn_data_at_intro: forall i t p,
(complete_legal_cosu_type t && (sizeof t <? Ptrofs.modulus) && is_aligned cenv_cs ha_env_cs la_env_cs t 0 = true)%bool ->
msubst_eval_lvar Delta T2 i t = Some p ->
fn_data_at Delta T2 (i, t) (data_at_ Tsh t p).

(* Specifications: *)
Lemma canonicalize_stackframe: forall {cs: compspecs} Delta P Q R T1 T2 GV fn,
local2ptree Q = (T1, T2, nil, GV) ->
Forall2 (fn_data_at Delta T2) fn R ->
local (tc_environ Delta) && PROPx P (LOCALx Q (SEPx R)) |-- fold_right sepcon emp (map (var_block Tsh) fn).
Lemma canonicalize_stackframe_emp: forall {cs: compspecs} Delta P Q,
local (tc_environ Delta) && PROPx P (LOCALx Q (SEPx nil)) |-- emp.