Machine- and ABI-dependent layout information for activation records.
Require Import Coqlib.
Require Import AST Memory Separation.
Require Import Bounds.
Local Open Scope sep_scope.
The general shape of activation records is as follows,
from bottom (lowest offsets) to top:
-
Space for outgoing arguments to function calls.
-
Back link to parent frame
-
Saved values of integer callee-save registers used by the function.
-
Saved values of float callee-save registers used by the function.
-
Local stack slots.
-
Space for the stack-allocated data declared in Cminor
-
Return address.
Definition fe_ofs_arg := 0.
Definition make_env (
b:
bounds) :
frame_env :=
let w :=
if Archi.ptr64 then 8
else 4
in
let ocs :=
align (4 *
b.(
bound_outgoing))
w in
let ol :=
align (
size_callee_save_area b ocs) 8
in
let ostkdata :=
align (
ol + 4 *
b.(
bound_local)) 8
in
let preretaddr :=
align (
ostkdata +
b.(
bound_stack_data))
w in
let sz :=
align (
preretaddr +
w) 8
in
let oretaddr :=
sz -
w in
{|
fe_size :=
sz;
fe_ofs_retaddr :=
oretaddr;
fe_ofs_local :=
ol;
fe_ofs_callee_save :=
ocs;
fe_stack_data :=
ostkdata;
fe_used_callee_save :=
b.(
used_callee_save) |}.
Lemma retaddr_le:
forall preretaddr w,
preretaddr <= (
align (
preretaddr +
w) 8) -
w.
Proof.
intros.
assert (
preretaddr +
w <= (
align (
preretaddr +
w) 8)).
apply align_le;
omega.
omega.
Qed.
Section WITHMEM.
Context `{
memory_model_prf:
Mem.MemoryModel}.
Lemma frame_env_separated:
forall b sp (
m:
mem)
P,
let fe :=
make_env b in
m |=
range sp 0 (
fe_stack_data fe) **
range sp (
fe_stack_data fe +
bound_stack_data b) (
fe_size fe) **
P ->
m |=
range sp (
fe_ofs_local fe) (
fe_ofs_local fe + 4 *
bound_local b)
**
range sp fe_ofs_arg (
fe_ofs_arg + 4 *
bound_outgoing b)
**
range sp (
fe_ofs_retaddr fe) (
fe_ofs_retaddr fe +
size_chunk Mptr)
**
range sp (
fe_ofs_callee_save fe) (
size_callee_save_area b (
fe_ofs_callee_save fe))
**
P.
Proof.
Lemma frame_env_separated':
forall b ,
let w :=
if Archi.ptr64 then 8
else 4
in
let fe :=
make_env b in
let ocs :=
align (4 *
bound_outgoing b)
w in
let ol :=
align (
size_callee_save_area b ocs) 8
in
let ostkdata :=
align (
ol + 4 *
bound_local b) 8
in
let oretaddr :=
align (
ostkdata +
bound_stack_data b)
w in
0 <=
ocs
/\
ocs <=
size_callee_save_area b ocs
/\
size_callee_save_area b ocs <=
ol
/\
ol + 4 *
bound_local b <=
ostkdata
/\
ostkdata +
bound_stack_data b <=
oretaddr
/\
ocs <=
fe_stack_data fe.
Proof.
Lemma frame_env_range:
forall b,
let fe :=
make_env b in
0 <=
fe_stack_data fe /\
fe_stack_data fe +
bound_stack_data b <=
fe_size fe.
Proof.
Lemma w_divides8 :
let w :=
if Archi.ptr64 then 8
else 4
in
(
w | 8).
Proof.
Lemma frame_env_aligned:
forall b,
let fe :=
make_env b in
(8 |
fe_ofs_arg)
/\ (8 |
fe_ofs_local fe)
/\ (8 |
fe_stack_data fe)
/\ (
align_chunk Mptr |
fe_ofs_retaddr fe).
Proof.
Lemma le_add_pos:
forall a b,
0 <=
b ->
a <=
a +
b.
Proof.
intros; omega.
Qed.
Lemma lt_add_pos:
forall a b,
0 <
b ->
a <
a +
b.
Proof.
intros; omega.
Qed.
Opaque bound_local bound_outgoing size_callee_save_area bound_stack_data.
Lemma zero_lt_align8 :
forall x,
0 <
x -> 0 <
align x 8.
Proof.
Lemma fe_size_pos (
b:
bounds) :
let fe :=
make_env b in
0 <
fe_size fe.
Proof.
Lemma zero_le_align8 :
forall x,
0 <=
x -> 0 <=
align x 8.
Proof.
Program Definition frame_of_frame_env (
b:
bounds) :
frame_info :=
let fe :=
make_env b in
{|
frame_size :=
fe_size fe;
frame_perm :=
fun o =>
if zle (
fe_stack_data fe)
o &&
zlt o (
fe_stack_data fe +
bound_stack_data b)
then Public
else Private
|}.
Next Obligation.
Lemma stkdata_retaddr_sep:
forall b,
let fe :=
make_env b in
forall o,
fe_stack_data fe <=
o <
fe_stack_data fe +
bound_stack_data b ->
fe_ofs_retaddr fe <=
o <
fe_ofs_retaddr fe +
size_chunk Mptr ->
False.
Proof.
clear.
intros b fe.
generalize (
frame_env_separated'
b).
intros.
destruct H.
destruct H2.
destruct H3.
destruct H4.
destruct H5.
set (
w :=
if Archi.ptr64 then 8
else 4)
in *.
set (
ocs :=
align (4 *
b.(
bound_outgoing))
w)
in *.
set (
ol :=
align (
size_callee_save_area b ocs) 8)
in *.
set (
ostkdata :=
align (
ol + 4 *
b.(
bound_local)) 8)
in *.
set (
preretaddr :=
align (
ostkdata +
b.(
bound_stack_data))
w)
in *.
set (
sz :=
align (
preretaddr +
w) 8)
in *.
set (
oretaddr :=
sz -
w)
in *.
assert (
preretaddr <=
oretaddr)
as RET by apply retaddr_le.
subst w ocs ol ostkdata preretaddr sz oretaddr.
simpl in *.
omega.
Qed.
Lemma arg_retaddr_sep:
forall b,
let fe :=
make_env b in
forall o,
fe_ofs_arg <=
o <
fe_ofs_arg + 4 *
bound_outgoing b ->
fe_ofs_retaddr fe <=
o <
fe_ofs_retaddr fe +
size_chunk Mptr ->
False.
Proof.
Lemma arg_local_sep:
forall b,
let fe :=
make_env b in
forall o,
fe_ofs_arg <=
o <
fe_ofs_arg + 4 *
bound_outgoing b ->
fe_ofs_local fe <=
o <
fe_ofs_local fe + 4 *
bound_local b ->
False.
Proof.
Lemma arg_callee_save_sep:
forall b,
let fe :=
make_env b in
forall o,
fe_ofs_arg <=
o <
fe_ofs_arg + 4 *
bound_outgoing b ->
fe_ofs_callee_save fe <=
o <
size_callee_save_area b (
fe_ofs_callee_save fe) ->
False.
Proof.
clear.
intros b fe.
generalize (
frame_env_separated'
b).
simpl.
intuition.
cut (
o<
o).
omega.
eapply Z.lt_le_trans.
apply H8.
etransitivity. 2:
apply H4.
change fe_ofs_arg with 0.
rewrite Z.add_0_l.
apply align_le.
destr;
omega.
Qed.
Lemma local_retaddr_sep:
forall b,
let fe :=
make_env b in
forall o,
fe_ofs_local fe <=
o <
fe_ofs_local fe + 4 *
bound_local b ->
fe_ofs_retaddr fe <=
o <
fe_ofs_retaddr fe +
size_chunk Mptr ->
False.
Proof.
Lemma local_callee_save_sep:
forall b,
let fe :=
make_env b in
forall o,
fe_ofs_local fe <=
o <
fe_ofs_local fe + 4 *
bound_local b ->
fe_ofs_callee_save fe <=
o <
size_callee_save_area b (
fe_ofs_callee_save fe) ->
False.
Proof.
clear. intros b fe.
generalize (frame_env_separated' b).
simpl. intuition.
Qed.
Lemma stkdata_callee_save_sep:
forall b,
let fe :=
make_env b in
forall o,
fe_stack_data fe <=
o <
fe_stack_data fe +
bound_stack_data b ->
fe_ofs_callee_save fe <=
o <
size_callee_save_area b (
fe_ofs_callee_save fe) ->
False.
Proof.
clear.
intros b fe.
generalize (
frame_env_separated'
b).
simpl.
intuition.
cut (
o <
o).
omega.
eapply Z.lt_le_trans.
apply H9.
etransitivity.
2:
apply H7.
etransitivity. 2:
apply align_le ;
try omega.
etransitivity. 2:
apply le_add_pos; [
generalize (
bound_local_pos b);
omega].
apply align_le.
omega.
Qed.
Lemma local_arg_sep:
forall b,
let fe :=
make_env b in
forall o,
fe_ofs_local fe <=
o <
fe_ofs_local fe + 4 *
bound_local b ->
fe_ofs_arg <=
o <
fe_ofs_arg + 4 *
bound_outgoing b ->
False.
Proof.
Lemma stkdata_arg_sep:
forall b,
let fe :=
make_env b in
forall o,
fe_stack_data fe <=
o <
fe_stack_data fe +
bound_stack_data b ->
fe_ofs_arg <=
o <
fe_ofs_arg + 4 *
bound_outgoing b ->
False.
Proof.
Lemma stkdata_local_sep:
forall b,
let fe :=
make_env b in
forall o,
fe_stack_data fe <=
o <
fe_stack_data fe +
bound_stack_data b ->
fe_ofs_local fe <=
o <
fe_ofs_local fe + 4 *
bound_local b ->
False.
Proof.
clear. intros b fe.
generalize (frame_env_separated' b).
simpl. intuition.
Qed.
End WITHMEM.