(** ** Properties of destroyed registers. *)
Definition no_callee_saves (l: list mreg) : Prop :=
existsb is_callee_save l = false.
Remark destroyed_by_op_caller_save:
forall op, no_callee_saves (destroyed_by_op op).
Remark destroyed_by_load_caller_save:
forall chunk addr, no_callee_saves (destroyed_by_load chunk addr).
Remark destroyed_by_store_caller_save:
forall chunk addr, no_callee_saves (destroyed_by_store chunk addr).
Remark destroyed_by_cond_caller_save:
forall cond, no_callee_saves (destroyed_by_cond cond).
Remark destroyed_by_jumptable_caller_save:
no_callee_saves destroyed_by_jumptable.
Remark destroyed_by_setstack_caller_save:
forall ty, no_callee_saves (destroyed_by_setstack ty).
Remark destroyed_at_function_entry_caller_save:
no_callee_saves destroyed_at_function_entry.
Hint Resolve destroyed_by_op_caller_save destroyed_by_load_caller_save
destroyed_by_store_caller_save
destroyed_by_cond_caller_save destroyed_by_jumptable_caller_save
destroyed_at_function_entry_caller_save: stacking.
Remark destroyed_by_setstack_function_entry:
forall ty, incl (destroyed_by_setstack ty) destroyed_at_function_entry.
Remark transl_destroyed_by_op:
forall op e, destroyed_by_op (transl_op e op) = destroyed_by_op op.
Remark transl_destroyed_by_load:
forall chunk addr e, destroyed_by_load chunk (transl_addr e addr) = destroyed_by_load chunk addr.
Remark transl_destroyed_by_store:
forall chunk addr e, destroyed_by_store chunk (transl_addr e addr) = destroyed_by_store chunk addr.
(** * Correctness of saving and restoring of callee-save registers *)
(** The following lemmas show the correctness of the register saving code generated by [save_callee_save]: after this code has executed, the register save areas of the current frame do contain the values of the callee-save registers used by the function. *)
Section SAVE_CALLEE_SAVE.
Variable j: meminj.
Variable cs: list stackframe.
Variable fb: block.
Variable sp: block.
Variable ls: locset.
Hypothesis ls_temp_undef:
forall ty r, In r (destroyed_by_setstack ty) -> ls (R r) = Vundef.
Hypothesis wt_ls: forall r, Val.has_type (ls (R r)) (mreg_type r).

(* Specifications: *)
Lemma save_callee_save_rec_correct:
forall k l pos rs m P,
(forall r, In r l -> is_callee_save r = true) ->
m |= range sp pos (size_callee_save_area_rec l pos) ** P ->
agree_regs j ls rs ->
exists rs', exists m',
star step tge
(State cs fb (Vptr sp Ptrofs.zero) (save_callee_save_rec l pos k) rs m)
E0 (State cs fb (Vptr sp Ptrofs.zero) k rs' m')
/\ m' |= contains_callee_saves j sp pos l ls ** P
/\ (forall ofs k p, Mem.perm m sp ofs k p -> Mem.perm m' sp ofs k p)
/\ agree_regs j ls rs'.