Program Definition function_bounds := {|
used_callee_save := RegSet.elements record_regs_of_function;
bound_local := max_over_slots_of_funct local_slot;
bound_outgoing := Z.max (max_over_instrs outgoing_space) (max_over_slots_of_funct outgoing_slot);
bound_stack_data := Z.max f.(fn_stacksize) 0
|}.
Next Obligation.
apply max_over_slots_of_funct_pos.
Qed.
Next Obligation.
apply Z.le_ge. eapply Z.le_trans. 2: apply Z.le_max_r.
apply Z.ge_le. apply max_over_slots_of_funct_pos.
Qed.
Next Obligation.
apply Z.le_ge. apply Z.le_max_r.
Qed.
Next Obligation.
generalize (RegSet.elements_3w record_regs_of_function).
generalize (RegSet.elements record_regs_of_function).
induction 1. constructor. constructor; auto.
red; intros; elim H. apply InA_alt. exists x; auto.
Qed.
Next Obligation.
apply record_regs_of_function_only. apply RegSet.elements_2.
apply InA_alt. exists r; auto.
Qed.
(** We now show the correctness of the inferred bounds. *)

(* Specifications: *)
Lemma record_reg_incr: forall u r r', RegSet.In r' u -> RegSet.In r' (record_reg u r).
Lemma record_reg_ok: forall u r, is_callee_save r = true -> RegSet.In r (record_reg u r).
Lemma record_regs_incr: forall r' rl u, RegSet.In r' u -> RegSet.In r' (record_regs u rl).
Lemma record_regs_ok: forall r rl u, In r rl -> is_callee_save r = true -> RegSet.In r (record_regs u rl).
Lemma record_regs_of_instr_incr: forall r' u i, RegSet.In r' u -> RegSet.In r' (record_regs_of_instr u i).
Definition defined_by_instr (r': mreg) (i: instruction) :=
match i with
| Lgetstack sl ofs ty r => r' = r
| Lop op args res => r' = res
| Lload chunk addr args dst => r' = dst
| Lbuiltin ef args res => In r' (params_of_builtin_res res) \/ In r' (destroyed_by_builtin ef)
| _ => False
end.
Lemma record_regs_of_instr_ok: forall r' u i, defined_by_instr r' i -> is_callee_save r' = true -> RegSet.In r' (record_regs_of_instr u i).
Lemma record_regs_of_function_ok:
forall r i, In i f.(fn_code) -> defined_by_instr r i -> is_callee_save r = true -> RegSet.In r record_regs_of_function.
Lemma max_over_list_bound:
forall (A: Type) (valu: A -> Z) (l: list A) (x: A),
In x l -> valu x <= max_over_list valu l.
Lemma max_over_instrs_bound:
forall (valu: instruction -> Z) i,
In i f.(fn_code) -> valu i <= max_over_instrs valu.
Lemma max_over_slots_of_funct_bound:
forall (valu: slot * Z * typ -> Z) i s,
In i f.(fn_code) -> In s (slots_of_instr i) ->
valu s <= max_over_slots_of_funct valu.
Lemma local_slot_bound:
forall i ofs ty,
In i f.(fn_code) -> In (Local, ofs, ty) (slots_of_instr i) ->
ofs + typesize ty <= bound_local function_bounds.
Lemma outgoing_slot_bound:
forall i ofs ty,
In i f.(fn_code) -> In (Outgoing, ofs, ty) (slots_of_instr i) ->
ofs + typesize ty <= bound_outgoing function_bounds.
Lemma size_arguments_bound:
forall sig ros,
In (Lcall sig ros) f.(fn_code) ->
size_arguments sig <= bound_outgoing function_bounds.