(** * Agreement between location sets and Mach states *)

(** Agreement with Mach register states *)

Definition agree_regs (j: meminj) (ls: locset) (rs: regset) : Prop :=
  forall r, Val.inject j (ls (R r)) (rs r).(** Agreement over locations *)

Record agree_locs (ls ls0: locset) : Prop :=
  mk_agree_locs {

    (** Unused registers have the same value as in the caller *)
    agree_unused_reg:
       forall r, ~(mreg_within_bounds b r) -> ls (R r) = ls0 (R r);

    (** Incoming stack slots have the same value as the
        corresponding Outgoing stack slots in the caller *)
    agree_incoming:
       forall ofs ty,
       In (S Incoming ofs ty) (regs_of_rpairs (loc_parameters f.(Linear.fn_sig))) ->
       ls (S Incoming ofs ty) = ls0 (S Outgoing ofs ty)
}.(** Agreement over locations *)

Record agree_locs (ls ls0: locset) : Prop :=
  mk_agree_locs {

    (** Unused registers have the same value as in the caller *)
    agree_unused_reg:
       forall r, ~(mreg_within_bounds b r) -> ls (R r) = ls0 (R r);

    (** Incoming stack slots have the same value as the
        corresponding Outgoing stack slots in the caller *)
    agree_incoming:
       forall ofs ty,
       In (S Incoming ofs ty) (regs_of_rpairs (loc_parameters f.(Linear.fn_sig))) ->
       ls (S Incoming ofs ty) = ls0 (S Outgoing ofs ty)
}.(** Agreement over locations *)

Record agree_locs (ls ls0: locset) : Prop :=
  mk_agree_locs {

    (** Unused registers have the same value as in the caller *)
    agree_unused_reg:
       forall r, ~(mreg_within_bounds b r) -> ls (R r) = ls0 (R r);

    (** Incoming stack slots have the same value as the
        corresponding Outgoing stack slots in the caller *)
    agree_incoming:
       forall ofs ty,
       In (S Incoming ofs ty) (regs_of_rpairs (loc_parameters f.(Linear.fn_sig))) ->
       ls (S Incoming ofs ty) = ls0 (S Outgoing ofs ty)
}.(** Agreement over locations *)

Record agree_locs (ls ls0: locset) : Prop :=
  mk_agree_locs {

    (** Unused registers have the same value as in the caller *)
    agree_unused_reg:
       forall r, ~(mreg_within_bounds b r) -> ls (R r) = ls0 (R r);

    (** Incoming stack slots have the same value as the
        corresponding Outgoing stack slots in the caller *)
    agree_incoming:
       forall ofs ty,
       In (S Incoming ofs ty) (regs_of_rpairs (loc_parameters f.(Linear.fn_sig))) ->
       ls (S Incoming ofs ty) = ls0 (S Outgoing ofs ty)
}.

(* Specifications: *)
Lemma agree_reg: forall j ls rs r, agree_regs j ls rs -> Val.inject j (ls (R r)) (rs r).
Lemma agree_regs_set_reg: forall j ls rs r v v', agree_regs j ls rs -> Val.inject j v v' -> agree_regs j (Locmap.set (R r) v ls) (Regmap.set r v' rs).
Lemma agree_regs_set_pair: forall j p v v' ls rs, agree_regs j ls rs -> Val.inject j v v' -> agree_regs j (Locmap.setpair p v ls) (set_pair p v' rs).
Lemma agree_regs_set_res: forall j res v v' ls rs, agree_regs j ls rs -> Val.inject j v v' -> agree_regs j (Locmap.setres res v ls) (set_res res v' rs).
Lemma agree_regs_exten: forall j ls rs ls' rs', agree_regs j ls rs -> (forall r, ls' (R r) = Vundef \/ ls' (R r) = ls (R r) /\ rs' r = rs r) -> agree_regs j ls' rs'.
Lemma agree_regs_undef_regs: forall j rl ls rs, agree_regs j ls rs -> agree_regs j (LTL.undef_regs rl ls) (Mach.undef_regs rl rs).
Lemma agree_regs_undef_caller_save_regs: forall j ls rs, agree_regs j ls rs -> agree_regs j (LTL.undef_caller_save_regs ls) (Mach.undef_caller_save_regs rs).
Lemma agree_regs_set_slot: forall j ls rs sl ofs ty v, agree_regs j ls rs -> agree_regs j (Locmap.set (S sl ofs ty) v ls) rs.
Lemma agree_regs_inject_incr: forall j ls rs j', agree_regs j ls rs -> inject_incr j j' -> agree_regs j' ls rs.
Lemma agree_regs_call_regs: forall j ls rs, agree_regs j ls rs -> agree_regs j (call_regs ls) rs.
Lemma agree_locs_set_reg: forall ls ls0 r v, agree_locs ls ls0 -> mreg_within_bounds b r -> agree_locs (Locmap.set (R r) v ls) ls0.
Lemma caller_save_reg_within_bounds: forall r, is_callee_save r = false -> mreg_within_bounds b r.
Lemma agree_locs_set_pair: forall ls0 p v ls, agree_locs ls ls0 -> forall_rpair (fun r => is_callee_save r = false) p -> agree_locs (Locmap.setpair p v ls) ls0.
Lemma agree_locs_set_res: forall ls0 res v ls, agree_locs ls ls0 -> (forall r, In r (params_of_builtin_res res) -> mreg_within_bounds b r) -> agree_locs (Locmap.setres res v ls) ls0.
Lemma agree_locs_undef_regs: forall ls0 regs ls, agree_locs ls ls0 -> (forall r, In r regs -> mreg_within_bounds b r) -> agree_locs (LTL.undef_regs regs ls) ls0.
Lemma agree_locs_undef_locs_1: forall ls0 regs ls, agree_locs ls ls0 -> (forall r, In r regs -> is_callee_save r = false) -> agree_locs (LTL.undef_regs regs ls) ls0.
Lemma agree_locs_undef_locs: forall ls0 regs ls, agree_locs ls ls0 -> existsb is_callee_save regs = false -> agree_locs (LTL.undef_regs regs ls) ls0.
Lemma agree_locs_set_slot: forall ls ls0 sl ofs ty v, agree_locs ls ls0 -> slot_writable sl = true -> agree_locs (Locmap.set (S sl ofs ty) v ls) ls0.
Lemma agree_locs_return: forall ls ls0 ls', agree_locs ls ls0 -> agree_callee_save ls' ls -> agree_locs ls' ls0.