(** ** Construction 1: allocating the stack frame at function entry *)

Ltac splitall := repeat (match goal with |- _ /\ _ => split end).

(* Specifications: *)
Theorem allocate_stack: forall m sz m' sp bc ge rm am, Mem.alloc m 0 sz = (m', sp) -> genv_match bc ge -> romatch bc m rm -> mmatch bc m am -> bc_nostack bc -> exists bc', bc_incr bc bc' /\ bc' sp = BCstack /\ genv_match bc' ge /\ romatch bc' m' rm /\ mmatch bc' m' mfunction_entry /\ (forall b, Plt b sp -> bc' b = bc b) /\ (forall v x, vmatch bc v x -> vmatch bc' v (Ifptr Nonstack)).
Theorem anonymize_stack: forall m sp bc ge rm am, genv_match bc ge -> romatch bc m rm -> mmatch bc m am -> bc sp = BCstack -> exists bc', bc_nostack bc' /\ bc' sp = BCother /\ (forall b, b <> sp -> bc' b = bc b) /\ (forall v x, vmatch bc v x -> vmatch bc' v Vtop) /\ genv_match bc' ge /\ romatch bc' m rm /\ mmatch bc' m mtop.
Theorem hide_stack: forall m sp bc ge rm am, genv_match bc ge -> romatch bc m rm -> mmatch bc m am -> bc sp = BCstack -> pge Nonstack am.(am_nonstack) -> exists bc', bc_nostack bc' /\ bc' sp = BCinvalid /\ (forall b, b <> sp -> bc' b = bc b) /\ (forall v x, vge (Ifptr Nonstack) x -> vmatch bc v x -> vmatch bc' v Vtop) /\ genv_match bc' ge /\ romatch bc' m rm /\ mmatch bc' m mtop.
Theorem return_from_public_call: forall (caller callee: block_classification) bound sp ge e ae v m rm, bc_below caller bound -> callee sp = BCother -> caller sp = BCstack -> (forall b, Plt b bound -> b <> sp -> caller b = callee b) -> genv_match caller ge -> ematch caller e ae -> Ple bound (Mem.nextblock m) -> vmatch callee v Vtop -> romatch callee m rm -> mmatch callee m mtop -> genv_match callee ge -> bc_nostack callee -> exists bc, vmatch bc v Vtop /\ ematch bc e ae /\ romatch bc m rm /\ mmatch bc m mafter_public_call /\ genv_match bc ge /\ bc sp = BCstack /\ (forall b, Plt b sp -> bc b = caller b).
Theorem return_from_private_call: forall (caller callee: block_classification) bound sp ge e ae v m rm am, bc_below caller bound -> callee sp = BCinvalid -> caller sp = BCstack -> (forall b, Plt b bound -> b <> sp -> caller b = callee b) -> genv_match caller ge -> ematch caller e ae -> bmatch caller m sp am.(am_stack) -> Ple bound (Mem.nextblock m) -> vmatch callee v Vtop -> romatch callee m rm -> mmatch callee m mtop -> genv_match callee ge -> bc_nostack callee -> exists bc, vmatch bc v (Ifptr Nonstack) /\ ematch bc e ae /\ romatch bc m rm /\ mmatch bc m (mafter_private_call am) /\ genv_match bc ge /\ bc sp = BCstack /\ (forall b, Plt b sp -> bc b = caller b).
Theorem external_call_match: forall ef (ge: genv) vargs m t vres m' bc rm am, external_call ef ge vargs m t vres m' -> genv_match bc ge -> (forall v, In v vargs -> vmatch bc v Vtop) -> romatch bc m rm -> mmatch bc m am -> bc_nostack bc -> exists bc', bc_incr bc bc' /\ (forall b, Plt b (Mem.nextblock m) -> bc' b = bc b) /\ vmatch bc' vres Vtop /\ genv_match bc' ge /\ romatch bc' m' rm /\ mmatch bc' m' mtop /\ bc_nostack bc' /\ (forall b ofs n, Mem.valid_block m b -> bc b = BCinvalid -> Mem.loadbytes m' b ofs n = Mem.loadbytes m b ofs n).
Lemma sound_stack_ext: forall m' bc stk m bound, sound_stack bc stk m bound -> (forall b ofs n bytes, Plt b bound -> bc b = BCinvalid -> n >= 0 -> Mem.loadbytes m' b ofs n = Some bytes -> Mem.loadbytes m b ofs n = Some bytes) -> sound_stack bc stk m' bound.
Lemma sound_stack_inv: forall m' bc stk m bound, sound_stack bc stk m bound -> (forall b ofs n, Plt b bound -> bc b = BCinvalid -> n >= 0 -> Mem.loadbytes m' b ofs n = Mem.loadbytes m b ofs n) -> sound_stack bc stk m' bound.
Lemma sound_stack_storev: forall chunk m addr v m' bc aaddr stk bound, Mem.storev chunk m addr v = Some m' -> vmatch bc addr aaddr -> sound_stack bc stk m bound -> sound_stack bc stk m' bound.
Lemma sound_stack_storebytes: forall m b ofs bytes m' bc aaddr stk bound, Mem.storebytes m b (Ptrofs.unsigned ofs) bytes = Some m' -> vmatch bc (Vptr b ofs) aaddr -> sound_stack bc stk m bound -> sound_stack bc stk m' bound.
Lemma sound_stack_free: forall m b lo hi m' bc stk bound, Mem.free m b lo hi = Some m' -> sound_stack bc stk m bound -> sound_stack bc stk m' bound.
Lemma sound_stack_new_bound: forall bc stk m bound bound', sound_stack bc stk m bound -> Ple bound bound' -> sound_stack bc stk m bound'.
Lemma sound_stack_exten: forall bc stk m bound (bc1: block_classification), sound_stack bc stk m bound -> (forall b, Plt b bound -> bc1 b = bc b) -> sound_stack bc1 stk m bound.
Theorem sound_step_base: forall st t st', RTL.step ge st t st' -> sound_state_base st -> sound_state_base st'.