(** As a corollary of the previous lemmas, we obtain the following correctness theorem for the execution of a function prologue (allocation of the frame + saving of the link and return address + saving of the used callee-save registers). *)

Lemma function_prologue_correct:
forall j ls ls0 ls1 rs rs1 m1 m1' m2 sp parent ra cs fb k P,
agree_regs j ls rs ->
agree_callee_save ls ls0 ->
agree_outgoing_arguments (Linear.fn_sig f) ls ls0 ->
(forall r, Val.has_type (ls (R r)) (mreg_type r)) ->
ls1 = LTL.undef_regs destroyed_at_function_entry (LTL.call_regs ls) ->
rs1 = undef_regs destroyed_at_function_entry rs ->
Mem.alloc m1 0 f.(Linear.fn_stacksize) = (m2, sp) ->
Val.has_type parent Tptr -> Val.has_type ra Tptr ->
m1' |= minjection j m1 ** globalenv_inject ge j ** P ->
exists j', exists rs', exists m2', exists sp', exists m3', exists m4', exists m5',
Mem.alloc m1' 0 tf.(fn_stacksize) = (m2', sp')
/\ store_stack m2' (Vptr sp' Ptrofs.zero) Tptr tf.(fn_link_ofs) parent = Some m3'
/\ store_stack m3' (Vptr sp' Ptrofs.zero) Tptr tf.(fn_retaddr_ofs) ra = Some m4'
/\ star step tge
(State cs fb (Vptr sp' Ptrofs.zero) (save_callee_save fe k) rs1 m4')
E0 (State cs fb (Vptr sp' Ptrofs.zero) k rs' m5')
/\ agree_regs j' ls1 rs'
/\ agree_locs ls1 ls0
/\ m5' |= frame_contents j' sp' ls1 ls0 parent ra ** minjection j' m2 ** globalenv_inject ge j' ** P
/\ j' sp = Some(sp', fe.(fe_stack_data))
/\ inject_incr j j'.