summaryrefslogtreecommitdiff
path: root/backend
diff options
context:
space:
mode:
authorGravatar xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e>2007-10-27 10:23:16 +0000
committerGravatar xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e>2007-10-27 10:23:16 +0000
commite882493e2c4b91024b42f0603ca6869e95695e85 (patch)
tree1d90dda6b56b541310d8b8703152fdcd49e8a7fa /backend
parent7f6ac3209e7fb7d822780c7e990fb604b11a6409 (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.v107
-rw-r--r--backend/Linearizeproof.v280
-rw-r--r--backend/Linearizetyping.v28
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.