Local Open Scope logic.
(* PROOF AUTOMATION FOR SEMAX *)
Hint Extern 3 (inlist _ _ = false) => (compute; reflexivity).
Ltac compute_neq := solve [let H := fresh in intro H; inversion H].
Hint Rewrite arguments_gss : args.
Hint Rewrite arguments_gso using compute_neq : args.
Ltac call_tac := unfold call; simpl; autorewrite with args; simpl.
Ltac funassert_tac :=
match goal with
| |-   ?A && ?B |-- _ =>
match A with context [funassert _] => apply andp_left1; funassert_tac  end ||
match B with context [funassert _] => apply andp_left2; funassert_tac  end
| |- funassert _ |-- _ => apply funassert_e; simpl; reflexivity
end.
Ltac func_tac :=
apply semax_func_cons;
[ compute; reflexivity | compute; reflexivity | compute; reflexivity
|  (*eapply semax_pre; [intro ; call_tac; apply derives_refl | ] *)
| ].
Ltac rewrite' H := eapply semax_pre; [ intro; rewrite H; apply derives_refl | ].
(* This tactic works but introduces magic wands, which is undesirable *)
Ltac forward_magic :=
match goal with |- semax _ ?G ?P (Assign (Mem ?e1) ?e2 ?c) =>
let v := fresh "v" in
(evar (v:adr);
apply semax_pre with (P' := fun s => mapsto (eval e1 s) v * (mapsto (eval e1 s) v -* P s));
[intro | apply semax_store; auto  ] );
unfold v; clear v
end.
Hint Resolve now_later sepcon_derives.
Definition semax_body (G: funspecs) (spec: funspec) (f: list var * control) :=
semax (fst f) G (fun s => call spec (map s (fst f))) (snd f).

Lemma semax_load_next: forall x y z c vars G P,
expcheck vars y = true ->
semax (vs_add x vars) G P c ->
semax vars G (fun s => (next (eval y s) z * TT) && |> subst x z P s)
(Do x := Mem y ; c).