diff options
author | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2007-10-27 10:23:16 +0000 |
---|---|---|
committer | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2007-10-27 10:23:16 +0000 |
commit | e882493e2c4b91024b42f0603ca6869e95695e85 (patch) | |
tree | 1d90dda6b56b541310d8b8703152fdcd49e8a7fa /backend | |
parent | 7f6ac3209e7fb7d822780c7e990fb604b11a6409 (diff) |
Linearize: utilisation d'une heuristique externe d'enumeration des noeuds du CFG
git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@437 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
Diffstat (limited to 'backend')
-rw-r--r-- | backend/Linearize.v | 107 | ||||
-rw-r--r-- | backend/Linearizeproof.v | 280 | ||||
-rw-r--r-- | backend/Linearizetyping.v | 28 |
3 files changed, 257 insertions, 158 deletions
diff --git a/backend/Linearize.v b/backend/Linearize.v index 305473b..57919b8 100644 --- a/backend/Linearize.v +++ b/backend/Linearize.v @@ -3,9 +3,13 @@ Require Import Coqlib. Require Import Maps. +Require Import Ordered. +Require Import FSets. +Require FSetAVL. Require Import AST. Require Import Values. Require Import Globalenvs. +Require Import Errors. Require Import Op. Require Import Locations. Require Import LTL. @@ -13,10 +17,12 @@ Require Import LTLin. Require Import Kildall. Require Import Lattice. -(** To translate from LTL to LTLin, we must lay out the basic blocks +Open Scope error_monad_scope. + +(** To translate from LTL to LTLin, we must lay out the nodes of the LTL control-flow graph in some linear order, and insert explicit branches and conditional branches to make sure that - each basic block jumps to its successors as prescribed by the + each node jumps to its successors as prescribed by the LTL control-flow graph. However, branches are not necessary if the fall-through behaviour of LTLin instructions already implements the desired flow of control. For instance, @@ -39,29 +45,28 @@ Require Import Lattice. L2: ... >> The main challenge in code linearization is therefore to pick a - ``good'' order for the basic blocks that exploits well the + ``good'' order for the nodes that exploits well the fall-through behavior. Many clever trace picking heuristics have been developed for this purpose. In this file, we present linearization in a way that clearly separates the heuristic part (choosing an order for the basic blocks) from the actual code transformation parts. We proceed in three passes: -- Choosing an order for the basic blocks. This returns an enumeration - of CFG nodes stating that the basic blocks must be laid out in - the order shown in the list. -- Generate LTLin code where each basic block branches explicitly - to its successors, except if one of these successors is the - immediately following instruction. +- Choosing an order for the nodes. This returns an enumeration of CFG + nodes stating that they must be laid out in the order shown in the + list. +- Generate LTLin code where each node branches explicitly to its + successors, except if one of these successors is the immediately + following instruction. The beauty of this approach is that correct code is generated under surprisingly weak hypotheses on the enumeration of CFG nodes: it suffices that every reachable instruction occurs - exactly once in the enumeration. While the enumeration heuristic we use - is quite trivial, it is easy to implement more sophisticated - trace picking heuristics: as long as they satisfy the property above, - we do not need to re-do the proof of semantic preservation. - The enumeration could even be performed by external, untrusted - Caml code, then verified (for the property above) by certified Coq code. + exactly once in the enumeration. We therefore follow an approach + based on validation a posteriori: a piece of untrusted Caml code + implements the node enumeration heuristics, and the resulting + enumeration is checked for correctness by Coq functions that are + proved to be sound. *) (** * Determination of the order of basic blocks *) @@ -88,21 +93,44 @@ Definition reachable (f: LTL.function) : PMap.t bool := | Some rs => rs end. -(** We then enumerate the nodes of reachable basic blocks. The heuristic - we take is trivial: nodes are enumerated in decreasing numerical - order. Remember that CFG nodes are positive integers, and that - the [RTLgen] pass allocated fresh nodes 1, 2, 3, ..., but generated - instructions in roughly reverse control-flow order: often, - a basic block at label [n] has [n-1] as its only successor. - Therefore, by enumerating reachable nodes in decreasing order, - we recover a reasonable layout of basic blocks that globally respects - the structure of the original Cminor code. *) - -Definition enumerate (f: LTL.function) : list node := +(** We then enumerate the nodes of reachable instructions. + This task is performed by external, untrusted Caml code. *) + +Parameter enumerate_aux: LTL.function -> PMap.t bool -> list node. + +(** Now comes the validation of an enumeration a posteriori. *) + +Module Nodeset := FSetAVL.Make(OrderedPositive). + +(** Build a Nodeset.t from a list of nodes, checking that the list + contains no duplicates. *) + +Fixpoint nodeset_of_list (l: list node) (s: Nodeset.t) + {struct l}: res Nodeset.t := + match l with + | nil => OK s + | hd :: tl => + if Nodeset.mem hd s + then Error (msg "Linearize: duplicates in enumeration") + else nodeset_of_list tl (Nodeset.add hd s) + end. + +Definition check_reachable_aux + (reach: PMap.t bool) (s: Nodeset.t) + (ok: bool) (pc: node) (i: LTL.instruction) : bool := + if reach!!pc then ok && Nodeset.mem pc s else ok. + +Definition check_reachable + (f: LTL.function) (reach: PMap.t bool) (s: Nodeset.t) : bool := + PTree.fold (check_reachable_aux reach s) f.(LTL.fn_code) true. + +Definition enumerate (f: LTL.function) : res (list node) := let reach := reachable f in - positive_rec (list node) nil - (fun pc nodes => if reach!!pc then pc :: nodes else nodes) - f.(fn_nextpc). + let enum := enumerate_aux f reach in + do s <- nodeset_of_list enum Nodeset.empty; + if check_reachable f reach s + then OK enum + else Error (msg "Linearize: wrong enumeration"). (** * Translation from LTL to LTLin *) @@ -172,15 +200,16 @@ Fixpoint linearize_body (f: LTL.function) (enum: list node) (** * Entry points for code linearization *) -Definition transf_function (f: LTL.function) : LTLin.function := - mkfunction - (LTL.fn_sig f) - (LTL.fn_params f) - (LTL.fn_stacksize f) - (add_branch (LTL.fn_entrypoint f) (linearize_body f (enumerate f))). +Definition transf_function (f: LTL.function) : res LTLin.function := + do enum <- enumerate f; + OK (mkfunction + (LTL.fn_sig f) + (LTL.fn_params f) + (LTL.fn_stacksize f) + (add_branch (LTL.fn_entrypoint f) (linearize_body f enum))). -Definition transf_fundef (f: LTL.fundef) : LTLin.fundef := - AST.transf_fundef transf_function f. +Definition transf_fundef (f: LTL.fundef) : res LTLin.fundef := + AST.transf_partial_fundef transf_function f. -Definition transf_program (p: LTL.program) : LTLin.program := - transform_program transf_fundef p. +Definition transf_program (p: LTL.program) : res LTLin.program := + transform_partial_program transf_fundef p. diff --git a/backend/Linearizeproof.v b/backend/Linearizeproof.v index c729908..a625ba7 100644 --- a/backend/Linearizeproof.v +++ b/backend/Linearizeproof.v @@ -2,12 +2,15 @@ Require Import Coqlib. Require Import Maps. +Require Import Ordered. +Require Import FSets. Require Import AST. Require Import Integers. Require Import Values. Require Import Mem. Require Import Events. Require Import Globalenvs. +Require Import Errors. Require Import Smallstep. Require Import Op. Require Import Locations. @@ -17,10 +20,14 @@ Require Import LTLin. Require Import Linearize. Require Import Lattice. +Module NodesetFacts := FSetFacts.Facts(Nodeset). + Section LINEARIZATION. Variable prog: LTL.program. -Let tprog := transf_program prog. +Variable tprog: LTLin.program. + +Hypothesis TRANSF: transf_program prog = OK tprog. Let ge := Genv.globalenv prog. Let tge := Genv.globalenv tprog. @@ -28,33 +35,40 @@ Let tge := Genv.globalenv tprog. Lemma functions_translated: forall v f, Genv.find_funct ge v = Some f -> - Genv.find_funct tge v = Some (transf_fundef f). -Proof (@Genv.find_funct_transf _ _ _ transf_fundef prog). + exists tf, + Genv.find_funct tge v = Some tf /\ transf_fundef f = OK tf. +Proof (Genv.find_funct_transf_partial transf_fundef TRANSF). Lemma function_ptr_translated: forall v f, Genv.find_funct_ptr ge v = Some f -> - Genv.find_funct_ptr tge v = Some (transf_fundef f). -Proof (@Genv.find_funct_ptr_transf _ _ _ transf_fundef prog). + exists tf, + Genv.find_funct_ptr tge v = Some tf /\ transf_fundef f = OK tf. +Proof (Genv.find_funct_ptr_transf_partial transf_fundef TRANSF). Lemma symbols_preserved: forall id, Genv.find_symbol tge id = Genv.find_symbol ge id. -Proof (@Genv.find_symbol_transf _ _ _ transf_fundef prog). +Proof (Genv.find_symbol_transf_partial transf_fundef _ TRANSF). Lemma sig_preserved: - forall f, funsig (transf_fundef f) = LTL.funsig f. + forall f tf, + transf_fundef f = OK tf -> + LTLin.funsig tf = LTL.funsig f. Proof. - destruct f; reflexivity. + unfold transf_fundef, transf_partial_fundef; intros. + destruct f. monadInv H. monadInv EQ. reflexivity. + inv H. reflexivity. Qed. Lemma find_function_translated: forall ros ls f, LTL.find_function ge ros ls = Some f -> - find_function tge ros ls = Some (transf_fundef f). + exists tf, + find_function tge ros ls = Some tf /\ transf_fundef f = OK tf. Proof. - intros until f. destruct ros; simpl. - intro. apply functions_translated; auto. + unfold LTL.find_function; intros; destruct ros; simpl. + apply functions_translated; auto. rewrite symbols_preserved. destruct (Genv.find_symbol ge i). apply function_ptr_translated; auto. congruence. @@ -102,54 +116,84 @@ Qed. - All nodes for reachable basic blocks must be in the list. - The list is without repetition (so that no code duplication occurs). -We prove that our [enumerate] function satisfies all three. *) +We prove that our [enumerate] function satisfies both conditions. *) + + +Lemma nodeset_of_list_correct: + forall l s s', + nodeset_of_list l s = OK s' -> + list_norepet l + /\ (forall pc, Nodeset.In pc s' <-> Nodeset.In pc s \/ In pc l) + /\ (forall pc, In pc l -> ~Nodeset.In pc s). +Proof. + induction l; simpl; intros. + inv H. split. constructor. split. intro; tauto. intros; tauto. + generalize H; clear H; caseEq (Nodeset.mem a s); intros. + inv H0. + exploit IHl; eauto. intros [A [B C]]. + split. constructor; auto. red; intro. elim (C a H1). apply Nodeset.add_1. hnf. auto. + split. intros. rewrite B. rewrite NodesetFacts.add_iff. + unfold Nodeset.E.eq. unfold OrderedPositive.eq. tauto. + intros. destruct H1. subst pc. rewrite NodesetFacts.not_mem_iff. auto. + generalize (C pc H1). rewrite NodesetFacts.add_iff. tauto. +Qed. + +Lemma check_reachable_correct: + forall f reach s pc i, + check_reachable f reach s = true -> + f.(LTL.fn_code)!pc = Some i -> + reach!!pc = true -> + Nodeset.In pc s. +Proof. + intros f reach s. + assert (forall l ok, + List.fold_left (fun a p => check_reachable_aux reach s a (fst p) (snd p)) l ok = true -> + ok = true /\ + (forall pc i, + In (pc, i) l -> + reach!!pc = true -> + Nodeset.In pc s)). + induction l; simpl; intros. + split. auto. intros. destruct H0. + destruct a as [pc1 i1]. simpl in H. + exploit IHl; eauto. intros [A B]. + unfold check_reachable_aux in A. + split. destruct (reach!!pc1). elim (andb_prop _ _ A). auto. auto. + intros. destruct H0. inv H0. rewrite H1 in A. destruct (andb_prop _ _ A). + apply Nodeset.mem_2; auto. + eauto. + + intros pc i. unfold check_reachable. rewrite PTree.fold_spec. intros. + exploit H; eauto. intros [A B]. eapply B; eauto. + apply PTree.elements_correct. eauto. +Qed. Lemma enumerate_complete: - forall f pc i, + forall f enum pc i, + enumerate f = OK enum -> f.(LTL.fn_code)!pc = Some i -> (reachable f)!!pc = true -> - In pc (enumerate f). + In pc enum. Proof. - intros. - assert (forall p, - Plt p f.(fn_nextpc) -> - (reachable f)!!p = true -> - In p (enumerate f)). - unfold enumerate. pattern (fn_nextpc f). - apply positive_Peano_ind. - intros. compute in H1. destruct p; discriminate. - intros. rewrite positive_rec_succ. elim (Plt_succ_inv _ _ H2); intro. - case (reachable f)!!x. apply in_cons. auto. auto. - subst x. rewrite H3. apply in_eq. - elim (LTL.fn_code_wf f pc); intro. auto. congruence. -Qed. + intros until i. unfold enumerate. + set (reach := reachable f). + intros. monadInv H. + generalize EQ0; clear EQ0. caseEq (check_reachable f reach x); intros; inv EQ0. + exploit check_reachable_correct; eauto. intro. + exploit nodeset_of_list_correct; eauto. intros [A [B C]]. + rewrite B in H2. destruct H2. elim (Nodeset.empty_1 pc H2). auto. +Qed. Lemma enumerate_norepet: - forall f, list_norepet (enumerate f). -Proof. - intro. - unfold enumerate. pattern (fn_nextpc f). - apply positive_Peano_ind. - rewrite positive_rec_base. constructor. - intros. rewrite positive_rec_succ. - case (reachable f)!!x. - constructor. - assert (forall y, - In y (positive_rec - (list node) nil - (fun (pc : positive) (nodes : list node) => - if (reachable f) !! pc then pc :: nodes else nodes) x) -> - Plt y x). - pattern x. apply positive_Peano_ind. - rewrite positive_rec_base. intros. elim H0. - intros until y. rewrite positive_rec_succ. - case (reachable f)!!x0. - simpl. intros [A|B]. - subst x0. apply Plt_succ. - apply Plt_trans_succ. auto. - intro. apply Plt_trans_succ. auto. - red; intro. generalize (H0 x H1). exact (Plt_strict x). auto. - auto. + forall f enum, + enumerate f = OK enum -> + list_norepet enum. +Proof. + intros until enum. unfold enumerate. + set (reach := reachable f). + intros. monadInv H. + generalize EQ0; clear EQ0. caseEq (check_reachable f reach x); intros; inv EQ0. + exploit nodeset_of_list_correct; eauto. intros [A [B C]]. auto. Qed. (** * Properties related to labels *) @@ -243,23 +287,34 @@ Proof. auto. Qed. +(* +Lemma transf_function_inv: + forall f tf, transf_function f = OK tf -> + exists enum, enumerate f = OK enum /\ fn_code tf = add_branch (LTL.fn_entrypoint f) (linearize_body f enum). +Proof. + intros. monadInv H. exists x; auto. +Qed. +*) + Lemma find_label_lin: - forall f pc b, + forall f tf pc b, + transf_function f = OK tf -> f.(LTL.fn_code)!pc = Some b -> (reachable f)!!pc = true -> exists k, - find_label pc (fn_code (transf_function f)) = Some (linearize_instr b k). + find_label pc (fn_code tf) = Some (linearize_instr b k). Proof. - intros. unfold transf_function; simpl. + intros. monadInv H. simpl. rewrite find_label_add_branch. apply find_label_lin_rec. eapply enumerate_complete; eauto. auto. Qed. Lemma find_label_lin_inv: - forall f pc b k , + forall f tf pc b k, + transf_function f = OK tf -> f.(LTL.fn_code)!pc = Some b -> (reachable f)!!pc = true -> - find_label pc (fn_code (transf_function f)) = Some k -> + find_label pc (fn_code tf) = Some k -> exists k', k = linearize_instr b k'. Proof. intros. exploit find_label_lin; eauto. intros [k' FIND]. @@ -267,13 +322,14 @@ Proof. Qed. Lemma find_label_lin_succ: - forall f s, + forall f tf s, + transf_function f = OK tf -> valid_successor f s -> (reachable f)!!s = true -> exists k, - find_label s (fn_code (transf_function f)) = Some k. + find_label s (fn_code tf) = Some k. Proof. - intros. destruct H as [i AT]. + intros. destruct H0 as [i AT]. exploit find_label_lin; eauto. intros [k FIND]. exists (linearize_instr i k); auto. Qed. @@ -344,12 +400,13 @@ Proof. Qed. Lemma unique_labels_transf_function: - forall f, - unique_labels (fn_code (transf_function f)). + forall f tf, + transf_function f = OK tf -> + unique_labels (fn_code tf). Proof. - intros. unfold transf_function; simpl. + intros. monadInv H. simpl. apply unique_labels_add_branch. - apply unique_labels_lin_rec. apply enumerate_norepet. + apply unique_labels_lin_rec. eapply enumerate_norepet; eauto. Qed. (** Correctness of [add_branch]. *) @@ -373,16 +430,17 @@ Proof. Qed. Lemma add_branch_correct: - forall lbl c k s f sp ls m, - is_tail k (transf_function f).(fn_code) -> - find_label lbl (transf_function f).(fn_code) = Some c -> - plus step tge (State s (transf_function f) sp (add_branch lbl k) ls m) - E0 (State s (transf_function f) sp c ls m). + forall lbl c k s f tf sp ls m, + transf_function f = OK tf -> + is_tail k tf.(fn_code) -> + find_label lbl tf.(fn_code) = Some c -> + plus step tge (State s tf sp (add_branch lbl k) ls m) + E0 (State s tf sp c ls m). Proof. intros. unfold add_branch. caseEq (starts_with lbl k); intro SW. eapply starts_with_correct; eauto. - apply unique_labels_transf_function. + eapply unique_labels_transf_function; eauto. apply plus_one. apply exec_Lgoto. auto. Qed. @@ -407,30 +465,33 @@ Qed. Inductive match_stackframes: LTL.stackframe -> LTLin.stackframe -> Prop := | match_stackframe_intro: - forall res f sp pc ls c, + forall res f sp pc ls tf c, + transf_function f = OK tf -> (reachable f)!!pc = true -> valid_successor f pc -> - is_tail c (fn_code (transf_function f)) -> + is_tail c (fn_code tf) -> wt_function f -> match_stackframes (LTL.Stackframe res f sp ls pc) - (LTLin.Stackframe res (transf_function f) sp ls (add_branch pc c)). + (LTLin.Stackframe res tf sp ls (add_branch pc c)). Inductive match_states: LTL.state -> LTLin.state -> Prop := | match_states_intro: - forall s f sp pc ls m ts c + forall s f sp pc ls m tf ts c (STACKS: list_forall2 match_stackframes s ts) + (TRF: transf_function f = OK tf) (REACH: (reachable f)!!pc = true) - (AT: find_label pc (fn_code (transf_function f)) = Some c) + (AT: find_label pc (fn_code tf) = Some c) (WTF: wt_function f), match_states (LTL.State s f sp pc ls m) - (LTLin.State ts (transf_function f) sp c ls m) + (LTLin.State ts tf sp c ls m) | match_states_call: - forall s f ls m ts, + forall s f ls m tf ts, list_forall2 match_stackframes s ts -> + transf_fundef f = OK tf -> wt_fundef f -> match_states (LTL.Callstate s f ls m) - (LTLin.Callstate ts (transf_fundef f) ls m) + (LTLin.Callstate ts tf ls m) | match_states_return: forall s sig ls m ts, list_forall2 match_stackframes s ts -> @@ -455,7 +516,7 @@ Proof. induction 1; intros; try (inv MS); try (generalize (wt_instrs _ WTF _ _ H); intro WTI). (* Lnop *) - destruct (find_label_lin_inv _ _ _ _ H REACH AT) as [c' EQ]. + destruct (find_label_lin_inv _ _ _ _ _ TRF H REACH AT) as [c' EQ]. simpl in EQ. subst c. assert (REACH': (reachable f)!!pc' = true). eapply reachable_successors; eauto. @@ -466,7 +527,7 @@ Proof. eapply is_tail_add_branch. eapply is_tail_find_label. eauto. econstructor; eauto. (* Lop *) - destruct (find_label_lin_inv _ _ _ _ H REACH AT) as [c' EQ]. + destruct (find_label_lin_inv _ _ _ _ _ TRF H REACH AT) as [c' EQ]. simpl in EQ. subst c. assert (REACH': (reachable f)!!pc' = true). eapply reachable_successors; eauto. @@ -482,7 +543,7 @@ Proof. traceEq. econstructor; eauto. (* Lload *) - destruct (find_label_lin_inv _ _ _ _ H REACH AT) as [c' EQ]. + destruct (find_label_lin_inv _ _ _ _ _ TRF H REACH AT) as [c' EQ]. simpl in EQ. subst c. assert (REACH': (reachable f)!!pc' = true). eapply reachable_successors; eauto. @@ -498,7 +559,7 @@ Proof. traceEq. econstructor; eauto. (* Lstore *) - destruct (find_label_lin_inv _ _ _ _ H REACH AT) as [c' EQ]. + destruct (find_label_lin_inv _ _ _ _ _ TRF H REACH AT) as [c' EQ]. simpl in EQ. subst c. assert (REACH': (reachable f)!!pc' = true). eapply reachable_successors; eauto. @@ -516,16 +577,16 @@ Proof. (* Lcall *) unfold rs1 in *. inv MS. fold rs1. generalize (wt_instrs _ WTF _ _ H); intro WTI. - destruct (find_label_lin_inv _ _ _ _ H REACH AT) as [c' EQ]. + destruct (find_label_lin_inv _ _ _ _ _ TRF H REACH AT) as [c' EQ]. simpl in EQ. subst c. assert (REACH': (reachable f)!!pc' = true). eapply reachable_successors; eauto. unfold successors; rewrite H; auto with coqlib. assert (VALID: valid_successor f pc'). inv WTI; auto. + exploit find_function_translated; eauto. intros [tf' [A B]]. econstructor; split. - apply plus_one. eapply exec_Lcall with (f' := transf_fundef f'); eauto. - apply find_function_translated; auto. - symmetry; apply sig_preserved. + apply plus_one. eapply exec_Lcall with (f' := tf'); eauto. + symmetry; apply sig_preserved; auto. econstructor; eauto. constructor; auto. econstructor; eauto. eapply is_tail_add_branch. eapply is_tail_cons_left. @@ -537,12 +598,12 @@ Proof. (* Ltailcall *) unfold rs2, rs1 in *. inv MS. fold rs1; fold rs2. - destruct (find_label_lin_inv _ _ _ _ H REACH AT) as [c' EQ]. + destruct (find_label_lin_inv _ _ _ _ _ TRF H REACH AT) as [c' EQ]. simpl in EQ. subst c. + exploit find_function_translated; eauto. intros [tf' [A B]]. econstructor; split. - apply plus_one. eapply exec_Ltailcall with (f' := transf_fundef f'); eauto. - apply find_function_translated; auto. - symmetry; apply sig_preserved. + apply plus_one. eapply exec_Ltailcall with (f' := tf'); eauto. + symmetry; apply sig_preserved; auto. rewrite (parent_locset_match _ _ STACKS). econstructor; eauto. destruct ros; simpl in H0. @@ -551,7 +612,7 @@ Proof. eapply Genv.find_funct_ptr_prop; eauto. (* Lalloc *) - destruct (find_label_lin_inv _ _ _ _ H REACH AT) as [c' EQ]. + destruct (find_label_lin_inv _ _ _ _ _ TRF H REACH AT) as [c' EQ]. simpl in EQ. subst c. assert (REACH': (reachable f)!!pc' = true). eapply reachable_successors; eauto. @@ -565,8 +626,9 @@ Proof. eapply is_tail_find_label. eauto. traceEq. econstructor; eauto. + (* Lcond true *) - destruct (find_label_lin_inv _ _ _ _ H REACH AT) as [c' EQ]. + destruct (find_label_lin_inv _ _ _ _ _ TRF H REACH AT) as [c' EQ]. simpl in EQ. subst c. assert (REACH': (reachable f)!!ifso = true). eapply reachable_successors; eauto. @@ -585,8 +647,9 @@ Proof. econstructor; split. apply plus_one. eapply exec_Lcond_true; eauto. econstructor; eauto. + (* Lcond false *) - destruct (find_label_lin_inv _ _ _ _ H REACH AT) as [c' EQ]. + destruct (find_label_lin_inv _ _ _ _ _ TRF H REACH AT) as [c' EQ]. simpl in EQ. subst c. assert (REACH': (reachable f)!!ifnot = true). eapply reachable_successors; eauto. @@ -605,29 +668,33 @@ Proof. eapply is_tail_find_label. eauto. traceEq. econstructor; eauto. + (* Lreturn *) - destruct (find_label_lin_inv _ _ _ _ H REACH AT) as [c' EQ]. + destruct (find_label_lin_inv _ _ _ _ _ TRF H REACH AT) as [c' EQ]. simpl in EQ. subst c. econstructor; split. apply plus_one. eapply exec_Lreturn; eauto. rewrite (parent_locset_match _ _ STACKS). - econstructor; eauto. + monadInv TRF. simpl. econstructor; eauto. + (* internal function *) assert (REACH: (reachable f)!!(LTL.fn_entrypoint f) = true). apply reachable_entrypoint. - inv H6. + inv H7. monadInv H6. exploit find_label_lin_succ; eauto. inv H1; auto. intros [c'' AT']. - simpl. econstructor; split. + generalize EQ; intro. monadInv EQ0. econstructor; simpl; split. eapply plus_left'. eapply exec_function_internal; eauto. - simpl. eapply add_branch_correct. + simpl. eapply add_branch_correct. eauto. simpl. eapply is_tail_add_branch. constructor. eauto. traceEq. econstructor; eauto. + (* external function *) - simpl. econstructor; split. + monadInv H6. econstructor; split. apply plus_one. eapply exec_function_external; eauto. econstructor; eauto. + (* return *) inv H4. inv H1. exploit find_label_lin_succ; eauto. intros [c' AT]. @@ -642,17 +709,18 @@ Lemma transf_initial_states: forall st1, LTL.initial_state prog st1 -> exists st2, LTLin.initial_state tprog st2 /\ match_states st1 st2. Proof. - intros. inversion H. - exists (Callstate nil (transf_fundef f) (Locmap.init Vundef) (Genv.init_mem tprog)); split. + intros. inversion H. + exploit function_ptr_translated; eauto. intros [tf [A B]]. + exists (Callstate nil tf (Locmap.init Vundef) (Genv.init_mem tprog)); split. econstructor; eauto. - change (prog_main tprog) with (prog_main prog). + replace (prog_main tprog) with (prog_main prog). rewrite symbols_preserved. eauto. - apply function_ptr_translated; auto. - rewrite <- H2. apply sig_preserved. + symmetry. apply (transform_partial_program_main transf_fundef _ TRANSF). + rewrite <- H2. apply sig_preserved. auto. replace (Genv.init_mem tprog) with (Genv.init_mem prog). - constructor. constructor. + constructor. constructor. auto. eapply Genv.find_funct_ptr_prop; eauto. - symmetry. unfold tprog, transf_program. apply Genv.init_mem_transf. + symmetry. apply Genv.init_mem_transf_partial with transf_fundef. auto. Qed. Lemma transf_final_states: diff --git a/backend/Linearizetyping.v b/backend/Linearizetyping.v index c930ca5..473b342 100644 --- a/backend/Linearizetyping.v +++ b/backend/Linearizetyping.v @@ -2,6 +2,7 @@ Require Import Coqlib. Require Import Maps. +Require Import Errors. Require Import AST. Require Import Op. Require Import Locations. @@ -65,33 +66,34 @@ Proof. Qed. Lemma wt_transf_function: - forall f, + forall f tf, LTLtyping.wt_function f -> - wt_function (transf_function f). + transf_function f = OK tf -> + wt_function tf. Proof. - intros. inv H. constructor; auto. + intros. inv H. monadInv H0. constructor; auto. simpl. apply wt_add_branch. apply wt_linearize_body. auto. Qed. Lemma wt_transf_fundef: - forall f, + forall f tf, LTLtyping.wt_fundef f -> - wt_fundef (transf_fundef f). + transf_fundef f = OK tf -> + wt_fundef tf. Proof. - induction 1; simpl. - constructor; assumption. - constructor; apply wt_transf_function; assumption. + induction 1; intros. monadInv H. constructor. + monadInv H0. constructor; eapply wt_transf_function; eauto. Qed. Lemma program_typing_preserved: - forall (p: LTL.program), + forall (p: LTL.program) (tp: LTLin.program), LTLtyping.wt_program p -> - LTLintyping.wt_program (transf_program p). + transf_program p = OK tp -> + LTLintyping.wt_program tp. Proof. intros; red; intros. - generalize (transform_program_function transf_fundef p i f H0). + generalize (transform_partial_program_function transf_fundef _ _ _ H0 H1). intros [f0 [IN TR]]. - subst f. apply wt_transf_fundef; auto. - apply (H i f0 IN). + eapply wt_transf_fundef; eauto. Qed. |