aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Monniaux <david.monniaux@univ-grenoble-alpes.fr>2019-05-21 15:10:06 +0200
committerDavid Monniaux <david.monniaux@univ-grenoble-alpes.fr>2019-05-21 15:10:06 +0200
commit6e331ae1185694e1ca542db00445968c107c26b9 (patch)
tree434656b1dc22c795a809ced7199cb0a46f91f85d
parentad6ff26beeb42b0e34a95939baa6d41b369e5d56 (diff)
parent04dabc46a0c8dd795e5d4090134d5e0f52847f9f (diff)
downloadcompcert-kvx-6e331ae1185694e1ca542db00445968c107c26b9.tar.gz
compcert-kvx-6e331ae1185694e1ca542db00445968c107c26b9.zip
Merge remote-tracking branch 'origin/mppa-work' into mppa-fast-div
-rw-r--r--mppa_k1c/Asmgenproof.v90
-rw-r--r--mppa_k1c/Machblockgen.v693
-rw-r--r--mppa_k1c/Machblockgenproof.v779
-rw-r--r--mppa_k1c/lib/Asmblockgenproof0.v16
-rw-r--r--mppa_k1c/lib/ForwardSimulationBlock.v51
-rwxr-xr-xtest/monniaux/gengraphs.py15
-rwxr-xr-xtest/monniaux/genmake.py17
7 files changed, 712 insertions, 949 deletions
diff --git a/mppa_k1c/Asmgenproof.v b/mppa_k1c/Asmgenproof.v
index 588019a2..e7e21a18 100644
--- a/mppa_k1c/Asmgenproof.v
+++ b/mppa_k1c/Asmgenproof.v
@@ -45,96 +45,15 @@ Qed.
(** Return Address Offset *)
-Definition return_address_offset (f: Mach.function) (c: Mach.code) (ofs: ptrofs) : Prop :=
- Asmblockgenproof.return_address_offset (Machblockgen.transf_function f) (Machblockgen.trans_code c) ofs.
-
-
-(* TODO: put this proof in Machblocgen ? (it is specific to Machblocgen) *)
-Lemma trans_code_monotonic c i b l:
- trans_code c = b::l ->
- exists l', exists b', trans_code (i::c) = l' ++ (b'::l).
-Proof.
- destruct c as [|i' c]. { rewrite trans_code_equation; intros; congruence. }
- destruct (get_code_nature (i :: i':: c)) eqn:GCNIC.
- - apply get_code_nature_empty in GCNIC. discriminate.
- - (* i=label *)
- destruct i; try discriminate.
- rewrite! trans_code_equation;
- remember (to_bblock (Mlabel l0 :: i' :: c)) as b0.
- destruct b0 as [b0 c0].
- exploit to_bblock_label; eauto.
- intros (H1 & H2). rewrite H2; simpl; clear H2.
- intros H2; inversion H2; subst.
- exists nil; simpl; eauto.
- - (*i=basic *)
- rewrite! trans_code_equation; destruct (to_basic_inst i) eqn:TBI; [| destruct i; discriminate].
- destruct (cn_eqdec (get_code_nature (i':: c)) IsLabel).
- + (* i'=label *) remember (to_bblock (i :: i' :: c)) as b1.
- destruct b1 as [b1 c1].
- assert (X: c1 = i'::c).
- { generalize Heqb1; clear Heqb1.
- unfold to_bblock.
- erewrite to_bblock_header_noLabel; try congruence.
- destruct i'; try discriminate.
- destruct i; try discriminate; simpl;
- intro X; inversion X; auto.
- }
- subst c1.
- rewrite !trans_code_equation. intro H1; rewrite H1.
- exists (b1 :: nil). simpl; eauto.
- + (* i'<>label *) remember (to_bblock (i :: i' :: c)) as b1.
- destruct b1 as [b1 c1].
- remember (to_bblock (i' :: c)) as b2.
- destruct b2 as [b2 c2].
- intro H1; assert (X: c1=c2).
- { generalize Heqb1, Heqb2; clear Heqb1 Heqb2.
- unfold to_bblock.
- erewrite to_bblock_header_noLabel; try congruence.
- destruct i'; simpl in * |- ; try congruence;
- destruct i; try discriminate; simpl;
- try (destruct (to_bblock_body c) as [xx yy], (to_bblock_exit yy);
- intros X1 X2; inversion X1; inversion X2; auto).
- }
- subst; inversion H1.
- exists nil; simpl; eauto.
- - (* i=cfi *)
- remember (to_cfi i) as cfi.
- intros H. destruct cfi.
- + erewrite trans_code_cfi; eauto.
- rewrite H.
- refine (ex_intro _ (_::nil) _). simpl; eauto.
- + destruct i; simpl in * |-; try congruence.
-Qed.
-
-Lemma Mach_Machblock_tail sg ros c c1 c2: c1=(Mcall sg ros :: c) -> is_tail c1 c2 ->
- exists b, (* Machblock.exit b = Some (Machblock.MBcall sg ros) /\ *)
- is_tail (b :: trans_code c) (trans_code c2).
-Proof.
- intro H; induction 1.
- - intros; subst.
- rewrite (trans_code_equation (Mcall sg ros :: c)).
- simpl.
- eapply ex_intro; eauto with coqlib.
- - intros; exploit IHis_tail; eauto. clear IHis_tail.
- intros (b & Hb).
- + inversion Hb; clear Hb.
- * exploit (trans_code_monotonic c2 i); eauto.
- intros (l' & b' & Hl'); rewrite Hl'.
- simpl; eauto with coqlib.
- * exploit (trans_code_monotonic c2 i); eauto.
- intros (l' & b' & Hl'); rewrite Hl'.
- simpl; eapply ex_intro.
- eapply is_tail_trans; eauto with coqlib.
-Qed.
+Definition return_address_offset: Mach.function -> Mach.code -> ptrofs -> Prop :=
+ Mach_return_address_offset Asmblockgenproof.return_address_offset.
Lemma return_address_exists:
forall f sg ros c, is_tail (Mcall sg ros :: c) f.(Mach.fn_code) ->
exists ra, return_address_offset f c ra.
Proof.
- intros.
- exploit Mach_Machblock_tail; eauto.
- destruct 1.
- eapply Asmblockgenproof.return_address_exists; eauto.
+ intros; unfold return_address_offset; eapply Mach_return_address_exists; eauto.
+ intros; eapply Asmblockgenproof.return_address_exists; eauto.
Qed.
@@ -154,7 +73,6 @@ Proof.
eapply compose_forward_simulations.
exploit Machblockgenproof.transf_program_correct; eauto.
unfold Machblockgenproof.inv_trans_rao.
- intros X; apply X.
eapply compose_forward_simulations. apply Asmblockgenproof.transf_program_correct; eauto.
eapply compose_forward_simulations. apply PostpassSchedulingproof.transf_program_correct; eauto.
apply Asm.transf_program_correct. eauto.
diff --git a/mppa_k1c/Machblockgen.v b/mppa_k1c/Machblockgen.v
index 1d5555df..4dfc309e 100644
--- a/mppa_k1c/Machblockgen.v
+++ b/mppa_k1c/Machblockgen.v
@@ -15,552 +15,77 @@ Require Import Mach.
Require Import Linking.
Require Import Machblock.
+Inductive Machblock_inst: Type :=
+| MB_label (lbl: label)
+| MB_basic (bi: basic_inst)
+| MB_cfi (cfi: control_flow_inst).
-Fixpoint to_bblock_header (c: Mach.code): list label * Mach.code :=
- match c with
- | (Mlabel l)::c' =>
- let (h, c'') := to_bblock_header c' in
- (l::h, c'')
- | _ => (nil, c)
- end.
-
-Definition to_basic_inst(i: Mach.instruction): option basic_inst :=
+Definition trans_inst (i:Mach.instruction) : Machblock_inst :=
match i with
- | Mgetstack ofs ty dst => Some (MBgetstack ofs ty dst)
- | Msetstack src ofs ty => Some (MBsetstack src ofs ty)
- | Mgetparam ofs ty dst => Some (MBgetparam ofs ty dst)
- | Mop op args res => Some (MBop op args res)
- | Mload chunk addr args dst => Some (MBload chunk addr args dst)
- | Mstore chunk addr args src => Some (MBstore chunk addr args src)
- | _ => None
+ | Mcall sig ros => MB_cfi (MBcall sig ros)
+ | Mtailcall sig ros => MB_cfi (MBtailcall sig ros)
+ | Mbuiltin ef args res => MB_cfi (MBbuiltin ef args res)
+ | Mgoto lbl => MB_cfi (MBgoto lbl)
+ | Mcond cond args lbl => MB_cfi (MBcond cond args lbl)
+ | Mjumptable arg tbl => MB_cfi (MBjumptable arg tbl)
+ | Mreturn => MB_cfi (MBreturn)
+ | Mgetstack ofs ty dst => MB_basic (MBgetstack ofs ty dst)
+ | Msetstack src ofs ty => MB_basic (MBsetstack src ofs ty)
+ | Mgetparam ofs ty dst => MB_basic (MBgetparam ofs ty dst)
+ | Mop op args res => MB_basic (MBop op args res)
+ | Mload chunk addr args dst => MB_basic (MBload chunk addr args dst)
+ | Mstore chunk addr args src => MB_basic (MBstore chunk addr args src)
+ | Mlabel l => MB_label l
end.
-Fixpoint to_bblock_body(c: Mach.code): bblock_body * Mach.code :=
- match c with
- | nil => (nil,nil)
- | i::c' =>
- match to_basic_inst i with
- | Some bi =>
- let (p,c'') := to_bblock_body c' in
- (bi::p, c'')
- | None => (nil, c)
- end
- end.
+Definition empty_bblock:={| header := nil; body := nil; exit := None |}.
+Extraction Inline empty_bblock.
+Definition add_label l bb:={| header := l::(header bb); body := (body bb); exit := (exit bb) |}.
+Extraction Inline add_label.
-Definition to_cfi (i: Mach.instruction): option control_flow_inst :=
- match i with
- | Mcall sig ros => Some (MBcall sig ros)
- | Mtailcall sig ros => Some (MBtailcall sig ros)
- | Mbuiltin ef args res => Some (MBbuiltin ef args res)
- | Mgoto lbl => Some (MBgoto lbl)
- | Mcond cond args lbl => Some (MBcond cond args lbl)
- | Mjumptable arg tbl => Some (MBjumptable arg tbl)
- | Mreturn => Some (MBreturn)
- | _ => None
- end.
+Definition add_basic bi bb :={| header := nil; body := bi::(body bb); exit := (exit bb) |}.
+Extraction Inline add_basic.
-Definition to_bblock_exit (c: Mach.code): option control_flow_inst * Mach.code :=
- match c with
- | nil => (None,nil)
- | i::c' =>
- match to_cfi i with
- | Some bi as o => (o, c')
- | None => (None, c)
- end
- end.
-
-Inductive code_nature: Set := IsEmpty | IsLabel | IsBasicInst | IsCFI.
+Definition cfi_bblock cfi:={| header := nil; body := nil; exit := Some cfi |}.
+Extraction Inline cfi_bblock.
-Definition get_code_nature (c: Mach.code): code_nature :=
- match c with
- | nil => IsEmpty
- | (Mlabel _)::_ => IsLabel
- | i::_ => match to_basic_inst i with
- | Some _ => IsBasicInst
- | None => IsCFI
- end
+Definition add_to_new_bblock (i:Machblock_inst) : bblock :=
+ match i with
+ | MB_label l => add_label l empty_bblock
+ | MB_basic i => add_basic i empty_bblock
+ | MB_cfi i => cfi_bblock i
end.
-Lemma cn_eqdec (cn1 cn2: code_nature): { cn1=cn2 } + {cn1 <> cn2}.
-Proof.
- decide equality.
-Qed.
-
-Lemma get_code_nature_nil c: c<>nil -> get_code_nature c <> IsEmpty.
-Proof.
- intros H. unfold get_code_nature.
- destruct c; try (contradict H; auto; fail).
- destruct i; discriminate.
-Qed.
-
-Lemma get_code_nature_empty c: get_code_nature c = IsEmpty -> c = nil.
-Proof.
- intros H. destruct c; auto. exploit (get_code_nature_nil (i::c)); discriminate || auto.
- intro F. contradict F.
-Qed.
-
-Lemma to_bblock_header_noLabel c:
- get_code_nature c <> IsLabel ->
- to_bblock_header c = (nil, c).
-Proof.
- intros H. destruct c as [|i c]; auto.
- destruct i; simpl; auto.
- contradict H; simpl; auto.
-Qed.
-
-Lemma to_bblock_header_wfe c:
- forall h c0,
- to_bblock_header c = (h, c0) ->
- (length c >= length c0)%nat.
-Proof.
- induction c as [ |i c]; simpl; intros h c' H.
- - inversion H; subst; clear H; simpl; auto.
- - destruct i; try (inversion H; subst; simpl; auto; fail).
- remember (to_bblock_header c) as bhc; destruct bhc as [h0 c0].
- inversion H; subst.
- lapply (IHc h0 c'); auto.
-Qed.
-
-Lemma to_bblock_header_wf c b c0:
- get_code_nature c = IsLabel ->
- to_bblock_header c = (b, c0) ->
- (length c > length c0)%nat.
-Proof.
- intros H1 H2; destruct c; [ contradict H1; simpl; discriminate | ].
- destruct i; try discriminate.
- simpl in H2.
- remember (to_bblock_header c) as bh; destruct bh as [h c''].
- inversion H2; subst.
- exploit to_bblock_header_wfe; eauto.
- simpl; omega.
-Qed.
-
-Lemma to_bblock_body_noBasic c:
- get_code_nature c <> IsBasicInst ->
- to_bblock_body c = (nil, c).
-Proof.
- intros H. destruct c as [|i c]; simpl; auto.
- destruct i; simpl; auto.
- all: contradict H; simpl; auto.
-Qed.
-
-Lemma to_bblock_body_wfe c b c0:
- to_bblock_body c = (b, c0) ->
- (length c >= length c0)%nat.
-Proof.
- generalize b c0; clear b c0.
- induction c as [|i c].
- - intros b c0 H. simpl in H. inversion H; subst; auto.
- - intros b c0 H. simpl in H. destruct (to_basic_inst i).
- + remember (to_bblock_body c) as tbbc; destruct tbbc as [p c''].
- exploit (IHc p c''); auto. inversion H; subst; simpl; omega.
- + inversion H; subst; auto.
-Qed.
-
-(** Attempt to eliminate cons_to_bblock_body *)
-(*
-Lemma to_bblock_body_basic c:
- get_code_nature c = IsBasicInst ->
- exists i bi b c',
- to_basic_inst i = Some bi
- /\ c = i :: c'
- /\ to_bblock_body c = (bi::b, snd (to_bblock_body c')).
-Proof.
- intros H.
- destruct c as [|i c]; try (contradict H; simpl; discriminate).
- destruct i eqn:I; try (contradict H; simpl; discriminate).
- all: simpl; destruct (to_bblock_body c) as [p c''] eqn:TBBC; repeat (eapply ex_intro); (repeat split);
- simpl; eauto; rewrite TBBC; simpl; eauto.
-Qed.
-
-Lemma to_bblock_body_wf c b c0:
- get_code_nature c = IsBasicInst ->
- to_bblock_body c = (b, c0) ->
- (length c > length c0)%nat.
-Proof.
- intros H1 H2; exploit to_bblock_body_basic; eauto.
- intros X. destruct X as (i & bi & b' & c' & X1 & X2 & X3).
- exploit to_bblock_body_wfe. eauto. subst. simpl.
- rewrite X3 in H2. inversion H2; clear H2; subst.
- simpl; omega.
-Qed.
-*)
-
-Inductive cons_to_bblock_body c0: Mach.code -> bblock_body -> Prop :=
- Cons_to_bbloc_body i bi c' b':
- to_basic_inst i = Some bi
- -> to_bblock_body c' = (b', c0)
- -> cons_to_bblock_body c0 (i::c') (bi::b').
-
-Lemma to_bblock_body_IsBasicInst c b c0:
- get_code_nature c = IsBasicInst ->
- to_bblock_body c = (b, c0) ->
- cons_to_bblock_body c0 c b.
-Proof.
- intros H1 H2. destruct c; [ contradict H1; simpl; discriminate | ].
- remember (to_basic_inst i) as tbii. destruct tbii.
- - simpl in H2. rewrite <- Heqtbii in H2.
- remember (to_bblock_body c) as tbbc. destruct tbbc as [p1 c1].
- inversion H2. subst. eapply Cons_to_bbloc_body; eauto.
- - destruct i; try discriminate.
-Qed.
-
-Lemma to_bblock_body_wf c b c0:
- get_code_nature c = IsBasicInst ->
- to_bblock_body c = (b, c0) ->
- (length c > length c0)%nat.
-Proof.
- intros H1 H2; exploit to_bblock_body_IsBasicInst; eauto.
- intros X. destruct X.
- exploit to_bblock_body_wfe; eauto. subst. simpl.
- simpl; omega.
-Qed.
-
-Lemma to_bblock_exit_noCFI c:
- get_code_nature c <> IsCFI ->
- to_bblock_exit c = (None, c).
-Proof.
- intros H. destruct c as [|i c]; simpl; auto.
- destruct i; simpl; auto.
- all: contradict H; simpl; auto.
-Qed.
-
-Lemma to_bblock_exit_wf c b c0:
- get_code_nature c = IsCFI ->
- to_bblock_exit c = (b, c0) ->
- (length c > length c0)%nat.
-Proof.
- intros H1 H2. destruct c as [|i c]; try discriminate.
- destruct i; try discriminate;
- unfold to_bblock_header in H2; inversion H2; auto.
-Qed.
-
-Lemma to_bblock_exit_wfe c b c0:
- to_bblock_exit c = (b, c0) ->
- (length c >= length c0)%nat.
-Proof.
- intros H. destruct c as [|i c].
- - simpl in H. inversion H; subst; clear H; auto.
- - destruct i; try ( simpl in H; inversion H; subst; clear H; auto ).
- all: simpl; auto.
-Qed.
-
-Definition to_bblock(c: Mach.code): bblock * Mach.code :=
- let (h,c0) := to_bblock_header c in
- let (bdy, c1) := to_bblock_body c0 in
- let (ext, c2) := to_bblock_exit c1 in
- ({| header := h; body := bdy; exit := ext |}, c2)
- .
-
-Lemma to_bblock_acc_label c l b c':
- to_bblock c = (b, c') ->
- to_bblock (Mlabel l :: c) = ({| header := l::(header b); body := (body b); exit := (exit b) |}, c').
-Proof.
- unfold to_bblock; simpl.
- remember (to_bblock_header c) as bhc; destruct bhc as [h c0].
- remember (to_bblock_body c0) as bbc; destruct bbc as [bdy c1].
- remember (to_bblock_exit c1) as bbc; destruct bbc as [ext c2].
- intros H; inversion H; subst; clear H; simpl; auto.
-Qed.
-
-Lemma to_bblock_basic_then_label i c bi:
- get_code_nature (i::c) = IsBasicInst ->
- get_code_nature c = IsLabel ->
- to_basic_inst i = Some bi ->
- fst (to_bblock (i::c)) = {| header := nil; body := bi::nil; exit := None |}.
-Proof.
- intros H1 H2 H3.
- destruct c as [|i' c]; try (contradict H1; simpl; discriminate).
- destruct i'; try (contradict H1; simpl; discriminate).
- destruct i; simpl in *; inversion H3; subst; auto.
-Qed.
-
-Lemma to_bblock_CFI i c cfi:
- get_code_nature (i::c) = IsCFI ->
- to_cfi i = Some cfi ->
- fst (to_bblock (i::c)) = {| header := nil; body := nil; exit := Some cfi |}.
-Proof.
- intros H1 H2.
- destruct i; try discriminate.
- all: subst; rewrite <- H2; simpl; auto.
-Qed.
-
-Lemma to_bblock_noLabel c:
- get_code_nature c <> IsLabel ->
- fst (to_bblock c) = {|
- header := nil;
- body := body (fst (to_bblock c));
- exit := exit (fst (to_bblock c))
- |}.
-Proof.
- intros H.
- destruct c as [|i c]; simpl; auto.
- apply bblock_eq; simpl;
- destruct i; (
- try (
- remember (to_bblock _) as bb;
- unfold to_bblock in *;
- remember (to_bblock_header _) as tbh;
- destruct tbh;
- destruct (to_bblock_body _);
- destruct (to_bblock_exit _);
- subst; simpl; inversion Heqtbh; auto; fail
- )
- || contradict H; simpl; auto ).
-Qed.
-
-Lemma to_bblock_body_nil c c':
- to_bblock_body c = (nil, c') ->
- c = c'.
-Proof.
- intros H.
- destruct c as [|i c]; [ simpl in *; inversion H; auto |].
- destruct i; try ( simpl in *; remember (to_bblock_body c) as tbc; destruct tbc as [p c'']; inversion H ).
- all: auto.
-Qed.
-
-Lemma to_bblock_exit_nil c c':
- to_bblock_exit c = (None, c') ->
- c = c'.
-Proof.
- intros H.
- destruct c as [|i c]; [ simpl in *; inversion H; auto |].
- destruct i; try ( simpl in *; remember (to_bblock_exit c) as tbe; destruct tbe as [p c'']; inversion H ).
- all: auto.
-Qed.
-
-Lemma to_bblock_label b l c c':
- to_bblock (Mlabel l :: c) = (b, c') ->
- (header b) = l::(tail (header b)) /\ to_bblock c = ({| header:=tail (header b); body := body b; exit := exit b |}, c').
-Proof.
- unfold to_bblock; simpl.
- remember (to_bblock_header c) as bhc; destruct bhc as [h c0].
- remember (to_bblock_body c0) as bbc; destruct bbc as [bdy c1].
- remember (to_bblock_exit c1) as bbc; destruct bbc as [ext c2].
- intros H; inversion H; subst; clear H; simpl; auto.
-Qed.
-
-Lemma to_bblock_basic c i bi:
- get_code_nature (i::c) = IsBasicInst ->
- to_basic_inst i = Some bi ->
- get_code_nature c <> IsLabel ->
- fst (to_bblock (i::c)) = {|
- header := nil;
- body := bi :: body (fst (to_bblock c));
- exit := exit (fst (to_bblock c))
- |}.
-Proof.
- intros.
- destruct c; try (destruct i; inversion H0; subst; simpl; auto; fail).
- apply bblock_eq; simpl.
-(* header *)
- + destruct i; simpl; auto; (
- exploit to_bblock_noLabel; [rewrite H; discriminate | intro; rewrite H2; simpl; auto]).
-(* body *)
-(* FIXME - the proof takes some time to prove.. N² complexity :( *)
- + unfold to_bblock.
- remember (to_bblock_header _) as tbh; destruct tbh.
- remember (to_bblock_body _) as tbb; destruct tbb.
- remember (to_bblock_exit _) as tbe; destruct tbe.
- simpl.
- destruct i; destruct i0.
- all: try (simpl in H1; contradiction).
- all: try discriminate.
- all: try (
- simpl in Heqtbh; inversion Heqtbh; clear Heqtbh; subst;
- simpl in Heqtbb; remember (to_bblock_body c) as tbbc; destruct tbbc;
- inversion Heqtbb; clear Heqtbb; subst; simpl in *; clear H H1;
- inversion H0; clear H0; subst; destruct (to_bblock_body c);
- inversion Heqtbbc; clear Heqtbbc; subst;
- destruct (to_bblock_exit c1); simpl; auto; fail).
-(* exit *)
- + unfold to_bblock.
- remember (to_bblock_header _) as tbh; destruct tbh.
- remember (to_bblock_body _) as tbb; destruct tbb.
- remember (to_bblock_exit _) as tbe; destruct tbe.
- simpl.
- destruct i; destruct i0.
- all: try (simpl in H1; contradiction).
- all: try discriminate.
- all: try (
- simpl in Heqtbh; inversion Heqtbh; clear Heqtbh; subst;
- simpl in Heqtbb; remember (to_bblock_body c) as tbbc; destruct tbbc;
- inversion Heqtbb; clear Heqtbb; subst; simpl in *; clear H H1;
- inversion H0; clear H0; subst; destruct (to_bblock_body c) eqn:TBBC;
- inversion Heqtbbc; clear Heqtbbc; subst;
- destruct (to_bblock_exit c1) eqn:TBBE; simpl;
- inversion Heqtbe; clear Heqtbe; subst; auto; fail).
-Qed.
-
-Lemma to_bblock_size_single_label c i:
- get_code_nature (i::c) = IsLabel ->
- size (fst (to_bblock (i::c))) = Datatypes.S (size (fst (to_bblock c))).
-Proof.
- intros H.
- destruct i; try discriminate.
- remember (to_bblock c) as bl. destruct bl as [b c'].
- erewrite to_bblock_acc_label; eauto.
- unfold size; simpl.
- auto.
-Qed.
-
-Lemma to_bblock_size_label_neqz c:
- get_code_nature c = IsLabel ->
- size (fst (to_bblock c)) <> 0%nat.
-Proof.
- destruct c as [ |i c]; try discriminate.
- intros; rewrite to_bblock_size_single_label; auto.
-Qed.
-
-Lemma to_bblock_size_basic_neqz c:
- get_code_nature c = IsBasicInst ->
- size (fst (to_bblock c)) <> 0%nat.
-Proof.
- intros H. destruct c as [|i c]; try (contradict H; auto; simpl; discriminate).
- destruct i; try (contradict H; simpl; discriminate);
- (
- destruct (get_code_nature c) eqn:gcnc;
- (* Case gcnc is not IsLabel *)
- try (erewrite to_bblock_basic; eauto; [
- unfold size; simpl; auto
- | simpl; auto
- | rewrite gcnc; discriminate
- ]);
- erewrite to_bblock_basic_then_label; eauto; [
- unfold size; simpl; auto
- | simpl; auto
- ]
- ).
-Qed.
-
-Lemma to_bblock_size_cfi_neqz c:
- get_code_nature c = IsCFI ->
- size (fst (to_bblock c)) <> 0%nat.
-Proof.
- intros H. destruct c as [|i c]; try (contradict H; auto; simpl; discriminate).
- destruct i; discriminate.
-Qed.
-
-Lemma to_bblock_size_single_basic c i:
- get_code_nature (i::c) = IsBasicInst ->
- get_code_nature c <> IsLabel ->
- size (fst (to_bblock (i::c))) = Datatypes.S (size (fst (to_bblock c))).
-Proof.
- intros.
- destruct i; try (contradict H; simpl; discriminate); try (
- (exploit to_bblock_basic; eauto);
- [remember (to_basic_inst _) as tbi; destruct tbi; eauto |];
- intro; rewrite H1; unfold size; simpl;
- assert ((length (header (fst (to_bblock c)))) = 0%nat);
- exploit to_bblock_noLabel; eauto; intro; rewrite H2; simpl; auto;
- rewrite H2; auto
- ).
-Qed.
-
-Lemma to_bblock_wf c b c0:
- c <> nil ->
- to_bblock c = (b, c0) ->
- (length c > length c0)%nat.
-Proof.
- intro H; lapply (get_code_nature_nil c); eauto.
- intro H'; remember (get_code_nature c) as gcn.
- unfold to_bblock.
- remember (to_bblock_header c) as p1; eauto.
- destruct p1 as [h c1].
- intro H0.
- destruct gcn.
- - contradict H'; auto.
- - exploit to_bblock_header_wf; eauto.
- remember (to_bblock_body c1) as p2; eauto.
- destruct p2 as [h2 c2].
- exploit to_bblock_body_wfe; eauto.
- remember (to_bblock_exit c2) as p3; eauto.
- destruct p3 as [h3 c3].
- exploit to_bblock_exit_wfe; eauto.
- inversion H0. omega.
- - exploit to_bblock_header_noLabel; eauto. rewrite <- Heqgcn. discriminate.
- intro. rewrite H1 in Heqp1. inversion Heqp1. clear Heqp1. subst.
- remember (to_bblock_body c) as p2; eauto.
- destruct p2 as [h2 c2].
- exploit to_bblock_body_wf; eauto.
- remember (to_bblock_exit c2) as p3; eauto.
- destruct p3 as [h3 c3].
- exploit to_bblock_exit_wfe; eauto.
- inversion H0. omega.
- - exploit to_bblock_header_noLabel; eauto. rewrite <- Heqgcn. discriminate.
- intro. rewrite H1 in Heqp1. inversion Heqp1; clear Heqp1; subst.
- remember (to_bblock_body c) as p2; eauto.
- destruct p2 as [h2 c2].
- exploit (to_bblock_body_noBasic c); eauto. rewrite <- Heqgcn. discriminate.
- intros H2; rewrite H2 in Heqp2; inversion Heqp2; clear Heqp2; subst.
- remember (to_bblock_exit c) as p3; eauto.
- destruct p3 as [h3 c3].
- exploit (to_bblock_exit_wf c h3 c3); eauto.
- inversion H0. omega.
-Qed.
-
-Lemma to_bblock_nonil i c0:
- size (fst (to_bblock (i :: c0))) <> 0%nat.
-Proof.
- intros H. remember (i::c0) as c. remember (get_code_nature c) as gcnc. destruct gcnc.
- - contradict Heqgcnc. subst. simpl. destruct i; discriminate.
- - eapply to_bblock_size_label_neqz; eauto.
- - eapply to_bblock_size_basic_neqz; eauto.
- - eapply to_bblock_size_cfi_neqz; eauto.
-Qed.
-
-Function trans_code (c: Mach.code) { measure length c }: code :=
+(* ajout d'une instruction en début d'une liste de blocks *)
+(* Soit /1\ ajout en tête de block, soit /2\ ajout dans un nouveau block*)
+(* bl est vide -> /2\ *)
+(* cfi -> /2\ (ajout dans exit)*)
+(* basic -> /1\ si header vide, /2\ si a un header *)
+(* label -> /1\ (dans header)*)
+Definition add_to_code (i:Machblock_inst) (bl:code) : code :=
+ match bl with
+ | bh::bl0 => match i with
+ | MB_label l => add_label l bh::bl0
+ | MB_cfi i0 => cfi_bblock i0::bl
+ | MB_basic i0 => match header bh with
+ |_::_ => add_basic i0 empty_bblock::bl
+ | nil => add_basic i0 bh::bl0
+ end
+ end
+ | _ => add_to_new_bblock i::nil
+ end.
+
+Fixpoint trans_code_rev (c: Mach.code) (bl:code) : code :=
match c with
- | nil => nil
- | _ =>
- let (b, c0) := to_bblock c in
- b::(trans_code c0)
+ | nil => bl
+ | i::c0 =>
+ trans_code_rev c0 (add_to_code (trans_inst i) bl)
end.
-Proof.
- intros; eapply to_bblock_wf; eauto. discriminate.
-Qed.
-
-Lemma trans_code_nonil c:
- c <> nil -> trans_code c <> nil.
-Proof.
- intros H.
- induction c, (trans_code c) using trans_code_ind; simpl; auto. discriminate.
-Qed.
-Lemma trans_code_step c b lb0 hb c1 bb c2 eb c3:
- trans_code c = b :: lb0 ->
- to_bblock_header c = (hb, c1) ->
- to_bblock_body c1 = (bb, c2) ->
- to_bblock_exit c2 = (eb, c3) ->
- hb = header b /\ bb = body b /\ eb = exit b /\ trans_code c3 = lb0.
-Proof.
- intros.
- induction c, (trans_code c) using trans_code_ind. discriminate. clear IHc0.
- subst. destruct _x as [|i c]; try (contradict y; auto; fail).
- inversion H; subst. clear H. unfold to_bblock in e0.
- remember (to_bblock_header (i::c)) as hd. destruct hd as [hb' c1'].
- remember (to_bblock_body c1') as bd. destruct bd as [bb' c2'].
- remember (to_bblock_exit c2') as be. destruct be as [eb' c3'].
- inversion e0. simpl.
- inversion H0. subst.
- rewrite <- Heqbd in H1. inversion H1. subst.
- rewrite <- Heqbe in H2. inversion H2. subst.
- auto.
-Qed.
+Function trans_code (c: Mach.code) : code :=
+ trans_code_rev (List.rev_append c nil) nil.
-Lemma trans_code_cfi i c cfi:
- to_cfi i = Some cfi ->
- trans_code (i :: c) = {| header := nil ; body := nil ; exit := Some cfi |} :: trans_code c.
-Proof.
- intros. rewrite trans_code_equation. remember (to_bblock _) as tb; destruct tb as [b c0].
- destruct i; try (contradict H; discriminate).
- all: unfold to_bblock in Heqtb; remember (to_bblock_header _) as tbh; destruct tbh as [h c0'];
- remember (to_bblock_body c0') as tbb; destruct tbb as [bdy c1'];
- remember (to_bblock_exit c1') as tbe; destruct tbe as [ext c2]; simpl in *;
- inversion Heqtbh; subst; inversion Heqtbb; subst; inversion Heqtbe; subst;
- inversion Heqtb; subst; rewrite H; auto.
-Qed.
(* à finir pour passer des Mach.function au function, etc. *)
Definition transf_function (f: Mach.function) : function :=
@@ -576,3 +101,107 @@ Definition transf_fundef (f: Mach.fundef) : fundef :=
Definition transf_program (src: Mach.program) : program :=
transform_program transf_fundef src.
+
+
+(** Abstraction de trans_code *)
+
+Inductive is_end_block: Machblock_inst -> code -> Prop :=
+ | End_empty mbi: is_end_block mbi nil
+ | End_basic bi bh bl: header bh <> nil -> is_end_block (MB_basic bi) (bh::bl)
+ | End_cfi cfi bl: bl <> nil -> is_end_block (MB_cfi cfi) bl.
+
+Local Hint Resolve End_empty End_basic End_cfi.
+
+Inductive is_trans_code: Mach.code -> code -> Prop :=
+ | Tr_nil: is_trans_code nil nil
+ | Tr_end_block i c bl:
+ is_trans_code c bl ->
+ is_end_block (trans_inst i) bl ->
+ is_trans_code (i::c) (add_to_new_bblock (trans_inst i)::bl)
+ | Tr_add_label i l bh c bl:
+ is_trans_code c (bh::bl) ->
+ i = Mlabel l ->
+ is_trans_code (i::c) (add_label l bh::bl)
+ | Tr_add_basic i bi bh c bl:
+ is_trans_code c (bh::bl) ->
+ trans_inst i = MB_basic bi ->
+ header bh = nil ->
+ is_trans_code (i::c) (add_basic bi bh::bl).
+
+Local Hint Resolve Tr_nil Tr_end_block.
+
+Lemma add_to_code_is_trans_code i c bl:
+ is_trans_code c bl ->
+ is_trans_code (i::c) (add_to_code (trans_inst i) bl).
+Proof.
+ destruct bl as [|bh0 bl]; simpl.
+ - intro H. inversion H. subst. eauto.
+ - remember (trans_inst i) as ti.
+ destruct ti as [l|bi|cfi].
+ + intros; eapply Tr_add_label; eauto. destruct i; simpl in * |- *; congruence.
+ + intros. remember (header bh0) as hbh0. destruct hbh0 as [|b].
+ * eapply Tr_add_basic; eauto.
+ * cutrewrite (add_basic bi empty_bblock = add_to_new_bblock (MB_basic bi)); auto.
+ rewrite Heqti; eapply Tr_end_block; eauto.
+ rewrite <- Heqti. eapply End_basic. congruence.
+ + intros.
+ cutrewrite (cfi_bblock cfi = add_to_new_bblock (MB_cfi cfi)); auto.
+ rewrite Heqti. eapply Tr_end_block; eauto.
+ rewrite <- Heqti. eapply End_cfi. congruence.
+Qed.
+
+Local Hint Resolve add_to_code_is_trans_code.
+
+Lemma trans_code_is_trans_code_rev c1: forall c2 mbi,
+ is_trans_code c2 mbi ->
+ is_trans_code (rev_append c1 c2) (trans_code_rev c1 mbi).
+Proof.
+ induction c1 as [| i c1]; simpl; auto.
+Qed.
+
+Lemma trans_code_is_trans_code c: is_trans_code c (trans_code c).
+Proof.
+ unfold trans_code.
+ rewrite <- rev_alt.
+ rewrite <- (rev_involutive c) at 1.
+ rewrite rev_alt at 1.
+ apply trans_code_is_trans_code_rev; auto.
+Qed.
+
+Lemma add_to_code_is_trans_code_inv i c bl:
+ is_trans_code (i::c) bl -> exists bl0, is_trans_code c bl0 /\ bl = add_to_code (trans_inst i) bl0.
+Proof.
+ intro H; inversion H as [|H0 H1 bl0| | H0 bi bh H1 bl0]; clear H; subst; (repeat econstructor); eauto.
+ + (* case Tr_end_block *) inversion H3; subst; simpl; auto.
+ * destruct (header bh); congruence.
+ * destruct bl0; simpl; congruence.
+ + (* case Tr_add_basic *) rewrite H3. simpl. destruct (header bh); congruence.
+Qed.
+
+Lemma trans_code_is_trans_code_rev_inv c1: forall c2 mbi,
+ is_trans_code (rev_append c1 c2) mbi ->
+ exists mbi0, is_trans_code c2 mbi0 /\ mbi=trans_code_rev c1 mbi0.
+Proof.
+ induction c1 as [| i c1]; simpl; eauto.
+ intros; exploit IHc1; eauto.
+ intros (mbi0 & H1 & H2); subst.
+ exploit add_to_code_is_trans_code_inv; eauto.
+ intros. destruct H0 as [mbi1 [H2 H3]].
+ exists mbi1. split; congruence.
+Qed.
+
+Local Hint Resolve trans_code_is_trans_code.
+
+Theorem is_trans_code_inv c bl: is_trans_code c bl <-> bl=(trans_code c).
+Proof.
+ constructor; intros; subst; auto.
+ unfold trans_code.
+ exploit (trans_code_is_trans_code_rev_inv (rev_append c nil) nil bl); eauto.
+ * rewrite <- rev_alt.
+ rewrite <- rev_alt.
+ rewrite (rev_involutive c).
+ apply H.
+ * intros.
+ destruct H0 as [mbi [H0 H1]].
+ inversion H0. subst. reflexivity.
+Qed.
diff --git a/mppa_k1c/Machblockgenproof.v b/mppa_k1c/Machblockgenproof.v
index 62c1e0ed..9186e54a 100644
--- a/mppa_k1c/Machblockgenproof.v
+++ b/mppa_k1c/Machblockgenproof.v
@@ -17,6 +17,11 @@ Require Import Machblock.
Require Import Machblockgen.
Require Import ForwardSimulationBlock.
+Ltac subst_is_trans_code H :=
+ rewrite is_trans_code_inv in H;
+ rewrite <- H in * |- *;
+ rewrite <- is_trans_code_inv in H.
+
Definition inv_trans_rao (rao: function -> code -> ptrofs -> Prop) (f: Mach.function) (c: Mach.code) :=
rao (transf_function f) (trans_code c).
@@ -39,7 +44,7 @@ Fixpoint trans_stack (mst: list Mach.stackframe) : list stackframe :=
| msf :: mst0 => (trans_stackframe msf) :: (trans_stack mst0)
end.
-Definition trans_state (ms: Mach.state) : state :=
+Definition trans_state (ms: Mach.state): state :=
match ms with
| Mach.State s f sp c rs m => State (trans_stack s) f sp (trans_code c) rs m
| Mach.Callstate s f rs m => Callstate (trans_stack s) f rs m
@@ -163,6 +168,35 @@ Proof.
+ revert H. unfold Mach.find_label. simpl. rewrite peq_false; auto.
Qed.
+Lemma find_label_is_end_block_not_label i l c bl:
+ is_end_block (trans_inst i) bl ->
+ is_trans_code c bl ->
+ i <> Mlabel l -> find_label l (add_to_new_bblock (trans_inst i) :: bl) = find_label l bl.
+Proof.
+ intros H H0 H1.
+ unfold find_label.
+ remember (is_label l _) as b.
+ cutrewrite (b = false); auto.
+ subst; unfold is_label.
+ destruct i; simpl in * |- *; try (destruct (in_dec l nil); intuition).
+ inversion H.
+ destruct (in_dec l (l0::nil)) as [H6|H6]; auto.
+ simpl in H6; intuition try congruence.
+Qed.
+
+Lemma find_label_at_begin l bh bl:
+ In l (header bh)
+ -> find_label l (bh :: bl) = Some (bh::bl).
+Proof.
+ unfold find_label; rewrite is_label_correct_true; intro H; rewrite H; simpl; auto.
+Qed.
+
+Lemma find_label_add_label_diff l bh bl:
+ ~(In l (header bh)) ->
+ find_label l (bh::bl) = find_label l bl.
+Proof.
+ unfold find_label; rewrite is_label_correct_false; intro H; rewrite H; simpl; auto.
+Qed.
Definition concat (h: list label) (c: code): code :=
match c with
@@ -170,128 +204,69 @@ Definition concat (h: list label) (c: code): code :=
| b::c' => {| header := h ++ (header b); body := body b; exit := exit b |}::c'
end.
-Lemma to_bblock_start_label i c l b c0:
- (b, c0) = to_bblock (i :: c)
- -> In l (header b)
- -> i <> Mlabel l
- -> exists l2, i=Mlabel l2.
-Proof.
- unfold to_bblock.
- remember (to_bblock_header _) as bh; destruct bh as [h c1].
- remember (to_bblock_body _) as bb; destruct bb as [bdy c2].
- remember (to_bblock_exit _) as be; destruct be as [ext c3].
- intros H; inversion H; subst; clear H; simpl.
- destruct i; try (simpl in Heqbh; inversion Heqbh; subst; clear Heqbh; simpl; intuition eauto).
-Qed.
-
-Lemma find_label_stop c:
- forall l b c0 c',
- (b, c0) = to_bblock c
- -> Mach.find_label l c = Some c'
- -> In l (header b)
- -> exists h, In l h /\ Some (b :: trans_code c0) = Some (concat h (trans_code c')).
-Proof.
- induction c as [ |i c].
- - simpl; intros; discriminate.
- - intros l b c0 c' H H1 H2.
- exploit Mach_find_label_split; eauto; clear H1.
- intros [(X1 & X2) | (X1 & X2)].
- * subst. exploit to_bblock_label; eauto. clear H.
- intros (H3 & H4). constructor 1 with (x:=l::nil); simpl; intuition auto.
- symmetry.
- rewrite trans_code_equation.
- destruct c as [ |i c].
- + unfold to_bblock in H4; simpl in H4.
- injection H4. clear H4; intros H4 H H0 H1; subst. simpl.
- rewrite trans_code_equation; simpl.
- rewrite <- H1 in H3; clear H1.
- destruct b as [h b e]; simpl in * |- *; subst; auto.
- + rewrite H4; clear H4; simpl. rewrite <- H3; clear H3.
- destruct b; simpl; auto.
- * exploit to_bblock_start_label; eauto.
- intros (l' & H'). subst.
- assert (X: l' <> l). { intro Z; subst; destruct X1; auto. }
- clear X1.
- exploit to_bblock_label; eauto. clear H.
- intros (H3 & H4).
- exploit IHc; eauto. { simpl. rewrite H3 in H2; simpl in H2. destruct H2; subst; tauto. }
- intros (h' & H5 & H6).
- constructor 1 with (x:=l'::h'); simpl; intuition auto.
- destruct b as [h b e]; simpl in * |- *; subst.
- remember (tl h) as th. subst h.
- remember (trans_code c') as tcc'.
- rewrite trans_code_equation in Heqtcc'.
- destruct c'; subst; simpl in * |- *.
- + inversion H6; subst; auto.
- + destruct (to_bblock (i :: c')) as [b1 c1]. simpl in * |- *.
- inversion H6; subst; auto.
-Qed.
-
-Lemma to_bblock_header_find_label c l: forall c1 h c',
- to_bblock_header c = (h, c1)
- -> Mach.find_label l c = Some c'
- -> ~ In l h
- -> Mach.find_label l c = Mach.find_label l c1.
-Proof.
- induction c as [|i c]; simpl; auto.
- - intros; discriminate.
- - destruct i;
- try (simpl; intros c1 h c' H1 H2; inversion H1; subst; clear H1; intros; apply refl_equal).
- remember (to_bblock_header c) as tbhc. destruct tbhc as [h2 c2].
- intros h c1 c' H1; inversion H1; subst; clear H1.
- simpl. destruct (peq _ _).
- + subst; tauto.
- + intros H1 H2; erewrite IHc; eauto.
-Qed.
-
-Lemma to_bblock_body_find_label c1 l: forall c2 bdy,
- (bdy, c2) = to_bblock_body c1 ->
- Mach.find_label l c1 = Mach.find_label l c2.
-Proof.
- induction c1 as [|i c1].
- - intros bdy0 c0 H. simpl in H. inversion H; subst; clear H. auto.
- - intros bdy' c2' H. simpl in H. destruct i; try (
- simpl in H; remember (to_bblock_body c1) as tbb; destruct tbb as [p c''];
- inversion H; subst; clear H; simpl; erewrite IHc1; eauto; fail).
-Qed.
-
-Lemma to_bblock_exit_find_label c1 l c2 ext:
- (ext, c2) = to_bblock_exit c1
- -> Mach.find_label l c1 = Mach.find_label l c2.
-Proof.
- intros H. destruct c1 as [|i c1].
- - simpl in H. inversion H; subst; clear H. auto.
- - destruct i; try (
- simpl in H; inversion H; subst; clear H; auto; fail).
-Qed.
-
Lemma find_label_transcode_preserved:
forall l c c',
Mach.find_label l c = Some c' ->
exists h, In l h /\ find_label l (trans_code c) = Some (concat h (trans_code c')).
Proof.
- intros l c; induction c, (trans_code c) using trans_code_ind.
- - intros c' H; inversion H.
- - intros c' H. subst _x. destruct c as [| i c]; try tauto.
- unfold to_bblock in * |-.
- remember (to_bblock_header _) as bh; destruct bh as [h c1].
- remember (to_bblock_body _) as bb; destruct bb as [bdy c2].
- remember (to_bblock_exit _) as be; destruct be as [ext c3].
- simpl; injection e0; intros; subst; clear e0.
- unfold is_label; simpl; destruct (in_dec l h) as [Y|Y].
- + clear IHc0.
- eapply find_label_stop; eauto.
- unfold to_bblock.
- rewrite <- Heqbh, <- Heqbb, <- Heqbe.
- auto.
- + exploit IHc0; eauto. clear IHc0.
- rewrite <- H.
- erewrite (to_bblock_header_find_label (i::c) l c1); eauto.
- erewrite (to_bblock_body_find_label c1 l c2); eauto.
- erewrite (to_bblock_exit_find_label c2 l c0); eauto.
+ intros l c. remember (trans_code _) as bl.
+ rewrite <- is_trans_code_inv in * |-.
+ induction Heqbl.
+ + (* Tr_nil *)
+ intros; exists (l::nil); simpl in * |- *; intuition.
+ discriminate.
+ + (* Tr_end_block *)
+ intros.
+ exploit Mach_find_label_split; eauto.
+ clear H0; destruct 1 as [(H0&H2)|(H0&H2)].
+ - subst. rewrite find_label_at_begin; simpl; auto.
+ inversion H as [mbi H1 H2| | ].
+ subst.
+ inversion Heqbl.
+ subst.
+ exists (l :: nil); simpl; eauto.
+ - exploit IHHeqbl; eauto.
+ destruct 1 as (h & H3 & H4).
+ exists h.
+ split; auto.
+ erewrite find_label_is_end_block_not_label;eauto.
+ + (* Tr_add_label *)
+ intros.
+ exploit Mach_find_label_split; eauto.
+ clear H0; destruct 1 as [(H0&H2)|(H0&H2)].
+ - subst.
+ inversion H0 as [H1].
+ clear H0.
+ erewrite find_label_at_begin; simpl; eauto.
+ subst_is_trans_code Heqbl.
+ exists (l :: nil); simpl; eauto.
+ - subst; assert (H: l0 <> l); try congruence; clear H0.
+ exploit IHHeqbl; eauto.
+ clear IHHeqbl Heqbl.
+ intros (h & H3 & H4).
+ simpl; unfold is_label, add_label; simpl.
+ destruct (in_dec l (l0::header bh)) as [H5|H5]; simpl in H5.
+ * destruct H5; try congruence.
+ exists (l0::h); simpl; intuition.
+ rewrite find_label_at_begin in H4; auto.
+ apply f_equal. inversion H4 as [H5]. clear H4.
+ destruct (trans_code c'); simpl in * |- *;
+ inversion H5; subst; simpl; auto.
+ * exists h. intuition.
+ erewrite <- find_label_add_label_diff; eauto.
+ + (* Tr_add_basic *)
+ intros.
+ exploit Mach_find_label_split; eauto.
+ destruct 1 as [(H2&H3)|(H2&H3)].
+ rewrite H2 in H. unfold trans_inst in H. congruence.
+ exploit IHHeqbl; eauto.
+ clear IHHeqbl Heqbl.
+ intros (h & H4 & H5).
+ rewrite find_label_add_label_diff; auto.
+ rewrite find_label_add_label_diff in H5; eauto.
+ rewrite H0; auto.
Qed.
-
Lemma find_label_preserved:
forall l f c,
Mach.find_label l (Mach.fn_code f) = Some c ->
@@ -311,8 +286,12 @@ Qed.
Local Hint Resolve symbols_preserved senv_preserved init_mem_preserved prog_main_preserved functions_translated
parent_sp_preserved.
-Definition dist_end_block_code (c: Mach.code) := (size (fst (to_bblock c))-1)%nat.
+Definition dist_end_block_code (c: Mach.code) :=
+ match trans_code c with
+ | nil => 0
+ | bh::_ => (size bh-1)%nat
+ end.
Definition dist_end_block (s: Mach.state): nat :=
match s with
@@ -323,65 +302,174 @@ Definition dist_end_block (s: Mach.state): nat :=
Local Hint Resolve exec_nil_body exec_cons_body.
Local Hint Resolve exec_MBgetstack exec_MBsetstack exec_MBgetparam exec_MBop exec_MBload exec_MBstore.
-Ltac ExploitDistEndBlockCode :=
- match goal with
- | [ H : dist_end_block_code (Mlabel ?l :: ?c) <> 0%nat |- _ ] =>
- exploit (to_bblock_size_single_label c (Mlabel l)); eauto
- | [ H : dist_end_block_code (?i0 :: ?c) <> 0%nat |- _ ] =>
- exploit (to_bblock_size_single_basic c i0); eauto
- | _ => idtac
- end.
+Lemma size_add_label l bh: size (add_label l bh) = size bh + 1.
+Proof.
+ unfold add_label, size; simpl; omega.
+Qed.
+
+Lemma size_add_basic bi bh: header bh = nil -> size (add_basic bi bh) = size bh + 1.
+Proof.
+ intro H. unfold add_basic, size; rewrite H; simpl. omega.
+Qed.
+
+
+Lemma size_add_to_newblock i: size (add_to_new_bblock i) = 1.
+Proof.
+ destruct i; auto.
+Qed.
-Ltac totologize H :=
- match type of H with
- | ( ?id = _ ) =>
- let Hassert := fresh "Htoto" in (
- assert (id = id) as Hassert; auto; rewrite H in Hassert at 2; simpl in Hassert; rewrite H in Hassert)
- end.
Lemma dist_end_block_code_simu_mid_block i c:
dist_end_block_code (i::c) <> 0 ->
(dist_end_block_code (i::c) = Datatypes.S (dist_end_block_code c)).
Proof.
- intros H.
unfold dist_end_block_code.
- destruct (get_code_nature (i::c)) eqn:GCNIC.
- - apply get_code_nature_empty in GCNIC. discriminate.
- - rewrite to_bblock_size_single_label; auto.
- destruct c as [|i' c].
- + contradict H. destruct i; simpl; auto.
- + assert (size (fst (to_bblock (i'::c))) <> 0). apply to_bblock_nonil. omega.
- - destruct (get_code_nature c) eqn:GCNC.
- + apply get_code_nature_empty in GCNC. subst. contradict H. destruct i; simpl; auto.
- + contradict H. destruct c as [|i' c]; try discriminate.
- destruct i'; try discriminate.
- destruct i; try discriminate. all: simpl; auto.
- + destruct (to_basic_inst i) eqn:TBI; [| destruct i; discriminate].
- erewrite to_bblock_basic; eauto; [| rewrite GCNC; discriminate ].
- simpl. destruct c as [|i' c]; try discriminate.
- assert (size (fst (to_bblock (i'::c))) <> 0). apply to_bblock_nonil.
- cutrewrite (Datatypes.S (size (fst (to_bblock (i'::c))) - 1) = size (fst (to_bblock (i'::c)))).
- unfold size. cutrewrite (length (header (fst (to_bblock (i' :: c)))) = 0). simpl. omega.
- rewrite to_bblock_noLabel. simpl; auto.
- rewrite GCNC. discriminate.
- omega.
- + destruct (to_basic_inst i) eqn:TBI; [| destruct i; discriminate].
- erewrite to_bblock_basic; eauto; [| rewrite GCNC; discriminate ].
- simpl. destruct c as [|i' c]; try discriminate.
- assert (size (fst (to_bblock (i'::c))) <> 0). apply to_bblock_nonil.
- cutrewrite (Datatypes.S (size (fst (to_bblock (i'::c))) - 1) = size (fst (to_bblock (i'::c)))).
- unfold size. cutrewrite (length (header (fst (to_bblock (i' :: c)))) = 0). simpl. omega.
- rewrite to_bblock_noLabel. simpl; auto.
- rewrite GCNC. discriminate.
- omega.
- - contradict H. destruct i; try discriminate.
- all: unfold dist_end_block_code; erewrite to_bblock_CFI; eauto; simpl; eauto.
+ remember (trans_code (i::c)) as bl.
+ rewrite <- is_trans_code_inv in Heqbl.
+ inversion Heqbl as [|bl0 H| |]; subst; clear Heqbl.
+ - rewrite size_add_to_newblock; omega.
+ - rewrite size_add_label;
+ subst_is_trans_code H.
+ omega.
+ - rewrite size_add_basic; auto.
+ subst_is_trans_code H.
+ omega.
Qed.
Local Hint Resolve dist_end_block_code_simu_mid_block.
+
+Lemma size_nonzero c b bl:
+ is_trans_code c (b :: bl) -> size b <> 0.
+Proof.
+ intros H; inversion H; subst.
+ - rewrite size_add_to_newblock; omega.
+ - rewrite size_add_label; omega.
+ - rewrite size_add_basic; auto; omega.
+Qed.
+
+Inductive is_header: list label -> Mach.code -> Mach.code -> Prop :=
+ | header_empty : is_header nil nil nil
+ | header_not_label i c: (forall l, i <> Mlabel l) -> is_header nil (i::c) (i::c)
+ | header_is_label l h c c0: is_header h c c0 -> is_header (l::h) ((Mlabel l)::c) c0
+ .
+
+Inductive is_body: list basic_inst -> Mach.code -> Mach.code -> Prop :=
+ | body_empty : is_body nil nil nil
+ | body_not_bi i c: (forall bi, (trans_inst i) <> (MB_basic bi)) -> is_body nil (i::c) (i::c)
+ | body_is_bi i lbi c0 c1 bi: (trans_inst i) = MB_basic bi -> is_body lbi c0 c1 -> is_body (bi::lbi) (i::c0) c1
+ .
+
+Inductive is_exit: option control_flow_inst -> Mach.code -> Mach.code -> Prop :=
+ | exit_empty: is_exit None nil nil
+ | exit_not_cfi i c: (forall cfi, (trans_inst i) <> MB_cfi cfi) -> is_exit None (i::c) (i::c)
+ | exit_is_cfi i c cfi: (trans_inst i) = MB_cfi cfi -> is_exit (Some cfi) (i::c) c
+ .
+
+Lemma Mlabel_is_not_basic i:
+ forall bi, trans_inst i = MB_basic bi -> forall l, i <> Mlabel l.
+Proof.
+intros.
+unfold trans_inst in H.
+destruct i; congruence.
+Qed.
+
+Lemma Mlabel_is_not_cfi i:
+ forall cfi, trans_inst i = MB_cfi cfi -> forall l, i <> Mlabel l.
+Proof.
+intros.
+unfold trans_inst in H.
+destruct i; congruence.
+Qed.
+
+Lemma MBbasic_is_not_cfi i:
+ forall cfi, trans_inst i = MB_cfi cfi -> forall bi, trans_inst i <> MB_basic bi.
+Proof.
+intros.
+unfold trans_inst in H.
+unfold trans_inst.
+destruct i; congruence.
+Qed.
+
+
+Local Hint Resolve Mlabel_is_not_cfi.
+Local Hint Resolve MBbasic_is_not_cfi.
+
+Lemma add_to_new_block_is_label i:
+ header (add_to_new_bblock (trans_inst i)) <> nil -> exists l, i = Mlabel l.
+Proof.
+ intros.
+ unfold add_to_new_bblock in H.
+ destruct (trans_inst i) eqn : H1.
+ + exists lbl.
+ unfold trans_inst in H1.
+ destruct i; congruence.
+ + unfold add_basic in H; simpl in H; congruence.
+ + unfold cfi_bblock in H; simpl in H; congruence.
+Qed.
+
+Local Hint Resolve Mlabel_is_not_basic.
+
+Lemma trans_code_decompose c: forall b bl,
+ is_trans_code c (b::bl) ->
+ exists c0 c1 c2, is_header (header b) c c0 /\ is_body (body b) c0 c1 /\ is_exit (exit b) c1 c2 /\ is_trans_code c2 bl.
+Proof.
+ induction c as [|i c].
+ { (* nil => absurd *) intros b bl H; inversion H. }
+ intros b bl H; remember (trans_inst i) as ti.
+ destruct ti as [lbl|bi|cfi];
+ inversion H as [|d0 d1 d2 H0 H1| |]; subst;
+ try (rewrite <- Heqti in * |- *); simpl in * |- *;
+ try congruence.
+ + (* label at end block *)
+ inversion H1; subst. inversion H0; subst.
+ assert (X:i=Mlabel lbl). { destruct i; simpl in Heqti; congruence. }
+ subst. repeat econstructor; eauto.
+ + (* label at mid block *)
+ exploit IHc; eauto.
+ intros (c0 & c1 & c2 & H1 & H2 & H3 & H4).
+ repeat econstructor; eauto.
+ + (* basic at end block *)
+ inversion H1; subst.
+ lapply (Mlabel_is_not_basic i bi); auto.
+ intro H2.
+ - inversion H0; subst.
+ assert (X:(trans_inst i) = MB_basic bi ). { repeat econstructor; congruence. }
+ repeat econstructor; congruence.
+ - exists (i::c), c, c.
+ repeat econstructor; eauto; inversion H0; subst; repeat econstructor; simpl; try congruence.
+ * exploit (add_to_new_block_is_label i0); eauto.
+ intros (l & H8); subst; simpl; congruence.
+ * exploit H3; eauto.
+ * exploit (add_to_new_block_is_label i0); eauto.
+ intros (l & H8); subst; simpl; congruence.
+ + (* basic at mid block *)
+ inversion H1; subst.
+ exploit IHc; eauto.
+ intros (c0 & c1 & c2 & H3 & H4 & H5 & H6).
+ exists (i::c0), c1, c2.
+ repeat econstructor; eauto.
+ rewrite H2 in H3.
+ inversion H3; econstructor; eauto.
+ + (* cfi at end block *)
+ inversion H1; subst;
+ repeat econstructor; eauto.
+Qed.
+
+
+Lemma step_simu_header st f sp rs m s c h c' t:
+ is_header h c c' ->
+ starN (Mach.step (inv_trans_rao rao)) (Genv.globalenv prog) (length h) (Mach.State st f sp c rs m) t s ->
+ s = Mach.State st f sp c' rs m /\ t = E0.
+Proof.
+ induction 1; simpl; intros hs; try (inversion hs; tauto).
+ inversion hs as [|n1 s1 t1 t2 s2 t3 s3 H1]. inversion H1. subst. auto.
+Qed.
+
+
+
Lemma step_simu_basic_step (i: Mach.instruction) (bi: basic_inst) (c: Mach.code) s f sp rs m (t:trace) (s':Mach.state):
- to_basic_inst i = Some bi ->
+ trans_inst i = MB_basic bi ->
Mach.step (inv_trans_rao rao) ge (Mach.State s f sp (i::c) rs m) t s' ->
exists rs' m', s'=Mach.State s f sp c rs' m' /\ t=E0 /\ basic_step tge (trans_stack s) f sp rs m bi rs' m'.
Proof.
@@ -400,80 +488,71 @@ Proof.
Qed.
-Lemma star_step_simu_body_step s f sp c:
- forall (p:bblock_body) c' rs m t s',
- to_bblock_body c = (p, c') ->
- starN (Mach.step (inv_trans_rao rao)) ge (length p) (Mach.State s f sp c rs m) t s' ->
- exists rs' m', s'=Mach.State s f sp c' rs' m' /\ t=E0 /\ body_step tge (trans_stack s) f sp p rs m rs' m'.
-Proof.
- induction c as [ | i0 c0 Hc0]; simpl; intros p c' rs m t s' H.
- * (* nil *)
- inversion_clear H; simpl; intros X; inversion_clear X.
- eapply ex_intro; eapply ex_intro; intuition eauto.
- * (* cons *)
- remember (to_basic_inst i0) as o eqn:Ho.
- destruct o as [bi |].
- + (* to_basic_inst i0 = Some bi *)
- remember (to_bblock_body c0) as r eqn:Hr.
- destruct r as [p1 c1]; inversion H; simpl; subst; clear H.
- intros X; inversion_clear X.
- exploit step_simu_basic_step; eauto.
- intros [rs' [m' [H2 [H3 H4]]]]; subst.
- exploit Hc0; eauto.
- intros [rs'' [m'' [H5 [H6 H7]]]]; subst.
- refine (ex_intro _ rs'' (ex_intro _ m'' _)); intuition eauto.
- + (* to_basic_inst i0 = None *)
- inversion_clear H; simpl.
- intros X; inversion_clear X. intuition eauto.
-Qed.
+Lemma star_step_simu_body_step s f sp c bdy c':
+ is_body bdy c c' -> forall rs m t s',
+ starN (Mach.step (inv_trans_rao rao)) ge (length bdy) (Mach.State s f sp c rs m) t s' ->
+ exists rs' m', s'=Mach.State s f sp c' rs' m' /\ t=E0 /\ body_step tge (trans_stack s) f sp bdy rs m rs' m'.
+Proof.
+ induction 1; simpl.
+ + intros. inversion H. exists rs. exists m. auto.
+ + intros. inversion H0. exists rs. exists m. auto.
+ + intros. inversion H1; subst.
+ exploit (step_simu_basic_step ); eauto.
+ destruct 1 as [ rs1 [ m1 Hs]].
+ destruct Hs as [Hs1 [Hs2 Hs3]].
+ destruct (IHis_body rs1 m1 t2 s') as [rs2 Hb]. rewrite <- Hs1; eauto.
+ destruct Hb as [m2 [Hb1 [Hb2 Hb3]]].
+ exists rs2, m2.
+ rewrite Hs2, Hb2; eauto.
+ Qed.
Local Hint Resolve exec_MBcall exec_MBtailcall exec_MBbuiltin exec_MBgoto exec_MBcond_true exec_MBcond_false exec_MBjumptable exec_MBreturn exec_Some_exit exec_None_exit.
Local Hint Resolve eval_builtin_args_preserved external_call_symbols_preserved find_funct_ptr_same.
+
Lemma match_states_concat_trans_code st f sp c rs m h:
match_states (Mach.State st f sp c rs m) (State (trans_stack st) f sp (concat h (trans_code c)) rs m).
Proof.
- constructor 1; simpl.
+ intros; constructor 1; simpl.
+ intros (t0 & s1' & H0) t s'.
- rewrite! trans_code_equation.
- destruct c as [| i c]. { inversion H0. }
- remember (to_bblock (i :: c)) as bic. destruct bic as [b c0].
- simpl.
- constructor 1; intros H; inversion H; subst; simpl in * |- *;
- eapply exec_bblock; eauto.
- - inversion H11; subst; eauto.
- inversion H2; subst; eauto.
- - inversion H11; subst; simpl; eauto.
- inversion H2; subst; simpl; eauto.
+ remember (trans_code _) as bl.
+ destruct bl as [|bh bl].
+ { rewrite <- is_trans_code_inv in Heqbl; inversion Heqbl; inversion H0; congruence. }
+ clear H0.
+ simpl; constructor 1;
+ intros X; inversion X as [d1 d2 d3 d4 d5 d6 d7 rs' m' d10 d11 X1 X2| | | ]; subst; simpl in * |- *;
+ eapply exec_bblock; eauto; simpl;
+ inversion X2 as [cfi d1 d2 d3 H1|]; subst; eauto;
+ inversion H1; subst; eauto.
+ intros H r; constructor 1; intro X; inversion X.
Qed.
-Lemma step_simu_cfi_step:
- forall c e c' stk f sp rs m t s' b lb',
- to_bblock_exit c = (Some e, c') ->
- trans_code c' = lb' ->
- Mach.step (inv_trans_rao rao) ge (Mach.State stk f sp c rs m) t s' ->
- exists s2, cfi_step rao tge e (State (trans_stack stk) f sp (b::lb') rs m) t s2 /\ match_states s' s2.
+Lemma step_simu_cfi_step (i: Mach.instruction) (cfi: control_flow_inst) (c: Mach.code) (blc:code) stk f sp rs m (t:trace) (s':Mach.state) b:
+ trans_inst i = MB_cfi cfi ->
+ is_trans_code c blc ->
+ Mach.step (inv_trans_rao rao) ge (Mach.State stk f sp (i::c) rs m) t s' ->
+ exists s2, cfi_step rao tge cfi (State (trans_stack stk) f sp (b::blc) rs m) t s2 /\ match_states s' s2.
Proof.
- intros c e c' stk f sp rs m t s' b lb'.
- intros Hexit Htc Hstep.
- destruct c as [|ei c]; try (contradict Hexit; discriminate).
- destruct ei; (contradict Hexit; discriminate) || (
- inversion Hexit; subst; inversion Hstep; subst; simpl
- ).
- * eapply ex_intro; constructor 1; [ idtac | eapply match_states_trans_state ]; eauto.
- apply exec_MBcall with (f := (transf_function f0)); auto.
- rewrite find_function_ptr_same in H9; auto.
- * eapply ex_intro; constructor 1; [ idtac | eapply match_states_trans_state ]; eauto.
- apply exec_MBtailcall with (f := (transf_function f0)); auto.
- rewrite find_function_ptr_same in H9; auto.
- rewrite parent_sp_preserved in H11; subst; auto.
- rewrite parent_ra_preserved in H12; subst; auto.
- * eapply ex_intro; constructor 1; [ idtac | eapply match_states_trans_state ]; eauto.
- eapply exec_MBbuiltin; eauto.
- * exploit find_label_transcode_preserved; eauto. intros (h & X1 & X2).
+ destruct i; simpl in * |-;
+ (intro H; intro Htc;apply is_trans_code_inv in Htc;rewrite Htc;inversion_clear H;intro X; inversion_clear X).
+ * eapply ex_intro.
+ intuition auto.
+ eapply exec_MBcall;eauto.
+ rewrite <-H; exploit (find_function_ptr_same); eauto.
+ * eapply ex_intro.
+ intuition auto.
+ eapply exec_MBtailcall;eauto.
+ - rewrite <-H; exploit (find_function_ptr_same); eauto.
+ - simpl; rewrite <- parent_sp_preserved; auto.
+ - simpl; rewrite <- parent_ra_preserved; auto.
+ * eapply ex_intro.
+ intuition auto.
+ eapply exec_MBbuiltin ;eauto.
+ * exploit find_label_transcode_preserved; eauto.
+ intros (x & X1 & X2).
eapply ex_intro; constructor 1; [ idtac | eapply match_states_concat_trans_code ]; eauto.
- * exploit find_label_transcode_preserved; eauto. intros (h & X1 & X2).
+ * exploit find_label_transcode_preserved; eauto.
+ intros (x & X1 & X2).
eapply ex_intro; constructor 1; [ idtac | eapply match_states_concat_trans_code ]; eauto.
* eapply ex_intro; constructor 1; [ idtac | eapply match_states_trans_state ]; eauto.
eapply exec_MBcond_false; eauto.
@@ -481,42 +560,39 @@ Proof.
eapply ex_intro; constructor 1; [ idtac | eapply match_states_concat_trans_code ]; eauto.
* eapply ex_intro; constructor 1; [ idtac | eapply match_states_trans_state ]; eauto.
eapply exec_MBreturn; eauto.
- rewrite parent_sp_preserved in H8; subst; auto.
- rewrite parent_ra_preserved in H9; subst; auto.
+ rewrite parent_sp_preserved in H0; subst; auto.
+ rewrite parent_ra_preserved in H1; subst; auto.
Qed.
-
-
-Lemma step_simu_exit_step c e c' stk f sp rs m t s' b:
- to_bblock_exit c = (e, c') ->
- starN (Mach.step (inv_trans_rao rao)) (Genv.globalenv prog) (length_opt e) (Mach.State stk f sp c rs m) t s' ->
- exists s2, exit_step rao tge e (State (trans_stack stk) f sp (b::trans_code c') rs m) t s2 /\ match_states s' s2.
+Lemma step_simu_exit_step stk f sp rs m t s1 e c c' b blc:
+ is_exit e c c' -> is_trans_code c' blc ->
+ starN (Mach.step (inv_trans_rao rao)) (Genv.globalenv prog) (length_opt e) (Mach.State stk f sp c rs m) t s1 ->
+ exists s2, exit_step rao tge e (State (trans_stack stk) f sp (b::blc) rs m) t s2 /\ match_states s1 s2.
Proof.
- intros H1 H2; destruct e as [ e |]; inversion_clear H2.
- + (* Some *) inversion H0; clear H0; subst. autorewrite with trace_rewrite.
- exploit step_simu_cfi_step; eauto.
- intros (s2' & H2 & H3); eapply ex_intro; intuition eauto.
- + (* None *)
- destruct c as [ |i c]; simpl in H1; inversion H1.
- - eapply ex_intro; intuition eauto; try eapply match_states_trans_state.
- - remember to_cfi as o. destruct o; try discriminate.
- inversion_clear H1.
- eapply ex_intro; intuition eauto; try eapply match_states_trans_state.
+ destruct 1.
+ - (* None *)
+ intros H0 H1. inversion H1. exists (State (trans_stack stk) f sp blc rs m).
+ split; eauto.
+ apply is_trans_code_inv in H0.
+ rewrite H0.
+ apply match_states_trans_state.
+ - (* None *)
+ intros H0 H1. inversion H1. exists (State (trans_stack stk) f sp blc rs m).
+ split; eauto.
+ apply is_trans_code_inv in H0.
+ rewrite H0.
+ apply match_states_trans_state.
+ - (* Some *)
+ intros H0 H1.
+ inversion H1; subst.
+ exploit (step_simu_cfi_step); eauto.
+ intros [s2 [Hcfi1 Hcfi3]].
+ inversion H4. subst; simpl.
+ autorewrite with trace_rewrite.
+ exists s2.
+ split;eauto.
Qed.
-Lemma step_simu_header st f sp rs m s c: forall h c' t,
- (h, c') = to_bblock_header c ->
- starN (Mach.step (inv_trans_rao rao)) (Genv.globalenv prog) (length h) (Mach.State st f sp c rs m) t s -> s = Mach.State st f sp c' rs m /\ t = E0.
-Proof.
- induction c as [ | i c]; simpl; intros h c' t H.
- - inversion_clear H. simpl; intros H; inversion H; auto.
- - destruct i; try (injection H; clear H; intros H H2; subst; simpl; intros H; inversion H; subst; auto).
- remember (to_bblock_header c) as bhc. destruct bhc as [h0 c0].
- injection H; clear H; intros H H2; subst; simpl; intros H; inversion H; subst.
- inversion H1; clear H1; subst; auto. autorewrite with trace_rewrite.
- exploit IHc; eauto.
-Qed.
-
Lemma simu_end_block:
forall s1 t s1',
starN (Mach.step (inv_trans_rao rao)) ge (Datatypes.S (dist_end_block s1)) s1 t s1' ->
@@ -524,56 +600,41 @@ Lemma simu_end_block:
Proof.
destruct s1; simpl.
+ (* State *)
- (* c cannot be nil *)
- destruct c as [|i c]; simpl; try ( (* nil => absurd *)
- unfold dist_end_block_code; simpl;
- intros t s1' H; inversion_clear H;
- inversion_clear H0; fail
- ).
-
- intros t s1' H.
- remember (_::_) as c0. remember (trans_code c0) as tc0.
-
- (* tc0 cannot be nil *)
- destruct tc0; try
- ( exploit (trans_code_nonil c0); subst; auto; try discriminate; intro H0; contradict H0 ).
-
- assert (X: Datatypes.S (dist_end_block_code c0) = (size (fst (to_bblock c0)))).
+ remember (trans_code _) as tc.
+ rewrite <- is_trans_code_inv in Heqtc.
+ intros t s1 H.
+ destruct tc as [|b bl].
+ { (* nil => absurd *)
+ inversion Heqtc. subst.
+ unfold dist_end_block_code; simpl.
+ inversion_clear H;
+ inversion_clear H0.
+ }
+ assert (X: Datatypes.S (dist_end_block_code c) = (size b)).
{
- unfold dist_end_block_code. remember (size _) as siz.
- assert (siz <> 0%nat). rewrite Heqsiz; subst; apply to_bblock_nonil with (c0 := c) (i := i); auto.
+ unfold dist_end_block_code.
+ subst_is_trans_code Heqtc.
+ lapply (size_nonzero c b bl); auto.
omega.
}
-
- (* decomposition of starN in 3 parts: header + body + exit *)
rewrite X in H; unfold size in H.
- destruct (starN_split (Mach.semantics (inv_trans_rao rao) prog) _ _ _ _ H _ _ refl_equal) as [t3 [t4 [s1 [H0 [H3 H4]]]]].
+ (* decomposition of starN in 3 parts: header + body + exit *)
+ destruct (starN_split (Mach.semantics (inv_trans_rao rao) prog) _ _ _ _ H _ _ refl_equal) as (t3&t4&s1'&H0&H3&H4).
subst t; clear X H.
- destruct (starN_split (Mach.semantics (inv_trans_rao rao) prog) _ _ _ _ H0 _ _ refl_equal) as [t1 [t2 [s0 [H [H1 H2]]]]].
+ destruct (starN_split (Mach.semantics (inv_trans_rao rao) prog) _ _ _ _ H0 _ _ refl_equal) as (t1&t2&s1''&H&H1&H2).
subst t3; clear H0.
-
- unfold to_bblock in * |- *.
- (* naming parts of block "b" *)
- remember (to_bblock_header c0) as hd. destruct hd as [hb c1].
- remember (to_bblock_body c1) as bb. destruct bb as [bb c2].
- remember (to_bblock_exit c2) as exb. destruct exb as [exb c3].
- simpl in * |- *.
-
- exploit trans_code_step; eauto. intro EQ. destruct EQ as (EQH & EQB & EQE & EQTB0).
- subst hb bb exb.
-
- (* header opt step *)
+ exploit trans_code_decompose; eauto. clear Heqtc.
+ intros (c0&c1&c2&Hc0&Hc1&Hc2&Heqtc).
+ (* header steps *)
exploit step_simu_header; eauto.
- intros [X1 X2]; subst s0 t1.
- autorewrite with trace_rewrite.
+ clear H; intros [X1 X2]; subst.
(* body steps *)
exploit (star_step_simu_body_step); eauto.
- clear H1; intros [rs' [m' [H0 [H1 H2]]]].
- subst s1 t2. autorewrite with trace_rewrite.
+ clear H1; intros (rs'&m'&H0&H1&H2). subst.
+ autorewrite with trace_rewrite.
(* exit step *)
- subst tc0.
- exploit step_simu_exit_step; eauto. clear H3.
- intros (s2' & H3 & H4).
+ exploit step_simu_exit_step; eauto.
+ clear H3; intros (s2' & H3 & H4).
eapply ex_intro; intuition eauto.
eapply exec_bblock; eauto.
+ (* Callstate *)
@@ -599,13 +660,27 @@ Proof.
eapply exec_return.
Qed.
+
+Lemma cfi_dist_end_block i c:
+(exists cfi, trans_inst i = MB_cfi cfi) ->
+dist_end_block_code (i :: c) = 0.
+Proof.
+ unfold dist_end_block_code.
+ intro H. destruct H as [cfi H].
+ destruct i;simpl in H;try(congruence); (
+ remember (trans_code _) as bl;
+ rewrite <- is_trans_code_inv in Heqbl;
+ inversion Heqbl; subst; simpl in * |- *; try (congruence)).
+Qed.
+
Theorem transf_program_correct:
forward_simulation (Mach.semantics (inv_trans_rao rao) prog) (Machblock.semantics rao tprog).
Proof.
apply forward_simulation_block_trans with (dist_end_block := dist_end_block) (trans_state := trans_state).
(* simu_mid_block *)
- - intros s1 t s1' H1.
- destruct H1; simpl; omega || (intuition auto).
+ - intros s1 t s1' H1 H2.
+ destruct H1; simpl in * |- *; omega || (intuition auto);
+ destruct H2; eapply cfi_dist_end_block; simpl; eauto.
(* public_preserved *)
- apply senv_preserved.
(* match_initial_states *)
@@ -618,12 +693,114 @@ Proof.
(* match_final_states *)
- intros. simpl. destruct H. split with (r := r); auto.
(* final_states_end_block *)
- - intros. simpl in H0. inversion H0.
+ - intros. simpl in H0.
+ inversion H0.
inversion H; simpl; auto.
- (* the remaining instructions cannot lead to a Returnstate *)
- all: subst; discriminate.
+ all: try (subst; discriminate).
+ apply cfi_dist_end_block; exists MBreturn; eauto.
(* simu_end_block *)
- apply simu_end_block.
Qed.
End PRESERVATION.
+
+(** Auxiliary lemmas used to prove existence of a Mach return adress from a Machblock return address. *)
+
+
+
+Lemma is_trans_code_monotonic i c b l:
+ is_trans_code c (b::l) ->
+ exists l' b', is_trans_code (i::c) (l' ++ (b'::l)).
+Proof.
+ intro H; destruct c as [|i' c]. { inversion H. }
+ remember (trans_inst i) as ti.
+ destruct ti as [lbl|bi|cfi].
+ - (*i=lbl *) cutrewrite (i = Mlabel lbl). 2:{ destruct i; simpl in * |- *; try congruence. }
+ exists nil; simpl; eexists. eapply Tr_add_label; eauto.
+ - (*i=basic*)
+ destruct i'.
+ 10: {exists (add_to_new_bblock (MB_basic bi)::nil). exists b.
+ cutrewrite ((add_to_new_bblock (MB_basic bi) :: nil) ++ (b::l)=(add_to_new_bblock (MB_basic bi) :: (b::l)));eauto.
+ rewrite Heqti.
+ eapply Tr_end_block; eauto.
+ rewrite <-Heqti.
+ eapply End_basic. inversion H; try(simpl; congruence).
+ simpl in H5; congruence. }
+ all: try(exists nil; simpl; eexists; eapply Tr_add_basic; eauto; inversion H; try(eauto || congruence)).
+ - (*i=cfi*)
+ destruct i; try(simpl in Heqti; congruence).
+ all: exists (add_to_new_bblock (MB_cfi cfi)::nil); exists b;
+ cutrewrite ((add_to_new_bblock (MB_cfi cfi) :: nil) ++ (b::l)=(add_to_new_bblock (MB_cfi cfi) :: (b::l)));eauto;
+ rewrite Heqti;
+ eapply Tr_end_block; eauto;
+ rewrite <-Heqti;
+ eapply End_cfi; congruence.
+Qed.
+
+Lemma trans_code_monotonic i c b l:
+ (b::l) = trans_code c ->
+ exists l' b', trans_code (i::c) = (l' ++ (b'::l)).
+Proof.
+ intro H; rewrite <- is_trans_code_inv in H.
+ destruct (is_trans_code_monotonic i c b l H) as (l' & b' & H0).
+ subst_is_trans_code H0.
+ eauto.
+Qed.
+
+(* FIXME: these two lemma should go into [Coqlib.v] *)
+Lemma is_tail_app A (l1: list A): forall l2, is_tail l2 (l1 ++ l2).
+Proof.
+ induction l1; simpl; auto with coqlib.
+Qed.
+Hint Resolve is_tail_app: coqlib.
+
+Lemma is_tail_app_inv A (l1: list A): forall l2 l3, is_tail (l1 ++ l2) l3 -> is_tail l2 l3.
+Proof.
+ induction l1; simpl; auto with coqlib.
+ intros l2 l3 H; inversion H; eauto with coqlib.
+Qed.
+Hint Resolve is_tail_app_inv: coqlib.
+
+
+Lemma Mach_Machblock_tail sg ros c c1 c2: c1=(Mcall sg ros :: c) -> is_tail c1 c2 ->
+ exists b, is_tail (b :: trans_code c) (trans_code c2).
+Proof.
+ intros H; induction 1.
+ - intros; subst.
+ remember (trans_code (Mcall _ _::c)) as tc2.
+ rewrite <- is_trans_code_inv in Heqtc2.
+ inversion Heqtc2; simpl in * |- *; subst; try congruence.
+ subst_is_trans_code H1.
+ eapply ex_intro; eauto with coqlib.
+ - intros; exploit IHis_tail; eauto. clear IHis_tail.
+ intros (b & Hb). inversion Hb; clear Hb.
+ * exploit (trans_code_monotonic i c2); eauto.
+ intros (l' & b' & Hl'); rewrite Hl'.
+ exists b'; simpl; eauto with coqlib.
+ * exploit (trans_code_monotonic i c2); eauto.
+ intros (l' & b' & Hl'); rewrite Hl'.
+ simpl; eapply ex_intro.
+ eapply is_tail_trans; eauto with coqlib.
+Qed.
+
+Section Mach_Return_Address.
+
+Variable return_address_offset: function -> code -> ptrofs -> Prop.
+
+Hypothesis ra_exists: forall (b: bblock) (f: function) (c : list bblock),
+ is_tail (b :: c) (fn_code f) -> exists ra : ptrofs, return_address_offset f c ra.
+
+Definition Mach_return_address_offset (f: Mach.function) (c: Mach.code) (ofs: ptrofs) : Prop :=
+ return_address_offset (transf_function f) (trans_code c) ofs.
+
+Lemma Mach_return_address_exists:
+ forall f sg ros c, is_tail (Mcall sg ros :: c) f.(Mach.fn_code) ->
+ exists ra, Mach_return_address_offset f c ra.
+Proof.
+ intros.
+ exploit Mach_Machblock_tail; eauto.
+ destruct 1.
+ eapply ra_exists; eauto.
+Qed.
+
+End Mach_Return_Address. \ No newline at end of file
diff --git a/mppa_k1c/lib/Asmblockgenproof0.v b/mppa_k1c/lib/Asmblockgenproof0.v
index e0780b9d..89d41017 100644
--- a/mppa_k1c/lib/Asmblockgenproof0.v
+++ b/mppa_k1c/lib/Asmblockgenproof0.v
@@ -15,6 +15,7 @@ Require Import Asmblock.
Require Import Asmblockgen.
Require Import Conventions1.
Require Import Axioms.
+Require Import Machblockgenproof. (* FIXME: only use to import [is_tail_app] and [is_tail_app_inv] *)
Module MB:=Machblock.
Module AB:=Asmvliw.
@@ -577,21 +578,6 @@ Definition return_address_offset (f: MB.function) (c: MB.code) (ofs: ptrofs) : P
transl_blocks f c false = OK tc ->
code_tail (Ptrofs.unsigned ofs) (fn_blocks tf) tc.
-(* NB: these two lemma should go into [Coqlib.v] *)
-Lemma is_tail_app A (l1: list A): forall l2, is_tail l2 (l1 ++ l2).
-Proof.
- induction l1; simpl; auto with coqlib.
-Qed.
-Hint Resolve is_tail_app: coqlib.
-
-Lemma is_tail_app_inv A (l1: list A): forall l2 l3, is_tail (l1 ++ l2) l3 -> is_tail l2 l3.
-Proof.
- induction l1; simpl; auto with coqlib.
- intros l2 l3 H; inversion H; eauto with coqlib.
-Qed.
-Hint Resolve is_tail_app_inv: coqlib.
-
-
Lemma transl_blocks_tail:
forall f c1 c2, is_tail c1 c2 ->
forall tc2 ep2, transl_blocks f c2 ep2 = OK tc2 ->
diff --git a/mppa_k1c/lib/ForwardSimulationBlock.v b/mppa_k1c/lib/ForwardSimulationBlock.v
index dc8beb29..39dd2234 100644
--- a/mppa_k1c/lib/ForwardSimulationBlock.v
+++ b/mppa_k1c/lib/ForwardSimulationBlock.v
@@ -271,6 +271,7 @@ However, the Machblock state after a goto remains "equivalent" to the trans_stat
*)
+
Section ForwardSimuBlock_TRANS.
Variable L1 L2: semantics.
@@ -320,3 +321,53 @@ Proof.
Qed.
End ForwardSimuBlock_TRANS.
+
+
+(* another version with a relation [trans_state_R] instead of a function [trans_state] *)
+Section ForwardSimuBlock_TRANS_R.
+
+Variable L1 L2: semantics.
+
+Variable trans_state_R: state L1 -> state L2 -> Prop.
+
+Definition match_states_R s1 s2: Prop :=
+ exists s2', trans_state_R s1 s2' /\ equiv_on_next_step _ (exists t s1', Step L1 s1 t s1') (exists r, final_state L1 s1 r) s2 s2'.
+
+Lemma match_states_trans_state_R s1 s2: trans_state_R s1 s2 -> match_states_R s1 s2.
+Proof.
+ unfold match_states, equiv_on_next_step. firstorder.
+Qed.
+
+Variable dist_end_block: state L1 -> nat.
+
+Hypothesis simu_mid_block:
+ forall s1 t s1', Step L1 s1 t s1' -> (dist_end_block s1)<>0 -> t = E0 /\ dist_end_block s1=S (dist_end_block s1').
+
+Hypothesis public_preserved:
+ forall id, Senv.public_symbol (symbolenv L2) id = Senv.public_symbol (symbolenv L1) id.
+
+Hypothesis match_initial_states:
+ forall s1, initial_state L1 s1 -> exists s2, match_states_R s1 s2 /\ initial_state L2 s2.
+
+Hypothesis match_final_states:
+ forall s1 s2 r, final_state L1 s1 r -> trans_state_R s1 s2 -> final_state L2 s2 r.
+
+Hypothesis final_states_end_block:
+ forall s1 t s1' r, Step L1 s1 t s1' -> final_state L1 s1' r -> dist_end_block s1 = 0.
+
+Hypothesis simu_end_block:
+ forall s1 t s1' s2, starN (step L1) (globalenv L1) (S (dist_end_block s1)) s1 t s1' -> trans_state_R s1 s2 -> exists s2', Step L2 s2 t s2' /\ match_states_R s1' s2'.
+
+Lemma forward_simulation_block_trans_R: forward_simulation L1 L2.
+Proof.
+ eapply forward_simulation_block_rel with (dist_end_block:=dist_end_block) (match_states:=match_states_R); try tauto.
+ + (* final_states *) intros s1 s2 r H1 (s2' & H2 & H3 & H4). rewrite H4; eauto.
+ + (* simu_end_block *)
+ intros s1 t s1' s2 H1 (s2' & H2 & H2a & H2b). exploit simu_end_block; eauto.
+ intros (x & Hx & (y & H3 & H4 & H5)). repeat (econstructor; eauto).
+ rewrite H2a; eauto.
+ inversion_clear H1. eauto.
+Qed.
+
+End ForwardSimuBlock_TRANS_R.
+
diff --git a/test/monniaux/gengraphs.py b/test/monniaux/gengraphs.py
index 2455c285..fd8098b7 100755
--- a/test/monniaux/gengraphs.py
+++ b/test/monniaux/gengraphs.py
@@ -1,9 +1,10 @@
#!/usr/bin/python3.6
-import numpy as np
-import matplotlib.pyplot as plt
-import pandas as pd
+import numpy as np # type: ignore
+import matplotlib.pyplot as plt # type: ignore
+import pandas as pd # type: ignore
import sys
+from typing import *
##
# Reading data
@@ -28,7 +29,7 @@ colors = ["forestgreen", "darkorange", "cornflowerblue", "darkorchid", "darksalm
# Generating PDF
##
-def extract_envs(keys):
+def extract_envs(keys: List[str]) -> List[str]:
envs = []
for key in keys:
words = key.split()[:-1]
@@ -36,11 +37,11 @@ def extract_envs(keys):
return envs
-def subdivide_interv(inf, sup, n):
+def subdivide_interv(inf: float, sup: float, n: int) -> List[float]:
return [inf + k*(sup-inf)/n for k in range(n)]
-def generate_file(f, cols):
+def generate_file(f: str, cols: List[str]) -> None:
ind = np.arange(len(df[cols[0]]))
width = 0.35 # the width of the bars
@@ -63,7 +64,7 @@ def generate_file(f, cols):
ax.set_xticklabels(benches)
ax.legend()
- def autolabel(rects, xpos='center'):
+ def autolabel(rects: List[Any], xpos='center') -> None:
"""
Attach a text label above each bar in *rects*, displaying its height.
diff --git a/test/monniaux/genmake.py b/test/monniaux/genmake.py
index ad460b14..d04ba70c 100755
--- a/test/monniaux/genmake.py
+++ b/test/monniaux/genmake.py
@@ -8,6 +8,7 @@ See the source for more info.
"""
from collections import namedtuple
+from typing import *
import sys
import yaml
@@ -36,7 +37,7 @@ if len(sys.argv) != 2:
yaml_file = sys.argv[1]
with open(yaml_file, "r") as f:
- settings = yaml.load(f.read(), Loader=yaml.FullLoader)
+ settings = yaml.load(f.read(), Loader=yaml.SafeLoader)
basename = settings["target"]
objdeps = settings["objdeps"] if "objdeps" in settings else []
@@ -56,22 +57,22 @@ for objdep in objdeps:
# Printing the rules
##
-def make_product(env, optim):
+def make_product(env: Env, optim: Optim) -> str:
return basename + "." + env.compiler.short + (("." + optim.short) if optim.short != "" else "") + "." + env.target
-def make_obj(name, env, compiler_short):
+def make_obj(name: str, env: Env, compiler_short: str) -> str:
return name + "." + compiler_short + "." + env.target + ".o"
-def make_clock(env, optim):
+def make_clock(env: Env, optim: Optim) -> str:
return "clock.gcc." + env.target
-def make_sources(env, optim):
+def make_sources(env: Env, optim: Optim) -> str:
if sources:
return "$(src:.c=." + env.compiler.short + (("." + optim.short) if optim.short != "" else "") + "." + env.target + ".o)"
else:
return "{product}.o".format(product = make_product(env, optim))
-def print_rule(env, optim):
+def print_rule(env: Env, optim: Optim) -> None:
print("{product}: {sources} ../{clock}.o "
.format(product = make_product(env, optim),
sources = make_sources(env, optim), clock = make_clock(env, optim))
@@ -79,12 +80,12 @@ def print_rule(env, optim):
print(" {compiler} {flags} $+ -o $@"
.format(compiler = env.compiler.full, flags = optim.full))
-def make_env_list(envs):
+def make_env_list(envs: List[Env]) -> str:
return ",".join([(env.compiler.short + ((" " + optim.short) if optim.short != "" else "") + " " + env.target)
for env in environments
for optim in env.optimizations])
-def print_measure_rule(environments, measures):
+def print_measure_rule(environments: List[Env], measures: List[Union[List[str], str]]) -> None:
print("measures.csv: $(PRODUCTS_OUT)")
print(' echo "benches, {}" > $@'.format(make_env_list(environments)))
for measure in measures: