diff options
author | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2012-11-12 13:42:22 +0000 |
---|---|---|
committer | xleroy <xleroy@fca1b0fc-160b-0410-b1d3-a4f43f01ea2e> | 2012-11-12 13:42:22 +0000 |
commit | ce4951549999f403446415c135ad1403a16a15c3 (patch) | |
tree | cac9bbb2fea29fce331916b277c38ed8fe29e471 /common | |
parent | dcb9f48f51cec5e864565862a700c27df2a1a7e6 (diff) |
Globalenvs: allocate one-byte block with permissions Nonempty for each
function definition, so that comparisons between function pointers
are correctly defined.
AST, Globalenvs, and many other files:
represent programs as a list of (function or variable) definitions
instead of two lists, one for functions and the other for variables.
git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@2067 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
Diffstat (limited to 'common')
-rw-r--r-- | common/AST.v | 422 | ||||
-rw-r--r-- | common/Globalenvs.v | 1784 |
2 files changed, 979 insertions, 1227 deletions
diff --git a/common/AST.v b/common/AST.v index 6425cb0..ccc9dbf 100644 --- a/common/AST.v +++ b/common/AST.v @@ -118,44 +118,29 @@ Record globvar (V: Type) : Type := mkglobvar { }. (** Whole programs consist of: -- a collection of function definitions (name and description); -- the name of the ``main'' function that serves as entry point in the program; -- a collection of global variable declarations (name and information). +- a collection of global definitions (name and description); +- the name of the ``main'' function that serves as entry point in the program. +A global definition is either a global function or a global variable. The type of function descriptions and that of additional information for variables vary among the various intermediate languages and are taken as parameters to the [program] type. The other parts of whole programs are common to all languages. *) -Record program (F V: Type) : Type := mkprogram { - prog_funct: list (ident * F); - prog_main: ident; - prog_vars: list (ident * globvar V) -}. +Inductive globdef (F V: Type) : Type := + | Gfun (f: F) + | Gvar (v: globvar V). -Definition funct_names (F: Type) (fl: list (ident * F)) : list ident := - map (@fst ident F) fl. +Implicit Arguments Gfun [F V]. +Implicit Arguments Gvar [F V]. -Lemma funct_names_app : forall (F: Type) (fl1 fl2 : list (ident * F)), - funct_names (fl1 ++ fl2) = funct_names fl1 ++ funct_names fl2. -Proof. - intros; unfold funct_names; apply list_append_map. -Qed. - -Definition var_names (V: Type) (vl: list (ident * globvar V)) : list ident := - map (@fst ident (globvar V)) vl. - -Lemma var_names_app : forall (V: Type) (vl1 vl2 : list (ident * globvar V)), - var_names (vl1 ++ vl2) = var_names vl1 ++ funct_names vl2. -Proof. - intros; unfold var_names; apply list_append_map. -Qed. - -Definition prog_funct_names (F V: Type) (p: program F V) : list ident := - funct_names p.(prog_funct). +Record program (F V: Type) : Type := mkprogram { + prog_defs: list (ident * globdef F V); + prog_main: ident +}. -Definition prog_var_names (F V: Type) (p: program F V) : list ident := - var_names p.(prog_vars). +Definition prog_defs_names (F V: Type) (p: program F V) : list ident := + List.map fst p.(prog_defs). (** * Generic transformations over programs *) @@ -168,253 +153,195 @@ Section TRANSF_PROGRAM. Variable A B V: Type. Variable transf: A -> B. -Definition transf_program (l: list (ident * A)) : list (ident * B) := - List.map (fun id_fn => (fst id_fn, transf (snd id_fn))) l. +Definition transform_program_globdef (idg: ident * globdef A V) : ident * globdef B V := + match idg with + | (id, Gfun f) => (id, Gfun (transf f)) + | (id, Gvar v) => (id, Gvar v) + end. Definition transform_program (p: program A V) : program B V := mkprogram - (transf_program p.(prog_funct)) - p.(prog_main) - p.(prog_vars). + (List.map transform_program_globdef p.(prog_defs)) + p.(prog_main). Lemma transform_program_function: forall p i tf, - In (i, tf) (transform_program p).(prog_funct) -> - exists f, In (i, f) p.(prog_funct) /\ transf f = tf. + In (i, Gfun tf) (transform_program p).(prog_defs) -> + exists f, In (i, Gfun f) p.(prog_defs) /\ transf f = tf. Proof. - simpl. unfold transf_program. intros. + simpl. unfold transform_program. intros. exploit list_in_map_inv; eauto. - intros [[i' f] [EQ IN]]. simpl in EQ. inversion EQ; subst. - exists f; split; auto. + intros [[i' gd] [EQ IN]]. simpl in EQ. destruct gd; inv EQ. + exists f; auto. Qed. End TRANSF_PROGRAM. -(** The following is a variant of [transform_program] where the - code transformation function can fail and therefore returns an - option type. *) +(** The following is a more general presentation of [transform_program] where + global variable information can be transformed, in addition to function + definitions. Moreover, the transformation functions can fail and + return an error message. *) Open Local Scope error_monad_scope. Open Local Scope string_scope. -Section MAP_PARTIAL. +Section TRANSF_PROGRAM_GEN. -Variable A B C: Type. -Variable prefix_errmsg: A -> errmsg. -Variable f: B -> res C. +Variables A B V W: Type. +Variable transf_fun: A -> res B. +Variable transf_var: V -> res W. + +Definition transf_globvar (g: globvar V) : res (globvar W) := + do info' <- transf_var g.(gvar_info); + OK (mkglobvar info' g.(gvar_init) g.(gvar_readonly) g.(gvar_volatile)). -Fixpoint map_partial (l: list (A * B)) : res (list (A * C)) := +Fixpoint transf_globdefs (l: list (ident * globdef A V)) : res (list (ident * globdef B W)) := match l with | nil => OK nil - | (a, b) :: rem => - match f b with - | Error msg => Error (prefix_errmsg a ++ msg)%list - | OK c => - do rem' <- map_partial rem; - OK ((a, c) :: rem') + | (id, Gfun f) :: l' => + match transf_fun f with + | Error msg => Error (MSG "In function " :: CTX id :: MSG ": " :: msg) + | OK tf => + do tl' <- transf_globdefs l'; OK ((id, Gfun tf) :: tl') + end + | (id, Gvar v) :: l' => + match transf_globvar v with + | Error msg => Error (MSG "In variable " :: CTX id :: MSG ": " :: msg) + | OK tv => + do tl' <- transf_globdefs l'; OK ((id, Gvar tv) :: tl') end end. -Remark In_map_partial: - forall l l' a c, - map_partial l = OK l' -> - In (a, c) l' -> - exists b, In (a, b) l /\ f b = OK c. -Proof. - induction l; simpl. - intros. inv H. elim H0. - intros until c. destruct a as [a1 b1]. - caseEq (f b1); try congruence. - intro c1; intros. monadInv H0. - elim H1; intro. inv H0. exists b1; auto. - exploit IHl; eauto. intros [b [P Q]]. exists b; auto. -Qed. +Definition transform_partial_program2 (p: program A V) : res (program B W) := + do gl' <- transf_globdefs p.(prog_defs); OK(mkprogram gl' p.(prog_main)). -Remark map_partial_forall2: - forall l l', - map_partial l = OK l' -> - list_forall2 - (fun (a_b: A * B) (a_c: A * C) => - fst a_b = fst a_c /\ f (snd a_b) = OK (snd a_c)) - l l'. +Lemma transform_partial_program2_function: + forall p tp i tf, + transform_partial_program2 p = OK tp -> + In (i, Gfun tf) tp.(prog_defs) -> + exists f, In (i, Gfun f) p.(prog_defs) /\ transf_fun f = OK tf. Proof. - induction l; simpl. - intros. inv H. constructor. - intro l'. destruct a as [a b]. - caseEq (f b). 2: congruence. intro c; intros. monadInv H0. - constructor. simpl. auto. auto. + intros. monadInv H. simpl in H0. + revert x EQ H0. induction (prog_defs p); simpl; intros. + inv EQ. contradiction. + destruct a as [id [f|v]]. + destruct (transf_fun f) as [tf1|msg]_eqn; monadInv EQ. + simpl in H0; destruct H0. inv H. exists f; auto. + exploit IHl; eauto. intros [f' [P Q]]; exists f'; auto. + destruct (transf_globvar v) as [tv1|msg]_eqn; monadInv EQ. + simpl in H0; destruct H0. inv H. + exploit IHl; eauto. intros [f' [P Q]]; exists f'; auto. Qed. -End MAP_PARTIAL. - -Remark map_partial_total: - forall (A B C: Type) (prefix: A -> errmsg) (f: B -> C) (l: list (A * B)), - map_partial prefix (fun b => OK (f b)) l = - OK (List.map (fun a_b => (fst a_b, f (snd a_b))) l). +Lemma transform_partial_program2_variable: + forall p tp i tv, + transform_partial_program2 p = OK tp -> + In (i, Gvar tv) tp.(prog_defs) -> + exists v, + In (i, Gvar(mkglobvar v tv.(gvar_init) tv.(gvar_readonly) tv.(gvar_volatile))) p.(prog_defs) + /\ transf_var v = OK tv.(gvar_info). Proof. - induction l; simpl. - auto. - destruct a as [a1 b1]. rewrite IHl. reflexivity. + intros. monadInv H. simpl in H0. + revert x EQ H0. induction (prog_defs p); simpl; intros. + inv EQ. contradiction. + destruct a as [id [f|v]]. + destruct (transf_fun f) as [tf1|msg]_eqn; monadInv EQ. + simpl in H0; destruct H0. inv H. + exploit IHl; eauto. intros [v' [P Q]]; exists v'; auto. + destruct (transf_globvar v) as [tv1|msg]_eqn; monadInv EQ. + simpl in H0; destruct H0. inv H. + monadInv Heqr. simpl. exists (gvar_info v). split. left. destruct v; auto. auto. + exploit IHl; eauto. intros [v' [P Q]]; exists v'; auto. Qed. -Remark map_partial_identity: - forall (A B: Type) (prefix: A -> errmsg) (l: list (A * B)), - map_partial prefix (fun b => OK b) l = OK l. +Lemma transform_partial_program2_main: + forall p tp, + transform_partial_program2 p = OK tp -> + tp.(prog_main) = p.(prog_main). Proof. - induction l; simpl. - auto. - destruct a as [a1 b1]. rewrite IHl. reflexivity. + intros. monadInv H. reflexivity. Qed. -Section TRANSF_PARTIAL_PROGRAM. +(** Additionally, we can also "augment" the program with new global definitions + and a different "main" function. *) -Variable A B V: Type. -Variable transf_partial: A -> res B. - -Definition prefix_name (id: ident) : errmsg := - MSG "In function " :: CTX id :: MSG ": " :: nil. +Section AUGMENT. -Definition transform_partial_program (p: program A V) : res (program B V) := - do fl <- map_partial prefix_name transf_partial p.(prog_funct); - OK (mkprogram fl p.(prog_main) p.(prog_vars)). +Variable new_globs: list(ident * globdef B W). +Variable new_main: ident. -Lemma transform_partial_program_function: - forall p tp i tf, - transform_partial_program p = OK tp -> - In (i, tf) tp.(prog_funct) -> - exists f, In (i, f) p.(prog_funct) /\ transf_partial f = OK tf. -Proof. - intros. monadInv H. simpl in H0. - eapply In_map_partial; eauto. -Qed. +Definition transform_partial_augment_program (p: program A V) : res (program B W) := + do gl' <- transf_globdefs p.(prog_defs); + OK(mkprogram (gl' ++ new_globs) new_main). -Lemma transform_partial_program_main: +Lemma transform_partial_augment_program_main: forall p tp, - transform_partial_program p = OK tp -> - tp.(prog_main) = p.(prog_main). + transform_partial_augment_program p = OK tp -> + tp.(prog_main) = new_main. Proof. intros. monadInv H. reflexivity. Qed. -Lemma transform_partial_program_vars: - forall p tp, - transform_partial_program p = OK tp -> - tp.(prog_vars) = p.(prog_vars). +End AUGMENT. + +Remark transform_partial_program2_augment: + forall p, + transform_partial_program2 p = + transform_partial_augment_program nil p.(prog_main) p. Proof. - intros. monadInv H. reflexivity. + unfold transform_partial_program2, transform_partial_augment_program; intros. + destruct (transf_globdefs (prog_defs p)); auto. + simpl. f_equal. f_equal. rewrite <- app_nil_end. auto. Qed. -End TRANSF_PARTIAL_PROGRAM. +End TRANSF_PROGRAM_GEN. -(** The following is a variant of [transform_program_partial] where - both the program functions and the additional variable information - are transformed by functions that can fail. *) +(** The following is a special case of [transform_partial_program2], + where only function definitions are transformed, but not variable definitions. *) -Section TRANSF_PARTIAL_PROGRAM2. - -Variable A B V W: Type. -Variable transf_partial_function: A -> res B. -Variable transf_partial_variable: V -> res W. - -Definition transf_globvar (g: globvar V) : res (globvar W) := - do info' <- transf_partial_variable g.(gvar_info); - OK (mkglobvar info' g.(gvar_init) g.(gvar_readonly) g.(gvar_volatile)). - -Definition transform_partial_program2 (p: program A V) : res (program B W) := - do fl <- map_partial prefix_name transf_partial_function p.(prog_funct); - do vl <- map_partial prefix_name transf_globvar p.(prog_vars); - OK (mkprogram fl p.(prog_main) vl). +Section TRANSF_PARTIAL_PROGRAM. -Lemma transform_partial_program2_function: - forall p tp i tf, - transform_partial_program2 p = OK tp -> - In (i, tf) tp.(prog_funct) -> - exists f, In (i, f) p.(prog_funct) /\ transf_partial_function f = OK tf. -Proof. - intros. monadInv H. - eapply In_map_partial; eauto. -Qed. +Variable A B V: Type. +Variable transf_partial: A -> res B. -Lemma transform_partial_program2_variable: - forall p tp i tg, - transform_partial_program2 p = OK tp -> - In (i, tg) tp.(prog_vars) -> - exists v, - In (i, mkglobvar v tg.(gvar_init) tg.(gvar_readonly) tg.(gvar_volatile)) p.(prog_vars) - /\ transf_partial_variable v = OK tg.(gvar_info). -Proof. - intros. monadInv H. exploit In_map_partial; eauto. intros [g [P Q]]. - monadInv Q. simpl in *. exists (gvar_info g); split. destruct g; auto. auto. - Qed. +Definition transform_partial_program (p: program A V) : res (program B V) := + transform_partial_program2 transf_partial (fun v => OK v) p. -Lemma transform_partial_program2_main: +Lemma transform_partial_program_main: forall p tp, - transform_partial_program2 p = OK tp -> + transform_partial_program p = OK tp -> tp.(prog_main) = p.(prog_main). Proof. - intros. monadInv H. reflexivity. + apply transform_partial_program2_main. Qed. -End TRANSF_PARTIAL_PROGRAM2. - -(** The following is a variant of [transform_partial_program2] where the - where the set of functions and global data is augmented, and - the main function is potentially changed. *) - -Section TRANSF_PARTIAL_AUGMENT_PROGRAM. - -Variable A B V W: Type. -Variable transf_partial_function: A -> res B. -Variable transf_partial_variable: V -> res W. - -Variable new_functs : list (ident * B). -Variable new_vars : list (ident * globvar W). -Variable new_main : ident. - -Definition transform_partial_augment_program (p: program A V) : res (program B W) := - do fl <- map_partial prefix_name transf_partial_function p.(prog_funct); - do vl <- map_partial prefix_name (transf_globvar transf_partial_variable) p.(prog_vars); - OK (mkprogram (fl ++ new_functs) new_main (vl ++ new_vars)). - -Lemma transform_partial_augment_program_function: +Lemma transform_partial_program_function: forall p tp i tf, - transform_partial_augment_program p = OK tp -> - In (i, tf) tp.(prog_funct) -> - (exists f, In (i, f) p.(prog_funct) /\ transf_partial_function f = OK tf) - \/ In (i,tf) new_functs. -Proof. - intros. monadInv H. simpl in H0. - rewrite in_app in H0. destruct H0. - left. eapply In_map_partial; eauto. - right. auto. -Qed. - -Lemma transform_partial_augment_program_main: - forall p tp, - transform_partial_augment_program p = OK tp -> - tp.(prog_main) = new_main. + transform_partial_program p = OK tp -> + In (i, Gfun tf) tp.(prog_defs) -> + exists f, In (i, Gfun f) p.(prog_defs) /\ transf_partial f = OK tf. Proof. - intros. monadInv H. reflexivity. + apply transform_partial_program2_function. Qed. +End TRANSF_PARTIAL_PROGRAM. -Lemma transform_partial_augment_program_variable: - forall p tp i tg, - transform_partial_augment_program p = OK tp -> - In (i, tg) tp.(prog_vars) -> - (exists v, In (i, mkglobvar v tg.(gvar_init) tg.(gvar_readonly) tg.(gvar_volatile)) p.(prog_vars) /\ transf_partial_variable v = OK tg.(gvar_info)) - \/ In (i,tg) new_vars. +Lemma transform_program_partial_program: + forall (A B V: Type) (transf: A -> B) (p: program A V), + transform_partial_program (fun f => OK(transf f)) p = OK(transform_program transf p). Proof. - intros. monadInv H. - simpl in H0. rewrite in_app in H0. inversion H0. - left. exploit In_map_partial; eauto. intros [g [P Q]]. - monadInv Q. simpl in *. exists (gvar_info g); split. destruct g; auto. auto. - right. auto. + intros. + unfold transform_partial_program, transform_partial_program2, transform_program; intros. + replace (transf_globdefs (fun f => OK (transf f)) (fun v => OK v) p.(prog_defs)) + with (OK (map (transform_program_globdef transf) p.(prog_defs))). + auto. + induction (prog_defs p); simpl. + auto. + destruct a as [id [f|v]]; rewrite <- IHl. + auto. + destruct v; auto. Qed. -End TRANSF_PARTIAL_AUGMENT_PROGRAM. - - (** The following is a relational presentation of [transform_partial_augment_preogram]. Given relations between function definitions and between variable information, it defines a relation @@ -429,61 +356,50 @@ Variable A B V W: Type. Variable match_fundef: A -> B -> Prop. Variable match_varinfo: V -> W -> Prop. -Inductive match_funct_entry: ident * A -> ident * B -> Prop := - | match_funct_entry_intro: forall id fn1 fn2, - match_fundef fn1 fn2 -> - match_funct_entry (id, fn1) (id, fn2). - -Inductive match_var_entry: ident * globvar V -> ident * globvar W -> Prop := - | match_var_entry_intro: forall id info1 info2 init ro vo, +Inductive match_globdef: ident * globdef A V -> ident * globdef B W -> Prop := + | match_glob_fun: forall id f1 f2, + match_fundef f1 f2 -> + match_globdef (id, Gfun f1) (id, Gfun f2) + | match_glob_var: forall id init ro vo info1 info2, match_varinfo info1 info2 -> - match_var_entry (id, mkglobvar info1 init ro vo) - (id, mkglobvar info2 init ro vo). + match_globdef (id, Gvar (mkglobvar info1 init ro vo)) (id, Gvar (mkglobvar info2 init ro vo)). -Definition match_program (new_functs : list (ident * B)) - (new_vars : list (ident * globvar W)) +Definition match_program (new_globs : list (ident * globdef B W)) (new_main : ident) (p1: program A V) (p2: program B W) : Prop := - (exists tfuncts, list_forall2 match_funct_entry p1.(prog_funct) tfuncts /\ - (p2.(prog_funct) = tfuncts ++ new_functs)) /\ - (exists tvars, list_forall2 match_var_entry p1.(prog_vars) tvars /\ - (p2.(prog_vars) = tvars ++ new_vars)) /\ + (exists tglob, list_forall2 match_globdef p1.(prog_defs) tglob /\ + p2.(prog_defs) = tglob ++ new_globs) /\ p2.(prog_main) = new_main. End MATCH_PROGRAM. -Remark transform_partial_augment_program_match: +Lemma transform_partial_augment_program_match: forall (A B V W: Type) - (transf_partial_function: A -> res B) - (transf_partial_variable : V -> res W) + (transf_fun: A -> res B) + (transf_var: V -> res W) (p: program A V) - (new_functs : list (ident * B)) - (new_vars : list (ident * globvar W)) + (new_globs : list (ident * globdef B W)) (new_main : ident) (tp: program B W), - transform_partial_augment_program transf_partial_function transf_partial_variable new_functs new_vars new_main p = OK tp -> + transform_partial_augment_program transf_fun transf_var new_globs new_main p = OK tp -> match_program - (fun fd tfd => transf_partial_function fd = OK tfd) - (fun info tinfo => transf_partial_variable info = OK tinfo) - new_functs new_vars new_main + (fun fd tfd => transf_fun fd = OK tfd) + (fun info tinfo => transf_var info = OK tinfo) + new_globs new_main p tp. Proof. - intros. unfold transform_partial_augment_program in H. monadInv H. split. - exists x. split. - apply list_forall2_imply with - (fun (ab: ident * A) (ac: ident * B) => - fst ab = fst ac /\ transf_partial_function (snd ab) = OK (snd ac)). - eapply map_partial_forall2. eauto. - intros. destruct v1; destruct v2; simpl in *. - destruct H1; subst. constructor. auto. - auto. - split. exists x0. split. - apply list_forall2_imply with - (fun (ab: ident * globvar V) (ac: ident * globvar W) => - fst ab = fst ac /\ transf_globvar transf_partial_variable (snd ab) = OK (snd ac)). - eapply map_partial_forall2. eauto. - intros. destruct v1; destruct v2; simpl in *. destruct H1; subst. - monadInv H2. destruct g; simpl in *. constructor. auto. auto. auto. + unfold transform_partial_augment_program; intros. monadInv H. + red; simpl. split; auto. exists x; split; auto. + revert x EQ. generalize (prog_defs p). induction l; simpl; intros. + monadInv EQ. constructor. + destruct a as [id [f|v]]. + (* function *) + destruct (transf_fun f) as [tf|?]_eqn; monadInv EQ. + constructor; auto. constructor; auto. + (* variable *) + unfold transf_globvar in EQ. + destruct (transf_var (gvar_info v)) as [tinfo|?]_eqn; simpl in EQ; monadInv EQ. + constructor; auto. destruct v; simpl in *. constructor; auto. Qed. (** * External functions *) diff --git a/common/Globalenvs.v b/common/Globalenvs.v index ba038f8..8565ae6 100644 --- a/common/Globalenvs.v +++ b/common/Globalenvs.v @@ -69,13 +69,13 @@ Record t: Type := mkgenv { genv_symb: PTree.t block; (**r mapping symbol -> block *) genv_funs: ZMap.t (option F); (**r mapping function pointer -> definition *) genv_vars: ZMap.t (option (globvar V)); (**r mapping variable pointer -> info *) - genv_nextfun: block; (**r next function pointer *) - genv_nextvar: block; (**r next variable pointer *) - genv_nextfun_neg: genv_nextfun < 0; - genv_nextvar_pos: genv_nextvar > 0; - genv_symb_range: forall id b, PTree.get id genv_symb = Some b -> b <> 0 /\ genv_nextfun < b /\ b < genv_nextvar; - genv_funs_range: forall b f, ZMap.get b genv_funs = Some f -> genv_nextfun < b < 0; - genv_vars_range: forall b v, ZMap.get b genv_vars = Some v -> 0 < b < genv_nextvar; + genv_next: block; (**r next symbol pointer *) + genv_next_pos: genv_next > 0; + genv_symb_range: forall id b, PTree.get id genv_symb = Some b -> 0 < b < genv_next; + genv_funs_range: forall b f, ZMap.get b genv_funs = Some f -> 0 < b < genv_next; + genv_vars_range: forall b v, ZMap.get b genv_vars = Some v -> 0 < b < genv_next; + genv_funs_vars: forall b1 b2 f v, + ZMap.get b1 genv_funs = Some f -> ZMap.get b2 genv_vars = Some v -> b1 <> b2; genv_vars_inj: forall id1 id2 b, PTree.get id1 genv_symb = Some b -> PTree.get id2 genv_symb = Some b -> id1 = id2 }. @@ -117,69 +117,53 @@ Definition find_var_info (ge: t) (b: block) : option (globvar V) := (** ** Constructing the global environment *) -Program Definition add_function (ge: t) (idf: ident * F) : t := +Program Definition add_global (ge: t) (idg: ident * globdef F V) : t := @mkgenv - (PTree.set idf#1 ge.(genv_nextfun) ge.(genv_symb)) - (ZMap.set ge.(genv_nextfun) (Some idf#2) ge.(genv_funs)) - ge.(genv_vars) - (ge.(genv_nextfun) - 1) - ge.(genv_nextvar) + (PTree.set idg#1 ge.(genv_next) ge.(genv_symb)) + (match idg#2 with + | Gfun f => ZMap.set ge.(genv_next) (Some f) ge.(genv_funs) + | Gvar v => ge.(genv_funs) + end) + (match idg#2 with + | Gfun f => ge.(genv_vars) + | Gvar v => ZMap.set ge.(genv_next) (Some v) ge.(genv_vars) + end) + (ge.(genv_next) + 1) _ _ _ _ _ _. Next Obligation. destruct ge; simpl; omega. Qed. Next Obligation. - destruct ge; auto. -Qed. -Next Obligation. destruct ge; simpl in *. rewrite PTree.gsspec in H. destruct (peq id i). inv H. unfold block; omega. exploit genv_symb_range0; eauto. unfold block; omega. Qed. Next Obligation. - destruct ge; simpl in *. rewrite ZMap.gsspec in H. - destruct (ZIndexed.eq b genv_nextfun0). subst; omega. + destruct ge; simpl in *. + destruct g. + rewrite ZMap.gsspec in H. + destruct (ZIndexed.eq b genv_next0). subst; omega. + exploit genv_funs_range0; eauto. omega. exploit genv_funs_range0; eauto. omega. -Qed. -Next Obligation. - destruct ge; eauto. Qed. Next Obligation. destruct ge; simpl in *. - rewrite PTree.gsspec in H. rewrite PTree.gsspec in H0. - destruct (peq id1 i); destruct (peq id2 i). - congruence. - exploit genv_symb_range0; eauto. intros [A B]. inv H. omegaContradiction. - exploit genv_symb_range0; eauto. intros [A B]. inv H0. omegaContradiction. - eauto. -Qed. - -Program Definition add_variable (ge: t) (idv: ident * globvar V) : t := - @mkgenv - (PTree.set idv#1 ge.(genv_nextvar) ge.(genv_symb)) - ge.(genv_funs) - (ZMap.set ge.(genv_nextvar) (Some idv#2) ge.(genv_vars)) - ge.(genv_nextfun) - (ge.(genv_nextvar) + 1) - _ _ _ _ _ _. -Next Obligation. - destruct ge; auto. -Qed. -Next Obligation. - destruct ge; simpl; omega. -Qed. -Next Obligation. - destruct ge; simpl in *. - rewrite PTree.gsspec in H. destruct (peq id i). inv H. unfold block; omega. - exploit genv_symb_range0; eauto. unfold block; omega. -Qed. -Next Obligation. - destruct ge; eauto. + destruct g. + exploit genv_vars_range0; eauto. omega. + rewrite ZMap.gsspec in H. + destruct (ZIndexed.eq b genv_next0). subst; omega. + exploit genv_vars_range0; eauto. omega. Qed. Next Obligation. - destruct ge; simpl in *. rewrite ZMap.gsspec in H. - destruct (ZIndexed.eq b genv_nextvar0). subst; omega. - exploit genv_vars_range0; eauto. omega. + destruct ge; simpl in *. destruct g. + rewrite ZMap.gsspec in H. + destruct (ZIndexed.eq b1 genv_next0). inv H. + exploit genv_vars_range0; eauto. unfold ZIndexed.t; omega. + eauto. + rewrite ZMap.gsspec in H0. + destruct (ZIndexed.eq b2 genv_next0). inv H. + exploit genv_funs_range0; eauto. unfold ZIndexed.t; omega. + eauto. Qed. Next Obligation. destruct ge; simpl in *. @@ -191,16 +175,26 @@ Next Obligation. eauto. Qed. +Definition add_globals (ge: t) (gl: list (ident * globdef F V)) : t := + List.fold_left add_global gl ge. + +Lemma add_globals_app: + forall gl2 gl1 ge, + add_globals ge (gl1 ++ gl2) = add_globals (add_globals ge gl1) gl2. +Proof. + induction gl1; simpl; intros. auto. rewrite IHgl1; auto. +Qed. + Program Definition empty_genv : t := - @mkgenv (PTree.empty block) (ZMap.init None) (ZMap.init None) (-1) 1 _ _ _ _ _ _. + @mkgenv (PTree.empty block) (ZMap.init None) (ZMap.init None) 1 _ _ _ _ _ _. Next Obligation. omega. Qed. Next Obligation. - omega. + rewrite PTree.gempty in H. discriminate. Qed. Next Obligation. - rewrite PTree.gempty in H. discriminate. + rewrite ZMap.gi in H. discriminate. Qed. Next Obligation. rewrite ZMap.gi in H. discriminate. @@ -212,27 +206,54 @@ Next Obligation. rewrite PTree.gempty in H. discriminate. Qed. -Definition add_functions (ge: t) (fl: list (ident * F)) : t := - List.fold_left add_function fl ge. +Definition globalenv (p: program F V) := + add_globals empty_genv p.(prog_defs). -Lemma add_functions_app : forall ge fl1 fl2, - add_functions ge (fl1 ++ fl2) = add_functions (add_functions ge fl1) fl2. -Proof. - intros. unfold add_functions. rewrite fold_left_app. auto. -Qed. +(** Proof principles *) +Section GLOBALENV_PRINCIPLES. -Definition add_variables (ge: t) (vl: list (ident * globvar V)) : t := - List.fold_left add_variable vl ge. +Variable P: t -> Prop. -Lemma add_variables_app : forall ge vl1 vl2 , - add_variables ge (vl1 ++ vl2) = add_variables (add_variables ge vl1) vl2. -Proof. - intros. unfold add_variables. rewrite fold_left_app. auto. +Lemma add_globals_preserves: + forall gl ge, + (forall ge id g, P ge -> In (id, g) gl -> P (add_global ge (id, g))) -> + P ge -> P (add_globals ge gl). +Proof. + induction gl; simpl; intros. + auto. + destruct a. apply IHgl; auto. Qed. -Definition globalenv (p: program F V) := - add_variables (add_functions empty_genv p.(prog_funct)) p.(prog_vars). +Lemma add_globals_ensures: + forall id g gl ge, + (forall ge id g, P ge -> In (id, g) gl -> P (add_global ge (id, g))) -> + (forall ge, P (add_global ge (id, g))) -> + In (id, g) gl -> P (add_globals ge gl). +Proof. + induction gl; simpl; intros. + contradiction. + destruct H1. subst a. apply add_globals_preserves; auto. + apply IHgl; auto. +Qed. + +Lemma add_globals_norepet_ensures: + forall id g gl ge, + (forall ge id1 g1, P ge -> In (id1, g1) gl -> id1 <> id -> P (add_global ge (id1, g1))) -> + (forall ge, P (add_global ge (id, g))) -> + In (id, g) gl -> list_norepet (map fst gl) -> P (add_globals ge gl). +Proof. + induction gl; simpl; intros. + contradiction. + inv H2. + destruct H1. subst a. simpl in H5. + apply add_globals_preserves; auto. + intros. apply H. auto. auto. red; intros; subst id0. elim H5. + change id with (fst (id, g0)). apply List.in_map; auto. + apply IHgl; auto. +Qed. + +End GLOBALENV_PRINCIPLES. (** ** Properties of the operations over global environments *) @@ -254,298 +275,132 @@ Proof. Qed. Theorem find_symbol_exists: - forall p id gv, - In (id, gv) (prog_vars p) -> + forall p id g, + In (id, g) (prog_defs p) -> exists b, find_symbol (globalenv p) id = Some b. Proof. - intros until gv. - assert (forall vl ge, - (exists b, find_symbol ge id = Some b) -> - exists b, find_symbol (add_variables ge vl) id = Some b). - unfold find_symbol; induction vl; simpl; intros. auto. apply IHvl. - simpl. rewrite PTree.gsspec. fold ident. destruct (peq id a#1). - exists (genv_nextvar ge); auto. auto. - - assert (forall vl ge, In (id, gv) vl -> - exists b, find_symbol (add_variables ge vl) id = Some b). - unfold find_symbol; induction vl; simpl; intros. contradiction. - destruct H0. apply H. subst; unfold find_symbol; simpl. - rewrite PTree.gss. exists (genv_nextvar ge); auto. - eauto. + intros. unfold globalenv. eapply add_globals_ensures; eauto. +(* preserves *) + intros. unfold find_symbol; simpl. rewrite PTree.gsspec. destruct (peq id id0). + econstructor; eauto. + auto. +(* ensures *) + intros. unfold find_symbol; simpl. rewrite PTree.gss. econstructor; eauto. +Qed. - intros. unfold globalenv; eauto. +Theorem find_funct_ptr_exists: + forall p id f, + list_norepet (prog_defs_names p) -> + In (id, Gfun f) (prog_defs p) -> + exists b, + find_symbol (globalenv p) id = Some b + /\ find_funct_ptr (globalenv p) b = Some f. +Proof. + intros; unfold globalenv. eapply add_globals_norepet_ensures; eauto. +(* preserves *) + intros. unfold find_symbol, find_funct_ptr in *; simpl. + destruct H1 as [b [A B]]. exists b; split. + rewrite PTree.gso; auto. + destruct g1 as [f1 | v1]. rewrite ZMap.gso. auto. + exploit genv_funs_range; eauto. unfold ZIndexed.t; omega. + auto. +(* ensures *) + intros. unfold find_symbol, find_funct_ptr in *; simpl. + exists (genv_next ge); split. apply PTree.gss. apply ZMap.gss. Qed. Theorem find_var_exists: - forall p id gv, - list_norepet (prog_var_names p) -> - In (id, gv) (prog_vars p) -> + forall p id v, + list_norepet (prog_defs_names p) -> + In (id, Gvar v) (prog_defs p) -> exists b, find_symbol (globalenv p) id = Some b - /\ find_var_info (globalenv p) b = Some gv. -Proof. - intros until gv. - assert (forall vl ge, - ~In id (var_names vl) -> - (exists b, find_symbol ge id = Some b /\ find_var_info ge b = Some gv) -> - (exists b, find_symbol (add_variables ge vl) id = Some b - /\ find_var_info (add_variables ge vl) b = Some gv)). - induction vl; simpl; intros. - auto. - apply IHvl. tauto. destruct a as [id1 gv1]. destruct H0 as [b [P Q]]. - unfold add_variable, find_symbol, find_var_info; simpl. - exists b; split. rewrite PTree.gso. auto. intuition. - rewrite ZMap.gso. auto. exploit genv_vars_range; eauto. - unfold ZIndexed.t; omega. - - unfold globalenv, prog_var_names. - generalize (prog_vars p) (add_functions empty_genv (prog_funct p)). - induction l; simpl; intros. - contradiction. - destruct a as [id1 gv1]; simpl in *. inv H0. - destruct H1. inv H0. - apply H; auto. - exists (genv_nextvar t0); split. - unfold find_symbol, add_variable; simpl. apply PTree.gss. - unfold find_var_info, add_variable; simpl. apply ZMap.gss. - apply IHl; auto. -Qed. - -Remark add_variables_inversion : forall vs e x b, - find_symbol (add_variables e vs) x = Some b -> - In x (var_names vs) \/ find_symbol e x = Some b. -Proof. - induction vs; intros. - simpl in H. intuition. - simpl in H. destruct (IHvs _ _ _ H). - left. simpl. intuition. - destruct a as [y ?]. - unfold add_variable, find_symbol in H0. simpl in H0. - rewrite PTree.gsspec in H0. destruct (peq x y); subst; simpl; intuition. -Qed. - -Remark add_functions_inversion : forall fs e x b, - find_symbol (add_functions e fs) x = Some b -> - In x (funct_names fs) \/ find_symbol e x = Some b. -Proof. - induction fs; intros. - simpl in H. intuition. - simpl in H. destruct (IHfs _ _ _ H). - left. simpl. intuition. - destruct a as [y ?]. - unfold add_variable, find_symbol in H0. simpl in H0. - rewrite PTree.gsspec in H0. destruct (peq x y); subst; simpl; intuition. + /\ find_var_info (globalenv p) b = Some v. +Proof. + intros; unfold globalenv. eapply add_globals_norepet_ensures; eauto. +(* preserves *) + intros. unfold find_symbol, find_var_info in *; simpl. + destruct H1 as [b [A B]]. exists b; split. + rewrite PTree.gso; auto. + destruct g1 as [f1 | v1]. auto. rewrite ZMap.gso. auto. + exploit genv_vars_range; eauto. unfold ZIndexed.t; omega. +(* ensures *) + intros. unfold find_symbol, find_var_info in *; simpl. + exists (genv_next ge); split. apply PTree.gss. apply ZMap.gss. Qed. Lemma find_symbol_inversion : forall p x b, find_symbol (globalenv p) x = Some b -> - In x (prog_var_names p ++ prog_funct_names p). -Proof. - unfold prog_var_names, prog_funct_names, globalenv. - intros. - apply in_app. - apply add_variables_inversion in H. intuition. - apply add_functions_inversion in H0. inversion H0. intuition. - unfold find_symbol in H. - rewrite PTree.gempty in H. inversion H. -Qed. - - -Remark add_functions_same_symb: - forall id fl ge, - ~In id (funct_names fl) -> - find_symbol (add_functions ge fl) id = find_symbol ge id. -Proof. - induction fl; simpl; intros. auto. - rewrite IHfl. unfold find_symbol; simpl. apply PTree.gso. intuition. intuition. -Qed. - -Remark add_functions_same_address: - forall b fl ge, - b > ge.(genv_nextfun) -> - find_funct_ptr (add_functions ge fl) b = find_funct_ptr ge b. -Proof. - induction fl; simpl; intros. auto. - rewrite IHfl. unfold find_funct_ptr; simpl. apply ZMap.gso. - red; intros; subst b; omegaContradiction. - simpl. omega. -Qed. - -Remark add_variables_same_symb: - forall id vl ge, - ~In id (var_names vl) -> - find_symbol (add_variables ge vl) id = find_symbol ge id. + In x (prog_defs_names p). Proof. - induction vl; simpl; intros. auto. - rewrite IHvl. unfold find_symbol; simpl. apply PTree.gso. intuition. intuition. -Qed. - -Remark add_variables_same_address: - forall b vl ge, - b < ge.(genv_nextvar) -> - find_var_info (add_variables ge vl) b = find_var_info ge b. -Proof. - induction vl; simpl; intros. auto. - rewrite IHvl. unfold find_var_info; simpl. apply ZMap.gso. - red; intros; subst b; omegaContradiction. - simpl. omega. -Qed. - -Remark add_variables_same_funs: - forall b vl ge, find_funct_ptr (add_variables ge vl) b = find_funct_ptr ge b. -Proof. - induction vl; simpl; intros. auto. rewrite IHvl. auto. + intros until b; unfold globalenv. eapply add_globals_preserves. +(* preserves *) + unfold find_symbol; simpl; intros. rewrite PTree.gsspec in H1. + destruct (peq x id). subst x. change id with (fst (id, g)). apply List.in_map; auto. + auto. +(* base *) + unfold find_symbol; simpl; intros. rewrite PTree.gempty in H. discriminate. Qed. -Remark add_functions_nextvar: - forall fl ge, genv_nextvar (add_functions ge fl) = genv_nextvar ge. +Theorem find_funct_ptr_inversion: + forall p b f, + find_funct_ptr (globalenv p) b = Some f -> + exists id, In (id, Gfun f) (prog_defs p). Proof. - induction fl; simpl; intros. auto. rewrite IHfl. auto. + intros until f. unfold globalenv. apply add_globals_preserves. +(* preserves *) + unfold find_funct_ptr; simpl; intros. destruct g; auto. + rewrite ZMap.gsspec in H1. destruct (ZIndexed.eq b (genv_next ge)). + inv H1. exists id; auto. + auto. +(* base *) + unfold find_funct_ptr; simpl; intros. rewrite ZMap.gi in H. discriminate. Qed. -Remark add_variables_nextvar: - forall vl ge, genv_nextvar (add_variables ge vl) = genv_nextvar ge + Z_of_nat(List.length vl). +Theorem find_funct_inversion: + forall p v f, + find_funct (globalenv p) v = Some f -> + exists id, In (id, Gfun f) (prog_defs p). Proof. - induction vl; intros. - simpl. unfold block; omega. - simpl length; rewrite inj_S; simpl. rewrite IHvl. simpl. unfold block; omega. -Qed. - -Theorem find_funct_ptr_exists: - forall p id f, - list_norepet (prog_funct_names p) -> - list_disjoint (prog_funct_names p) (prog_var_names p) -> - In (id, f) (prog_funct p) -> - exists b, find_symbol (globalenv p) id = Some b - /\ find_funct_ptr (globalenv p) b = Some f. -Proof. - intros until f. - - assert (forall fl ge, In (id, f) fl -> list_norepet (funct_names fl) -> - exists b, find_symbol (add_functions ge fl) id = Some b - /\ find_funct_ptr (add_functions ge fl) b = Some f). - induction fl; simpl; intros. contradiction. inv H0. - destruct H. subst a. exists (genv_nextfun ge); split. - rewrite add_functions_same_symb; auto. unfold find_symbol; simpl. apply PTree.gss. - rewrite add_functions_same_address. unfold find_funct_ptr; simpl. apply ZMap.gss. - simpl; omega. - apply IHfl; auto. - - intros. exploit (H p.(prog_funct) empty_genv); eauto. intros [b [A B]]. - unfold globalenv; exists b; split. - rewrite add_variables_same_symb. auto. eapply list_disjoint_notin; eauto. - unfold prog_funct_names. change id with (fst (id, f)). apply in_map; auto. - rewrite add_variables_same_funs. auto. + intros. exploit find_funct_inv; eauto. intros [b EQ]. subst v. + rewrite find_funct_find_funct_ptr in H. + eapply find_funct_ptr_inversion; eauto. Qed. Theorem find_funct_ptr_prop: forall (P: F -> Prop) p b f, - (forall id f, In (id, f) (prog_funct p) -> P f) -> + (forall id f, In (id, Gfun f) (prog_defs p) -> P f) -> find_funct_ptr (globalenv p) b = Some f -> P f. Proof. - intros until f. intros PROP. - assert (forall fl ge, - List.incl fl (prog_funct p) -> - match find_funct_ptr ge b with None => True | Some f => P f end -> - match find_funct_ptr (add_functions ge fl) b with None => True | Some f => P f end). - induction fl; simpl; intros. auto. - apply IHfl. eauto with coqlib. unfold find_funct_ptr; simpl. - destruct a as [id' f']; simpl. - rewrite ZMap.gsspec. destruct (ZIndexed.eq b (genv_nextfun ge)). - apply PROP with id'. apply H. auto with coqlib. - assumption. - - unfold globalenv. rewrite add_variables_same_funs. intro. - exploit (H p.(prog_funct) empty_genv). auto with coqlib. - unfold find_funct_ptr; simpl. rewrite ZMap.gi. auto. - rewrite H0. auto. + intros. exploit find_funct_ptr_inversion; eauto. intros [id IN]. eauto. Qed. Theorem find_funct_prop: forall (P: F -> Prop) p v f, - (forall id f, In (id, f) (prog_funct p) -> P f) -> + (forall id f, In (id, Gfun f) (prog_defs p) -> P f) -> find_funct (globalenv p) v = Some f -> P f. Proof. - intros. exploit find_funct_inv; eauto. intros [b EQ]. subst v. - rewrite find_funct_find_funct_ptr in H0. - eapply find_funct_ptr_prop; eauto. -Qed. - -Theorem find_funct_ptr_inversion: - forall p b f, - find_funct_ptr (globalenv p) b = Some f -> - exists id, In (id, f) (prog_funct p). -Proof. - intros. pattern f. apply find_funct_ptr_prop with p b; auto. - intros. exists id; auto. -Qed. - -Theorem find_funct_inversion: - forall p v f, - find_funct (globalenv p) v = Some f -> - exists id, In (id, f) (prog_funct p). -Proof. - intros. pattern f. apply find_funct_prop with p v; auto. - intros. exists id; auto. -Qed. - -Theorem find_funct_ptr_negative: - forall p b f, - find_funct_ptr (globalenv p) b = Some f -> b < 0. -Proof. - unfold find_funct_ptr. intros. destruct (globalenv p). simpl in H. - exploit genv_funs_range0; eauto. omega. -Qed. - -Theorem find_var_info_positive: - forall p b v, - find_var_info (globalenv p) b = Some v -> b > 0. -Proof. - unfold find_var_info. intros. destruct (globalenv p). simpl in H. - exploit genv_vars_range0; eauto. omega. -Qed. - -Remark add_variables_symb_neg: - forall id b vl ge, - find_symbol (add_variables ge vl) id = Some b -> b < 0 -> - find_symbol ge id = Some b. -Proof. - induction vl; simpl; intros. auto. - exploit IHvl; eauto. unfold find_symbol; simpl. rewrite PTree.gsspec. - fold ident. destruct (peq id (a#1)); auto. intros. inv H1. - generalize (genv_nextvar_pos ge). intros. omegaContradiction. + intros. exploit find_funct_inversion; eauto. intros [id IN]. eauto. Qed. Theorem find_funct_ptr_symbol_inversion: forall p id b f, find_symbol (globalenv p) id = Some b -> find_funct_ptr (globalenv p) b = Some f -> - In (id, f) p.(prog_funct). -Proof. - intros until f. - - assert (forall fl ge, - find_symbol (add_functions ge fl) id = Some b -> - find_funct_ptr (add_functions ge fl) b = Some f -> - In (id, f) fl \/ (find_symbol ge id = Some b /\ find_funct_ptr ge b = Some f)). - induction fl; simpl; intros. + In (id, Gfun f) p.(prog_defs). +Proof. + intros until f. unfold globalenv, find_symbol, find_funct_ptr. apply add_globals_preserves. +(* preserves *) + intros. simpl in *. rewrite PTree.gsspec in H1. destruct (peq id id0). + inv H1. destruct g as [f1|v1]. rewrite ZMap.gss in H2. inv H2. auto. + exploit genv_funs_range; eauto. intros. omegaContradiction. + destruct g as [f1|v1]. rewrite ZMap.gso in H2. auto. + exploit genv_symb_range; eauto. unfold ZIndexed.t; omega. auto. - exploit IHfl; eauto. intros [A | [A B]]. auto. - destruct a as [id' f']. - unfold find_symbol in A; simpl in A. - unfold find_funct_ptr in B; simpl in B. - rewrite PTree.gsspec in A. destruct (peq id id'). inv A. - rewrite ZMap.gss in B. inv B. auto. - rewrite ZMap.gso in B. right; auto. - exploit genv_symb_range; eauto. unfold block, ZIndexed.t; omega. - - intros. assert (b < 0) by (eapply find_funct_ptr_negative; eauto). - unfold globalenv in *. rewrite add_variables_same_funs in H1. - exploit (H (prog_funct p) empty_genv). - eapply add_variables_symb_neg; eauto. auto. - intuition. unfold find_symbol in H3; simpl in H3. rewrite PTree.gempty in H3. discriminate. +(* initial *) + intros. simpl in *. rewrite PTree.gempty in H. discriminate. Qed. Theorem find_symbol_not_nullptr: @@ -553,7 +408,7 @@ Theorem find_symbol_not_nullptr: find_symbol (globalenv p) id = Some b -> b <> Mem.nullptr. Proof. intros until b. unfold find_symbol. destruct (globalenv p); simpl. - intros. exploit genv_symb_range0; eauto. intuition. + intros. exploit genv_symb_range0; eauto. unfold Mem.nullptr, block. omega. Qed. Theorem global_addresses_distinct: @@ -599,6 +454,16 @@ Proof. congruence. Qed. +Remark genv_next_add_globals: + forall gl ge, + genv_next (add_globals ge gl) = genv_next ge + Z_of_nat (length gl). +Proof. + induction gl; intros. + simpl. unfold block; omega. + simpl add_globals; simpl length; rewrite inj_S. + rewrite IHgl. simpl. unfold block; omega. +Qed. + (** * Construction of the initial memory state *) Section INITMEM. @@ -622,6 +487,18 @@ Proof. destruct i; simpl; try omega. generalize (Zle_max_r z 0). omega. Qed. +Function store_zeros (m: mem) (b: block) (p: Z) (n: Z) {wf (Zwf 0) n}: option mem := + if zle n 0 then Some m else + let n' := n - 1 in + match Mem.store Mint8unsigned m b p Vzero with + | Some m' => store_zeros m' b (p + 1) n' + | None => None + end. +Proof. + intros. red. omega. + apply Zwf_well_founded. +Qed. + Definition store_init_data (m: mem) (b: block) (p: Z) (id: init_data) : option mem := match id with | Init_int8 n => Mem.store Mint8unsigned m b p (Vint n) @@ -648,18 +525,6 @@ Fixpoint store_init_data_list (m: mem) (b: block) (p: Z) (idl: list init_data) end end. -Function store_zeros (m: mem) (b: block) (n: Z) {wf (Zwf 0) n}: option mem := - if zle n 0 then Some m else - let n' := n - 1 in - match Mem.store Mint8unsigned m b n' Vzero with - | Some m' => store_zeros m' b n' - | None => None - end. -Proof. - intros. red. omega. - apply Zwf_well_founded. -Qed. - Fixpoint init_data_list_size (il: list init_data) {struct il} : Z := match il with | nil => 0 @@ -671,37 +536,54 @@ Definition perm_globvar (gv: globvar V) : permission := else if gv.(gvar_readonly) then Readable else Writable. -Definition alloc_variable (m: mem) (idv: ident * globvar V) : option mem := - let init := idv#2.(gvar_init) in - let sz := init_data_list_size init in - let (m1, b) := Mem.alloc m 0 sz in - match store_zeros m1 b sz with - | None => None - | Some m2 => - match store_init_data_list m2 b 0 init with +Definition alloc_global (m: mem) (idg: ident * globdef F V): option mem := + match idg with + | (id, Gfun f) => + let (m1, b) := Mem.alloc m 0 1 in + Mem.drop_perm m1 b 0 1 Nonempty + | (id, Gvar v) => + let init := v.(gvar_init) in + let sz := init_data_list_size init in + let (m1, b) := Mem.alloc m 0 sz in + match store_zeros m1 b 0 sz with | None => None - | Some m3 => Mem.drop_perm m3 b 0 sz (perm_globvar idv#2) + | Some m2 => + match store_init_data_list m2 b 0 init with + | None => None + | Some m3 => Mem.drop_perm m3 b 0 sz (perm_globvar v) + end end end. -Fixpoint alloc_variables (m: mem) (vl: list (ident * globvar V)) - {struct vl} : option mem := - match vl with +Fixpoint alloc_globals (m: mem) (gl: list (ident * globdef F V)) + {struct gl} : option mem := + match gl with | nil => Some m - | v :: vl' => - match alloc_variable m v with + | g :: gl' => + match alloc_global m g with | None => None - | Some m' => alloc_variables m' vl' + | Some m' => alloc_globals m' gl' end end. -Lemma alloc_variables_app : forall vl1 vl2 m m1, - alloc_variables m vl1 = Some m1 -> - alloc_variables m1 vl2 = alloc_variables m (vl1 ++ vl2). +Lemma alloc_globals_app : forall gl1 gl2 m m1, + alloc_globals m gl1 = Some m1 -> + alloc_globals m1 gl2 = alloc_globals m (gl1 ++ gl2). +Proof. + induction gl1. + simpl. intros. inversion H; subst. auto. + simpl. intros. destruct (alloc_global m a); eauto. inversion H. +Qed. + +(** Next-block properties *) + +Remark store_zeros_nextblock: + forall m b p n m', store_zeros m b p n = Some m' -> Mem.nextblock m' = Mem.nextblock m. Proof. - induction vl1. - simpl. intros. inversion H; subst. auto. - simpl. intros. destruct (alloc_variable m a); eauto. inversion H. + intros until n. functional induction (store_zeros m b p n); intros. + inv H; auto. + rewrite IHo; eauto with mem. + congruence. Qed. Remark store_init_data_list_nextblock: @@ -714,71 +596,52 @@ Proof. caseEq (store_init_data m b p a); try congruence. intros. transitivity (Mem.nextblock m0). eauto. destruct a; simpl in H; try (eapply Mem.nextblock_store; eauto; fail). - congruence. - destruct (find_symbol ge i); try congruence. eapply Mem.nextblock_store; eauto. -Qed. - -Remark store_zeros_nextblock: - forall m b n m', store_zeros m b n = Some m' -> Mem.nextblock m' = Mem.nextblock m. -Proof. - intros until n. functional induction (store_zeros m b n); intros. - inv H; auto. - rewrite IHo; eauto with mem. congruence. + destruct (find_symbol ge i); try congruence. eapply Mem.nextblock_store; eauto. Qed. -Remark alloc_variable_nextblock: - forall v m m', - alloc_variable m v = Some m' -> +Remark alloc_global_nextblock: + forall g m m', + alloc_global m g = Some m' -> Mem.nextblock m' = Zsucc(Mem.nextblock m). Proof. - unfold alloc_variable. - intros until m'. - set (init := gvar_init v#2). - set (sz := init_data_list_size init). - caseEq (Mem.alloc m 0 sz). intros m1 b ALLOC. - caseEq (store_zeros m1 b sz); try congruence. intros m2 STZ. - caseEq (store_init_data_list m2 b 0 init); try congruence. intros m3 STORE. - caseEq (Mem.drop_perm m3 b 0 sz (perm_globvar v#2)); try congruence. intros m4 DROP REC. - inv REC; subst. - rewrite (Mem.nextblock_drop _ _ _ _ _ _ DROP). - rewrite (store_init_data_list_nextblock _ _ _ _ STORE). - rewrite (store_zeros_nextblock _ _ _ STZ). - rewrite (Mem.nextblock_alloc _ _ _ _ _ ALLOC). - auto. -Qed. - - -Remark alloc_variables_nextblock: - forall vl m m', - alloc_variables m vl = Some m' -> - Mem.nextblock m' = Mem.nextblock m + Z_of_nat(List.length vl). -Proof. - induction vl. + unfold alloc_global. intros. + destruct g as [id [f|v]]. + (* function *) + destruct (Mem.alloc m 0 1) as [m1 b]_eqn. + erewrite Mem.nextblock_drop; eauto. erewrite Mem.nextblock_alloc; eauto. + (* variable *) + set (init := gvar_init v) in *. + set (sz := init_data_list_size init) in *. + destruct (Mem.alloc m 0 sz) as [m1 b]_eqn. + destruct (store_zeros m1 b 0 sz) as [m2|]_eqn; try discriminate. + destruct (store_init_data_list m2 b 0 init) as [m3|]_eqn; try discriminate. + erewrite Mem.nextblock_drop; eauto. + erewrite store_init_data_list_nextblock; eauto. + erewrite store_zeros_nextblock; eauto. + erewrite Mem.nextblock_alloc; eauto. +Qed. + +Remark alloc_globals_nextblock: + forall gl m m', + alloc_globals m gl = Some m' -> + Mem.nextblock m' = Mem.nextblock m + Z_of_nat(List.length gl). +Proof. + induction gl. simpl; intros. inv H; unfold block; omega. - simpl length; rewrite inj_S; simpl. intros m m'. - unfold alloc_variable. - set (init := gvar_init a#2). - set (sz := init_data_list_size init). - caseEq (Mem.alloc m 0 sz). intros m1 b ALLOC. - caseEq (store_zeros m1 b sz); try congruence. intros m2 STZ. - caseEq (store_init_data_list m2 b 0 init); try congruence. intros m3 STORE. - caseEq (Mem.drop_perm m3 b 0 sz (perm_globvar a#2)); try congruence. intros m4 DROP REC. - rewrite (IHvl _ _ REC). - rewrite (Mem.nextblock_drop _ _ _ _ _ _ DROP). - rewrite (store_init_data_list_nextblock _ _ _ _ STORE). - rewrite (store_zeros_nextblock _ _ _ STZ). - rewrite (Mem.nextblock_alloc _ _ _ _ _ ALLOC). - unfold block in *; omega. + simpl length; rewrite inj_S; simpl; intros. + destruct (alloc_global m a) as [m1|]_eqn; try discriminate. + erewrite IHgl; eauto. erewrite alloc_global_nextblock; eauto. unfold block; omega. Qed. +(** Permissions *) Remark store_zeros_perm: - forall k prm b' q m b n m', - store_zeros m b n = Some m' -> + forall k prm b' q m b p n m', + store_zeros m b p n = Some m' -> (Mem.perm m b' q k prm <-> Mem.perm m' b' q k prm). Proof. - intros until n. functional induction (store_zeros m b n); intros. + intros until n. functional induction (store_zeros m b p n); intros. inv H; tauto. destruct (IHo _ H); intros. split; eauto with mem. congruence. @@ -793,56 +656,74 @@ Proof. intros. inv H. tauto. caseEq (store_init_data m b p a); try congruence. intros. rewrite <- (IHidl _ _ _ _ H0). - destruct a; simpl in H; split; eauto with mem. - inv H; auto. inv H; auto. - destruct (find_symbol ge i); try congruence. eauto with mem. - destruct (find_symbol ge i); try congruence. eauto with mem. + assert (forall chunk v, + Mem.store chunk m b p v = Some m0 -> + (Mem.perm m b' q k prm <-> Mem.perm m0 b' q k prm)). + intros; split; eauto with mem. + destruct a; simpl in H; eauto. + inv H; tauto. + destruct (find_symbol ge i). eauto. discriminate. Qed. -Remark alloc_variables_perm: - forall k prm b' q vl m m', - alloc_variables m vl = Some m' -> +Remark alloc_global_perm: + forall k prm b' q idg m m', + alloc_global m idg = Some m' -> Mem.valid_block m b' -> (Mem.perm m b' q k prm <-> Mem.perm m' b' q k prm). Proof. - induction vl. - simpl; intros. inv H. tauto. - intros until m'. simpl. unfold alloc_variable. - set (init := gvar_init a#2). - set (sz := init_data_list_size init). - caseEq (Mem.alloc m 0 sz). intros m1 b ALLOC. - caseEq (store_zeros m1 b sz); try congruence. intros m2 STZ. - caseEq (store_init_data_list m2 b 0 init); try congruence. intros m3 STORE. - caseEq (Mem.drop_perm m3 b 0 sz (perm_globvar a#2)); try congruence. intros m4 DROP REC VALID. + intros. destruct idg as [id [f|v]]; simpl in H. + (* function *) + destruct (Mem.alloc m 0 1) as [m1 b]_eqn. + assert (b' <> b). apply Mem.valid_not_valid_diff with m; eauto with mem. + split; intros. + eapply Mem.perm_drop_3; eauto. eapply Mem.perm_alloc_1; eauto. + eapply Mem.perm_alloc_4; eauto. eapply Mem.perm_drop_4; eauto. + (* variable *) + set (init := gvar_init v) in *. + set (sz := init_data_list_size init) in *. + destruct (Mem.alloc m 0 sz) as [m1 b]_eqn. + destruct (store_zeros m1 b 0 sz) as [m2|]_eqn; try discriminate. + destruct (store_init_data_list m2 b 0 init) as [m3|]_eqn; try discriminate. assert (b' <> b). apply Mem.valid_not_valid_diff with m; eauto with mem. - assert (VALID': Mem.valid_block m4 b'). - unfold Mem.valid_block. rewrite (Mem.nextblock_drop _ _ _ _ _ _ DROP). - rewrite (store_init_data_list_nextblock _ _ _ _ STORE). - rewrite (store_zeros_nextblock _ _ _ STZ). - change (Mem.valid_block m1 b'). eauto with mem. - rewrite <- (IHvl _ _ REC VALID'). split; intros. eapply Mem.perm_drop_3; eauto. - rewrite <- store_init_data_list_perm; [idtac|eauto]. - rewrite <- store_zeros_perm; [idtac|eauto]. - eauto with mem. - assert (Mem.perm m1 b' q k prm). - rewrite store_zeros_perm; [idtac|eauto]. - rewrite store_init_data_list_perm; [idtac|eauto]. - eapply Mem.perm_drop_4; eauto. - exploit Mem.perm_alloc_inv; eauto. rewrite zeq_false; auto. + erewrite <- store_init_data_list_perm; [idtac|eauto]. + erewrite <- store_zeros_perm; [idtac|eauto]. + eapply Mem.perm_alloc_1; eauto. + eapply Mem.perm_alloc_4; eauto. + erewrite store_zeros_perm; [idtac|eauto]. + erewrite store_init_data_list_perm; [idtac|eauto]. + eapply Mem.perm_drop_4; eauto. +Qed. + +Remark alloc_globals_perm: + forall k prm b' q gl m m', + alloc_globals m gl = Some m' -> + Mem.valid_block m b' -> + (Mem.perm m b' q k prm <-> Mem.perm m' b' q k prm). +Proof. + induction gl. + simpl; intros. inv H. tauto. + simpl; intros. destruct (alloc_global m a) as [m1|]_eqn; try discriminate. + erewrite alloc_global_perm; eauto. eapply IHgl; eauto. + unfold Mem.valid_block in *. erewrite alloc_global_nextblock; eauto. omega. Qed. +(** Data preservation properties *) + Remark store_zeros_outside: - forall m b n m', - store_zeros m b n = Some m' -> - forall chunk b' p, - b' <> b -> Mem.load chunk m' b' p = Mem.load chunk m b' p. + forall m b p n m', + store_zeros m b p n = Some m' -> + forall chunk b' p', + b' <> b \/ p' + size_chunk chunk <= p \/ p + n <= p' -> + Mem.load chunk m' b' p' = Mem.load chunk m b' p'. Proof. - intros until n. functional induction (store_zeros m b n); intros. + intros until n. functional induction (store_zeros m b p n); intros. inv H; auto. - rewrite IHo; auto. eapply Mem.load_store_other; eauto. - inv H. + transitivity (Mem.load chunk m' b' p'). + apply IHo. auto. unfold block in *; omega. + eapply Mem.load_store_other; eauto. simpl. unfold block in *; omega. + discriminate. Qed. Remark store_init_data_list_outside: @@ -854,12 +735,12 @@ Remark store_init_data_list_outside: Proof. induction il; simpl. intros; congruence. - intros until m'. caseEq (store_init_data m b p a); try congruence. - intros m1 A B chunk b' q C. transitivity (Mem.load chunk m1 b' q). + intros. destruct (store_init_data m b p a) as [m1|]_eqn; try congruence. + transitivity (Mem.load chunk m1 b' q). eapply IHil; eauto. generalize (init_data_size_pos a). intuition omega. - destruct a; simpl in A; + destruct a; simpl in Heqo; try (eapply Mem.load_store_other; eauto; intuition; fail). - congruence. + inv Heqo. auto. destruct (find_symbol ge i); try congruence. eapply Mem.load_store_other; eauto; intuition. Qed. @@ -904,10 +785,9 @@ Proof. induction il; simpl. auto. - intros until m'. caseEq (store_init_data m b p a); try congruence. - intros m1 B C. + intros. destruct (store_init_data m b p a) as [m1|]_eqn; try congruence. exploit IHil; eauto. intro D. - destruct a; simpl in B; intuition. + destruct a; simpl in Heqo; intuition. eapply (A Mint8unsigned (Vint i)); eauto. eapply (A Mint16unsigned (Vint i)); eauto. eapply (A Mint32 (Vint i)); eauto. @@ -917,36 +797,49 @@ Proof. eapply (A Mint32 (Vptr b0 i0)); eauto. Qed. -Remark load_alloc_variables: - forall chunk b p vl m m', - alloc_variables m vl = Some m' -> +Remark load_alloc_global: + forall chunk b p id g m m', + alloc_global m (id, g) = Some m' -> Mem.valid_block m b -> Mem.load chunk m' b p = Mem.load chunk m b p. Proof. - induction vl; simpl; intros until m'. - congruence. - unfold alloc_variable. - set (init := gvar_init a#2). - set (sz := init_data_list_size init). - caseEq (Mem.alloc m 0 sz). intros m1 b1 ALLOC. - caseEq (store_zeros m1 b1 sz); try congruence. intros m2 STZ. - caseEq (store_init_data_list m2 b1 0 init); try congruence. intros m3 STORE. - caseEq (Mem.drop_perm m3 b1 0 sz (perm_globvar a#2)); try congruence. intros m4 DROP REC VALID. - assert (b <> b1). apply Mem.valid_not_valid_diff with m; eauto with mem. - transitivity (Mem.load chunk m4 b p). - apply IHvl; auto. red. - rewrite (Mem.nextblock_drop _ _ _ _ _ _ DROP). - rewrite (store_init_data_list_nextblock _ _ _ _ STORE). - rewrite (store_zeros_nextblock _ _ _ STZ). - change (Mem.valid_block m1 b). eauto with mem. - transitivity (Mem.load chunk m3 b p). + intros. destruct g as [f|v]; simpl in H. + (* function *) + destruct (Mem.alloc m 0 1) as [m1 b']_eqn. + assert (b <> b'). apply Mem.valid_not_valid_diff with m; eauto with mem. + transitivity (Mem.load chunk m1 b p). eapply Mem.load_drop; eauto. + eapply Mem.load_alloc_unchanged; eauto. + (* variable *) + set (init := gvar_init v) in *. + set (sz := init_data_list_size init) in *. + destruct (Mem.alloc m 0 sz) as [m1 b']_eqn. + destruct (store_zeros m1 b' 0 sz) as [m2|]_eqn; try discriminate. + destruct (store_init_data_list m2 b' 0 init) as [m3|]_eqn; try discriminate. + assert (b <> b'). apply Mem.valid_not_valid_diff with m; eauto with mem. + transitivity (Mem.load chunk m3 b p). + eapply Mem.load_drop; eauto. transitivity (Mem.load chunk m2 b p). - eapply store_init_data_list_outside; eauto. + eapply store_init_data_list_outside; eauto. transitivity (Mem.load chunk m1 b p). eapply store_zeros_outside; eauto. eapply Mem.load_alloc_unchanged; eauto. -Qed. +Qed. + +Remark load_alloc_globals: + forall chunk b p gl m m', + alloc_globals m gl = Some m' -> + Mem.valid_block m b -> + Mem.load chunk m' b p = Mem.load chunk m b p. +Proof. + induction gl; simpl; intros. + congruence. + destruct (alloc_global m a) as [m''|]_eqn; try discriminate. + transitivity (Mem.load chunk m'' b p). + apply IHgl; auto. unfold Mem.valid_block in *. + erewrite alloc_global_nextblock; eauto. omega. + destruct a as [id g]. eapply load_alloc_global; eauto. +Qed. Remark load_store_init_data_invariant: forall m m' b, @@ -967,114 +860,147 @@ Definition variables_initialized (g: t) (m: mem) := 0 <= ofs < init_data_list_size gv.(gvar_init) /\ perm_order (perm_globvar gv) p) /\ (gv.(gvar_volatile) = false -> load_store_init_data m b 0 gv.(gvar_init)). -Lemma alloc_variable_initialized: - forall g m id v m', - genv_nextvar g = Mem.nextblock m -> - alloc_variable m (id, v) = Some m' -> - variables_initialized g m -> - variables_initialized (add_variable g (id, v)) m' - /\ genv_nextvar (add_variable g (id,v)) = Mem.nextblock m'. -Proof. - intros. revert H0. unfold alloc_variable. simpl. - set (il := gvar_init v). - set (sz := init_data_list_size il). - caseEq (Mem.alloc m 0 sz). intros m1 b1 ALLOC. - caseEq (store_zeros m1 b1 sz); try congruence. intros m2 ZEROS. - caseEq (store_init_data_list m2 b1 0 il); try congruence. intros m3 INIT DROP. - exploit Mem.nextblock_alloc; eauto. intros NB1. - assert (Mem.nextblock m' = Mem.nextblock m1). - rewrite (Mem.nextblock_drop _ _ _ _ _ _ DROP). - rewrite (store_init_data_list_nextblock _ _ _ _ INIT). - eapply store_zeros_nextblock; eauto. - exploit Mem.alloc_result; eauto. intro RES. - split. - (* var-init *) - red; intros. revert H2. - unfold add_variable, find_var_info; simpl. - rewrite H; rewrite <- RES. - rewrite ZMap.gsspec. destruct (ZIndexed.eq b b1); intros VI. - (* new var *) - injection VI; intro EQ. subst b gv. clear VI. - fold il. fold sz. - split. red; intros. eapply Mem.perm_drop_1; eauto. - split. intros. - assert (0 <= ofs < sz). - eapply Mem.perm_alloc_3; eauto. - rewrite store_zeros_perm; [idtac|eauto]. - rewrite store_init_data_list_perm; [idtac|eauto]. - eapply Mem.perm_drop_4; eauto. - split; auto. eapply Mem.perm_drop_2; eauto. +Definition functions_initialized (g: t) (m: mem) := + forall b fd, + find_funct_ptr g b = Some fd -> + Mem.perm m b 0 Cur Nonempty + /\ (forall ofs k p, Mem.perm m b ofs k p -> ofs = 0 /\ perm_order Nonempty p). + +Lemma alloc_global_initialized: + forall ge m id g m', + genv_next ge = Mem.nextblock m -> + alloc_global m (id, g) = Some m' -> + variables_initialized ge m -> + functions_initialized ge m -> + variables_initialized (add_global ge (id, g)) m' + /\ functions_initialized (add_global ge (id, g)) m' + /\ genv_next (add_global ge (id, g)) = Mem.nextblock m'. +Proof. intros. - apply load_store_init_data_invariant with m3. - intros. eapply Mem.load_drop; eauto. right; right; right. - unfold perm_globvar. destruct (gvar_volatile v); try discriminate. - destruct (gvar_readonly v); auto with mem. + exploit alloc_global_nextblock; eauto. intros NB. split. +(* variables-initialized *) + destruct g as [f|v]. +(* function *) + red; intros. unfold find_var_info in H3. simpl in H3. + exploit H1; eauto. intros [A [B C]]. + assert (D: Mem.valid_block m b). + red. exploit genv_vars_range; eauto. rewrite H; omega. + split. red; intros. erewrite <- alloc_global_perm; eauto. + split. intros. eapply B. erewrite alloc_global_perm; eauto. + intros. apply load_store_init_data_invariant with m; auto. + intros. eapply load_alloc_global; eauto. +(* variable *) + red; intros. unfold find_var_info in H3. simpl in H3. rewrite ZMap.gsspec in H3. + destruct (ZIndexed.eq b (genv_next ge0)). + (* same *) + inv H3. simpl in H0. + set (init := gvar_init gv) in *. + set (sz := init_data_list_size init) in *. + destruct (Mem.alloc m 0 sz) as [m1 b']_eqn. + destruct (store_zeros m1 b' 0 sz) as [m2|]_eqn; try discriminate. + destruct (store_init_data_list m2 b' 0 init) as [m3|]_eqn; try discriminate. + exploit Mem.alloc_result; eauto. intro RES. + replace (genv_next ge0) with b' by congruence. + split. red; intros. eapply Mem.perm_drop_1; eauto. + split. intros. + assert (0 <= ofs < sz). + eapply Mem.perm_alloc_3; eauto. + erewrite store_zeros_perm; [idtac|eauto]. + erewrite store_init_data_list_perm; [idtac|eauto]. + eapply Mem.perm_drop_4; eauto. + split. auto. eapply Mem.perm_drop_2; eauto. + intros. apply load_store_init_data_invariant with m3. + intros. eapply Mem.load_drop; eauto. + right; right; right. unfold perm_globvar. rewrite H3. + destruct (gvar_readonly gv); auto with mem. eapply store_init_data_list_charact; eauto. - (* older vars *) + (* older var *) exploit H1; eauto. intros [A [B C]]. - split. red; intros. eapply Mem.perm_drop_3; eauto. - rewrite <- store_init_data_list_perm; [idtac|eauto]. - rewrite <- store_zeros_perm; [idtac|eauto]. - eapply Mem.perm_alloc_1; eauto. - split. intros. eapply B. - eapply Mem.perm_alloc_4; eauto. - rewrite store_zeros_perm; [idtac|eauto]. - rewrite store_init_data_list_perm; [idtac|eauto]. - eapply Mem.perm_drop_4; eauto. - intros. apply load_store_init_data_invariant with m; auto. - intros. transitivity (Mem.load chunk m3 b ofs). - eapply Mem.load_drop; eauto. - transitivity (Mem.load chunk m2 b ofs). - eapply store_init_data_list_outside; eauto. - transitivity (Mem.load chunk m1 b ofs). - eapply store_zeros_outside; eauto. - eapply Mem.load_alloc_unchanged; eauto. - red. exploit genv_vars_range; eauto. rewrite <- H. omega. - rewrite H0; rewrite NB1; rewrite H; auto. -Qed. - -Lemma alloc_variables_initialized: - forall vl g m m', - genv_nextvar g = Mem.nextblock m -> - alloc_variables m vl = Some m' -> - variables_initialized g m -> - variables_initialized (add_variables g vl) m'. -Proof. - induction vl; simpl; intros. + assert (D: Mem.valid_block m b). + red. exploit genv_vars_range; eauto. rewrite H; omega. + split. red; intros. erewrite <- alloc_global_perm; eauto. + split. intros. eapply B. erewrite alloc_global_perm; eauto. + intros. apply load_store_init_data_invariant with m; auto. + intros. eapply load_alloc_global; eauto. +(* functions-initialized *) + split. destruct g as [f|v]. +(* function *) + red; intros. unfold find_funct_ptr in H3. simpl in H3. rewrite ZMap.gsspec in H3. + destruct (ZIndexed.eq b (genv_next ge0)). + (* same *) + inv H3. simpl in H0. + destruct (Mem.alloc m 0 1) as [m1 b']_eqn. + exploit Mem.alloc_result; eauto. intro RES. + replace (genv_next ge0) with b' by congruence. + split. eapply Mem.perm_drop_1; eauto. omega. + intros. + assert (0 <= ofs < 1). + eapply Mem.perm_alloc_3; eauto. + eapply Mem.perm_drop_4; eauto. + split. omega. eapply Mem.perm_drop_2; eauto. + (* older function *) + exploit H2; eauto. intros [A B]. + assert (D: Mem.valid_block m b). + red. exploit genv_funs_range; eauto. rewrite H; omega. + split. erewrite <- alloc_global_perm; eauto. + intros. eapply B. erewrite alloc_global_perm; eauto. +(* variables *) + red; intros. unfold find_funct_ptr in H3. simpl in H3. + exploit H2; eauto. intros [A B]. + assert (D: Mem.valid_block m b). + red. exploit genv_funs_range; eauto. rewrite H; omega. + split. erewrite <- alloc_global_perm; eauto. + intros. eapply B. erewrite alloc_global_perm; eauto. +(* nextblock *) + rewrite NB. simpl. rewrite H. unfold block; omega. +Qed. + +Lemma alloc_globals_initialized: + forall gl ge m m', + genv_next ge = Mem.nextblock m -> + alloc_globals m gl = Some m' -> + variables_initialized ge m -> + functions_initialized ge m -> + variables_initialized (add_globals ge gl) m' /\ functions_initialized (add_globals ge gl) m'. +Proof. + induction gl; simpl; intros. inv H0; auto. - destruct (alloc_variable m a) as [m1|]_eqn; try discriminate. - destruct a as [id gv]. - exploit alloc_variable_initialized; eauto. intros [P Q]. - eapply IHvl; eauto. + destruct a as [id g]. destruct (alloc_global m (id, g)) as [m1|]_eqn; try discriminate. + exploit alloc_global_initialized; eauto. intros [P [Q R]]. + eapply IHgl; eauto. Qed. End INITMEM. Definition init_mem (p: program F V) := - alloc_variables (globalenv p) Mem.empty p.(prog_vars). + alloc_globals (globalenv p) Mem.empty p.(prog_defs). + +Lemma init_mem_genv_next: forall p m, + init_mem p = Some m -> + genv_next (globalenv p) = Mem.nextblock m. +Proof. + unfold init_mem; intros. + exploit alloc_globals_nextblock; eauto. rewrite Mem.nextblock_empty. intro. + generalize (genv_next_add_globals (prog_defs p) empty_genv). + fold (globalenv p). simpl genv_next. intros. congruence. +Qed. Theorem find_symbol_not_fresh: forall p id b m, init_mem p = Some m -> find_symbol (globalenv p) id = Some b -> Mem.valid_block m b. Proof. - unfold init_mem; intros. - exploit alloc_variables_nextblock; eauto. rewrite Mem.nextblock_empty. intro. - exploit genv_symb_range; eauto. intros. - generalize (add_variables_nextvar (prog_vars p) (add_functions empty_genv (prog_funct p))). - rewrite add_functions_nextvar. simpl genv_nextvar. intro. - red. rewrite H1. rewrite <- H3. intuition. + intros. red. erewrite <- init_mem_genv_next; eauto. + exploit genv_symb_range; eauto. omega. Qed. -Lemma init_mem_genv_vars : forall p m, - init_mem p = Some m -> - genv_nextvar (globalenv p) = Mem.nextblock m. +Theorem find_funct_ptr_not_fresh: + forall p b f m, + init_mem p = Some m -> + find_funct_ptr (globalenv p) b = Some f -> Mem.valid_block m b. Proof. - clear. unfold globalenv, init_mem. intros. - exploit alloc_variables_nextblock; eauto. - simpl (Mem.nextblock Mem.empty). - rewrite add_variables_nextvar. rewrite add_functions_nextvar. - simpl (genv_nextvar empty_genv). auto. + intros. red. erewrite <- init_mem_genv_next; eauto. + exploit genv_funs_range; eauto. omega. Qed. Theorem find_var_info_not_fresh: @@ -1082,12 +1008,8 @@ Theorem find_var_info_not_fresh: init_mem p = Some m -> find_var_info (globalenv p) b = Some gv -> Mem.valid_block m b. Proof. - unfold init_mem; intros. - exploit alloc_variables_nextblock; eauto. rewrite Mem.nextblock_empty. intro. - exploit genv_vars_range; eauto. intros. - generalize (add_variables_nextvar (prog_vars p) (add_functions empty_genv (prog_funct p))). - rewrite add_functions_nextvar. simpl genv_nextvar. intro. - red. rewrite H1. rewrite <- H3. intuition. + intros. red. erewrite <- init_mem_genv_next; eauto. + exploit genv_vars_range; eauto. omega. Qed. Theorem init_mem_characterization: @@ -1099,10 +1021,23 @@ Theorem init_mem_characterization: 0 <= ofs < init_data_list_size gv.(gvar_init) /\ perm_order (perm_globvar gv) p) /\ (gv.(gvar_volatile) = false -> load_store_init_data (globalenv p) m b 0 gv.(gvar_init)). Proof. - intros. eapply alloc_variables_initialized; eauto. - rewrite add_functions_nextvar; auto. - red; intros. exploit genv_vars_range; eauto. rewrite add_functions_nextvar. - simpl. intros. omegaContradiction. + intros. eapply alloc_globals_initialized; eauto. + rewrite Mem.nextblock_empty. auto. + red; intros. exploit genv_vars_range; eauto. simpl. intros. omegaContradiction. + red; intros. exploit genv_funs_range; eauto. simpl. intros. omegaContradiction. +Qed. + +Theorem init_mem_characterization_2: + forall p b fd m, + find_funct_ptr (globalenv p) b = Some fd -> + init_mem p = Some m -> + Mem.perm m b 0 Cur Nonempty + /\ (forall ofs k p, Mem.perm m b ofs k p -> ofs = 0 /\ perm_order Nonempty p). +Proof. + intros. unfold init_mem in H0. eapply alloc_globals_initialized; eauto. + rewrite Mem.nextblock_empty. auto. + red; intros. exploit genv_vars_range; eauto. simpl. intros. omegaContradiction. + red; intros. exploit genv_funs_range; eauto. simpl. intros. omegaContradiction. Qed. (** ** Compatibility with memory injections *) @@ -1113,6 +1048,19 @@ Variable ge: t. Variable thr: block. Hypothesis symb_inject: forall id b, find_symbol ge id = Some b -> b < thr. +Lemma store_zeros_neutral: + forall m b p n m', + Mem.inject_neutral thr m -> + b < thr -> + store_zeros m b p n = Some m' -> + Mem.inject_neutral thr m'. +Proof. + intros until n. functional induction (store_zeros m b p n); intros. + inv H1; auto. + apply IHo; auto. eapply Mem.store_inject_neutral; eauto. constructor. + inv H1. +Qed. + Lemma store_init_data_neutral: forall m b p id m', Mem.inject_neutral thr m -> @@ -1122,7 +1070,7 @@ Lemma store_init_data_neutral: Proof. intros. destruct id; simpl in H1; try (eapply Mem.store_inject_neutral; eauto; fail). - inv H1; auto. + congruence. revert H1. caseEq (find_symbol ge i); try congruence. intros b' FS ST. eapply Mem.store_inject_neutral; eauto. econstructor. unfold Mem.flat_inj. apply zlt_true; eauto. @@ -1143,54 +1091,46 @@ Proof. eapply IHidl. eapply store_init_data_neutral; eauto. auto. eauto. Qed. -Lemma store_zeros_neutral: - forall m b n m', - Mem.inject_neutral thr m -> - b < thr -> - store_zeros m b n = Some m' -> - Mem.inject_neutral thr m'. -Proof. - intros until n. functional induction (store_zeros m b n); intros. - inv H1; auto. - apply IHo; auto. eapply Mem.store_inject_neutral; eauto. constructor. - inv H1. -Qed. - -Lemma alloc_variable_neutral: - forall id m m', - alloc_variable ge m id = Some m' -> +Lemma alloc_global_neutral: + forall idg m m', + alloc_global ge m idg = Some m' -> Mem.inject_neutral thr m -> Mem.nextblock m < thr -> Mem.inject_neutral thr m'. Proof. - intros until m'. unfold alloc_variable. - set (init := gvar_init id#2). - set (sz := init_data_list_size init). - caseEq (Mem.alloc m 0 sz); try congruence. intros m1 b ALLOC. - caseEq (store_zeros m1 b sz); try congruence. intros m2 STZ. - caseEq (store_init_data_list ge m2 b 0 init); try congruence. - intros m3 STORE DROP NEUTRAL NEXT. - assert (b < thr). rewrite (Mem.alloc_result _ _ _ _ _ ALLOC). auto. + intros. destruct idg as [id [f|v]]; simpl in H. + (* function *) + destruct (Mem.alloc m 0 1) as [m1 b]_eqn. + assert (b < thr). rewrite (Mem.alloc_result _ _ _ _ _ Heqp). auto. + eapply Mem.drop_inject_neutral; eauto. + eapply Mem.alloc_inject_neutral; eauto. + (* variable *) + set (init := gvar_init v) in *. + set (sz := init_data_list_size init) in *. + destruct (Mem.alloc m 0 sz) as [m1 b]_eqn. + destruct (store_zeros m1 b 0 sz) as [m2|]_eqn; try discriminate. + destruct (store_init_data_list ge m2 b 0 init) as [m3|]_eqn; try discriminate. + assert (b < thr). rewrite (Mem.alloc_result _ _ _ _ _ Heqp). auto. eapply Mem.drop_inject_neutral; eauto. eapply store_init_data_list_neutral with (m := m2) (b := b); eauto. eapply store_zeros_neutral with (m := m1); eauto. eapply Mem.alloc_inject_neutral; eauto. Qed. -Lemma alloc_variables_neutral: - forall idl m m', - alloc_variables ge m idl = Some m' -> +Lemma alloc_globals_neutral: + forall gl m m', + alloc_globals ge m gl = Some m' -> Mem.inject_neutral thr m -> Mem.nextblock m' <= thr -> Mem.inject_neutral thr m'. Proof. - induction idl; simpl. + induction gl; simpl. intros. congruence. - intros until m'. caseEq (alloc_variable ge m a); try congruence. intros. - assert (Mem.nextblock m' = Mem.nextblock m + Z_of_nat(length (a :: idl))). - eapply alloc_variables_nextblock with ge. simpl. rewrite H. auto. + intros until m'. caseEq (alloc_global ge m a); try congruence. intros. + assert (Mem.nextblock m' = Mem.nextblock m + Z_of_nat(length (a :: gl))). + eapply alloc_globals_nextblock with ge. simpl. rewrite H. auto. simpl length in H3. rewrite inj_S in H3. - exploit alloc_variable_neutral; eauto. unfold block in *; omega. + exploit alloc_global_neutral; eauto. unfold block in *; omega. Qed. End INITMEM_INJ. @@ -1202,7 +1142,7 @@ Theorem initmem_inject: Proof. unfold init_mem; intros. apply Mem.neutral_inject. - eapply alloc_variables_neutral; eauto. + eapply alloc_globals_neutral; eauto. intros. exploit find_symbol_not_fresh; eauto. apply Mem.empty_inject_neutral. omega. @@ -1213,6 +1153,22 @@ Section INITMEM_AUGMENT_INJ. Variable ge: t. Variable thr: block. +Lemma store_zeros_augment: + forall m1 m2 b p n m2', + Mem.inject (Mem.flat_inj thr) m1 m2 -> + b >= thr -> + store_zeros m2 b p n = Some m2' -> + Mem.inject (Mem.flat_inj thr) m1 m2'. +Proof. + intros until n. functional induction (store_zeros m2 b p n); intros. + inv H1; auto. + apply IHo; auto. exploit Mem.store_outside_inject; eauto. simpl. + intros. exfalso. unfold Mem.flat_inj in H2. destruct (zlt b' thr). + inversion H2; subst; omega. + discriminate. + inv H1. +Qed. + Lemma store_init_data_augment: forall m1 m2 b p id m2', Mem.inject (Mem.flat_inj thr) m1 m2 -> @@ -1228,7 +1184,7 @@ Proof. intros. unfold Mem.flat_inj in H0. destruct (zlt b' thr); inversion H0; subst. omega. destruct id; simpl in ST; try (eapply P; eauto; fail). - inv ST; auto. + congruence. revert ST. caseEq (find_symbol ge i); try congruence. intros; eapply P; eauto. Qed. @@ -1246,59 +1202,49 @@ Proof. eapply IHidl. eapply store_init_data_augment; eauto. auto. eauto. Qed. -Lemma store_zeros_augment: - forall m1 m2 b n m2', - Mem.inject (Mem.flat_inj thr) m1 m2 -> - b >= thr -> - store_zeros m2 b n = Some m2' -> - Mem.inject (Mem.flat_inj thr) m1 m2'. -Proof. - intros until n. functional induction (store_zeros m2 b n); intros. - inv H1; auto. - apply IHo; auto. exploit Mem.store_outside_inject; eauto. simpl. - intros. exfalso. unfold Mem.flat_inj in H2. destruct (zlt b' thr). - inversion H2; subst; omega. - discriminate. - inv H1. -Qed. - -Lemma alloc_variable_augment: - forall id m1 m2 m2', - alloc_variable ge m2 id = Some m2' -> +Lemma alloc_global_augment: + forall idg m1 m2 m2', + alloc_global ge m2 idg = Some m2' -> Mem.inject (Mem.flat_inj thr) m1 m2 -> Mem.nextblock m2 >= thr -> Mem.inject (Mem.flat_inj thr) m1 m2'. Proof. - intros until m2'. unfold alloc_variable. - set (sz := init_data_list_size (gvar_init id#2)). - caseEq (Mem.alloc m2 0 sz); try congruence. intros m3 b ALLOC. - caseEq (store_zeros m3 b sz); try congruence. intros m4 STZ. - caseEq (store_init_data_list ge m4 b 0 (gvar_init id#2)); try congruence. - intros m5 STORE DROP INJ NEXT. - assert (b >= thr). - pose proof (Mem.fresh_block_alloc _ _ _ _ _ ALLOC). - unfold Mem.valid_block in H. unfold block in *; omega. - eapply Mem.drop_outside_inject. 2: eauto. - eapply store_init_data_list_augment. 2: eauto. 2: eauto. - eapply store_zeros_augment. 2: eauto. 2: eauto. - eapply Mem.alloc_right_inject; eauto. - intros. unfold Mem.flat_inj in H0. destruct (zlt b' thr); inversion H0. + intros. destruct idg as [id [f|v]]; simpl in H. + (* function *) + destruct (Mem.alloc m2 0 1) as [m3 b]_eqn. + assert (b >= thr). rewrite (Mem.alloc_result _ _ _ _ _ Heqp). auto. + eapply Mem.drop_outside_inject. 2: eauto. + eapply Mem.alloc_right_inject; eauto. + intros. unfold Mem.flat_inj in H3. destruct (zlt b' thr); inversion H3. + subst; exfalso; omega. + (* variable *) + set (init := gvar_init v) in *. + set (sz := init_data_list_size init) in *. + destruct (Mem.alloc m2 0 sz) as [m3 b]_eqn. + destruct (store_zeros m3 b 0 sz) as [m4|]_eqn; try discriminate. + destruct (store_init_data_list ge m4 b 0 init) as [m5|]_eqn; try discriminate. + assert (b >= thr). rewrite (Mem.alloc_result _ _ _ _ _ Heqp). auto. + eapply Mem.drop_outside_inject. 2: eauto. + eapply store_init_data_list_augment. 3: eauto. 2: eauto. + eapply store_zeros_augment. 3: eauto. 2: eauto. + eapply Mem.alloc_right_inject; eauto. + intros. unfold Mem.flat_inj in H3. destruct (zlt b' thr); inversion H3. subst; exfalso; omega. Qed. -Lemma alloc_variables_augment: - forall idl m1 m2 m2', - alloc_variables ge m2 idl = Some m2' -> +Lemma alloc_globals_augment: + forall gl m1 m2 m2', + alloc_globals ge m2 gl = Some m2' -> Mem.inject (Mem.flat_inj thr) m1 m2 -> Mem.nextblock m2 >= thr -> Mem.inject (Mem.flat_inj thr) m1 m2'. Proof. - induction idl; simpl. + induction gl; simpl. intros. congruence. - intros until m2'. caseEq (alloc_variable ge m2 a); try congruence. intros. - eapply IHidl with (m2 := m); eauto. - eapply alloc_variable_augment; eauto. - rewrite (alloc_variable_nextblock _ _ _ H). + intros until m2'. caseEq (alloc_global ge m2 a); try congruence. intros. + eapply IHgl with (m2 := m); eauto. + eapply alloc_global_augment; eauto. + rewrite (alloc_global_nextblock _ _ _ H). unfold block in *; omega. Qed. @@ -1321,216 +1267,156 @@ Inductive match_globvar: globvar V -> globvar W -> Prop := match_varinfo info1 info2 -> match_globvar (mkglobvar info1 init ro vo) (mkglobvar info2 init ro vo). -Record match_genvs (new_functs : list (ident * B)) (new_vars : list (ident * globvar W)) +Record match_genvs (new_globs : list (ident * globdef B W)) (ge1: t A V) (ge2: t B W): Prop := { - mge_nextfun: genv_nextfun ge2 = genv_nextfun ge1 - Z_of_nat(length new_functs); - mge_nextvar: genv_nextvar ge2 = genv_nextvar ge1 + Z_of_nat(length new_vars); - mge_symb: forall id, ~ In id ((funct_names new_functs) ++ (var_names new_vars)) -> + mge_next: + genv_next ge2 = genv_next ge1 + Z_of_nat(length new_globs); + mge_symb: + forall id, ~ In id (map fst new_globs) -> PTree.get id (genv_symb ge2) = PTree.get id (genv_symb ge1); mge_funs: forall b f, ZMap.get b (genv_funs ge1) = Some f -> exists tf, ZMap.get b (genv_funs ge2) = Some tf /\ match_fun f tf; mge_rev_funs: forall b tf, ZMap.get b (genv_funs ge2) = Some tf -> - if zlt (genv_nextfun ge1) b then + if zlt b (genv_next ge1) then exists f, ZMap.get b (genv_funs ge1) = Some f /\ match_fun f tf else - In tf (map (@snd ident B) new_functs); + In (Gfun tf) (map snd new_globs); mge_vars: forall b v, ZMap.get b (genv_vars ge1) = Some v -> exists tv, ZMap.get b (genv_vars ge2) = Some tv /\ match_globvar v tv; mge_rev_vars: forall b tv, ZMap.get b (genv_vars ge2) = Some tv -> - if zlt b (genv_nextvar ge1) then + if zlt b (genv_next ge1) then exists v, ZMap.get b (genv_vars ge1) = Some v /\ match_globvar v tv else - In tv (map (@snd ident (globvar W)) new_vars) + In (Gvar tv) (map snd new_globs) }. -Lemma add_function_match: - forall ge1 ge2 id f1 f2, - match_genvs nil nil ge1 ge2 -> - match_fun f1 f2 -> - match_genvs nil nil (add_function ge1 (id, f1)) (add_function ge2 (id, f2)). +Lemma add_global_match: + forall ge1 ge2 idg1 idg2, + match_genvs nil ge1 ge2 -> + match_globdef match_fun match_varinfo idg1 idg2 -> + match_genvs nil (add_global ge1 idg1) (add_global ge2 idg2). Proof. intros. destruct H. - simpl in mge_nextfun0. rewrite Zminus_0_r in mge_nextfun0. - simpl in mge_nextvar0. rewrite Zplus_0_r in mge_nextvar0. - constructor; simpl. - rewrite Zminus_0_r. congruence. + simpl in mge_next0. rewrite Zplus_0_r in mge_next0. + inv H0. +(* two functions *) + constructor; simpl. rewrite Zplus_0_r. congruence. - intros. rewrite mge_nextfun0. - repeat rewrite PTree.gsspec. destruct (peq id0 id); auto. - rewrite mge_nextfun0. intros. rewrite ZMap.gsspec in H. rewrite ZMap.gsspec. - destruct (ZIndexed.eq b (genv_nextfun ge1)). + intros. rewrite mge_next0. + repeat rewrite PTree.gsspec. destruct (peq id0 id); auto. + rewrite mge_next0. intros. rewrite ZMap.gsspec in H0. rewrite ZMap.gsspec. + destruct (ZIndexed.eq b (genv_next ge1)). exists f2; split; congruence. eauto. - rewrite mge_nextfun0. intros. rewrite ZMap.gsspec in H. rewrite ZMap.gsspec. - destruct (ZIndexed.eq b (genv_nextfun ge1)). - subst b. destruct (zlt (genv_nextfun ge1 - 1) (genv_nextfun ge1)). - exists f1; split; congruence. omega. - pose proof (mge_rev_funs0 b tf H). - destruct (zlt (genv_nextfun ge1) b); - destruct (zlt (genv_nextfun ge1 - 1) b). auto. omega. exfalso; omega. intuition. - auto. - auto. -Qed. - -Lemma add_functions_match: - forall fl1 fl2, list_forall2 (match_funct_entry match_fun) fl1 fl2 -> - forall ge1 ge2, match_genvs nil nil ge1 ge2 -> - match_genvs nil nil (add_functions ge1 fl1) (add_functions ge2 fl2). -Proof. - induction 1; intros; simpl. - auto. - destruct a1 as [id1 f1]; destruct b1 as [id2 f2]. - destruct H. subst. apply IHlist_forall2. apply add_function_match; auto. -Qed. - -Lemma add_function_augment_match: - forall new_functs new_vars ge1 ge2 id f2, - match_genvs new_functs new_vars ge1 ge2 -> - match_genvs (new_functs++((id,f2)::nil)) new_vars ge1 (add_function ge2 (id, f2)). -Proof. - intros. destruct H. constructor; simpl. - rewrite mge_nextfun0. rewrite app_length. - simpl. rewrite inj_plus. rewrite inj_S. rewrite inj_0. unfold block; omega. (* painful! *) - auto. - intros. unfold funct_names in H. rewrite map_app in H. rewrite in_app in H. rewrite in_app in H. simpl in H. - destruct (peq id id0). subst. intuition. rewrite PTree.gso. - apply mge_symb0. intro. apply H. rewrite in_app in H0. inversion H0; intuition. intuition. - intros. rewrite ZMap.gso. auto. - rewrite mge_nextfun0. pose proof (genv_funs_range ge1 b H). intro; subst; omega. - intros. rewrite ZMap.gsspec in H. - destruct (ZIndexed.eq b (genv_nextfun ge2)). - destruct (zlt (genv_nextfun ge1) b). - exfalso. rewrite mge_nextfun0 in e. unfold block; omega. - rewrite map_app. rewrite in_app. simpl. inversion H; intuition. - pose proof (mge_rev_funs0 b tf H). - destruct (zlt (genv_nextfun ge1) b). - auto. - rewrite map_app. rewrite in_app. intuition. - auto. - auto. -Qed. - - -Lemma add_functions_augment_match: - forall fl new_functs new_vars ge1 ge2, - match_genvs new_functs new_vars ge1 ge2 -> - match_genvs (new_functs++fl) new_vars ge1 (add_functions ge2 fl). -Proof. - induction fl; simpl. - intros. rewrite app_nil_r. auto. - intros. replace (new_functs ++ a :: fl) with ((new_functs ++ (a::nil)) ++ fl) - by (rewrite app_ass; auto). - apply IHfl. destruct a. apply add_function_augment_match. auto. -Qed. - - -Lemma add_variable_match: - forall new_functs ge1 ge2 id v1 v2, - match_genvs new_functs nil ge1 ge2 -> - match_globvar v1 v2 -> - match_genvs new_functs nil (add_variable ge1 (id, v1)) (add_variable ge2 (id, v2)). -Proof. - intros. destruct H. - simpl in mge_nextvar0. rewrite Zplus_0_r in mge_nextvar0. - constructor; simpl. - auto. - rewrite Zplus_0_r. rewrite mge_nextvar0. auto. - intros. rewrite mge_nextvar0. - repeat rewrite PTree.gsspec. destruct (peq id0 id); auto. - auto. - auto. - rewrite mge_nextvar0. intros. rewrite ZMap.gsspec in H. rewrite ZMap.gsspec. - destruct (ZIndexed.eq b (genv_nextvar ge1)). - exists v2; split; congruence. - eauto. - rewrite mge_nextvar0. intros. rewrite ZMap.gsspec in H. rewrite ZMap.gsspec. - destruct (ZIndexed.eq b (genv_nextvar ge1)). - subst b. inversion H; subst. - destruct (zlt (genv_nextvar ge1) (genv_nextvar ge1 + 1)). - exists v1; split; congruence. omega. - pose proof (mge_rev_vars0 _ _ H). - destruct (zlt b (genv_nextvar ge1)); - destruct (zlt b (genv_nextvar ge1 + 1)). auto. omega. exfalso; omega. intuition. + rewrite mge_next0. intros. rewrite ZMap.gsspec in H0. rewrite ZMap.gsspec. + destruct (ZIndexed.eq b (genv_next ge1)). + subst b. rewrite zlt_true. exists f1; split; congruence. omega. + pose proof (mge_rev_funs0 b tf H0). + destruct (zlt b (genv_next ge1)). rewrite zlt_true. auto. omega. + contradiction. + eauto. + intros. + pose proof (mge_rev_vars0 b tv H0). + destruct (zlt b (genv_next ge1)). rewrite zlt_true. auto. omega. + contradiction. +(* two variables *) + constructor; simpl. + rewrite Zplus_0_r. congruence. + intros. rewrite mge_next0. + repeat rewrite PTree.gsspec. destruct (peq id0 id); auto. + eauto. + intros. + pose proof (mge_rev_funs0 b tf H0). + destruct (zlt b (genv_next ge1)). rewrite zlt_true. auto. omega. + contradiction. + rewrite mge_next0. intros. rewrite ZMap.gsspec in H0. rewrite ZMap.gsspec. + destruct (ZIndexed.eq b (genv_next ge1)). + econstructor; split. eauto. inv H0. constructor; auto. + eauto. + rewrite mge_next0. intros. rewrite ZMap.gsspec in H0. rewrite ZMap.gsspec. + destruct (ZIndexed.eq b (genv_next ge1)). + subst b. rewrite zlt_true. + econstructor; split. eauto. inv H0. constructor; auto. + omega. + pose proof (mge_rev_vars0 b tv H0). + destruct (zlt b (genv_next ge1)). rewrite zlt_true. auto. omega. + contradiction. Qed. -Lemma add_variables_match: - forall vl1 vl2, list_forall2 (match_var_entry match_varinfo) vl1 vl2 -> - forall new_functs ge1 ge2, match_genvs new_functs nil ge1 ge2 -> - match_genvs new_functs nil (add_variables ge1 vl1) (add_variables ge2 vl2). +Lemma add_globals_match: + forall gl1 gl2, list_forall2 (match_globdef match_fun match_varinfo) gl1 gl2 -> + forall ge1 ge2, match_genvs nil ge1 ge2 -> + match_genvs nil (add_globals ge1 gl1) (add_globals ge2 gl2). Proof. induction 1; intros; simpl. auto. - inv H. apply IHlist_forall2. apply add_variable_match; auto. constructor; auto. + apply IHlist_forall2. apply add_global_match; auto. Qed. - -Lemma add_variable_augment_match: - forall ge1 new_functs new_vars ge2 id v2, - match_genvs new_functs new_vars ge1 ge2 -> - match_genvs new_functs (new_vars++((id,v2)::nil)) ge1 (add_variable ge2 (id, v2)). +Lemma add_global_augment_match: + forall new_globs ge1 ge2 idg, + match_genvs new_globs ge1 ge2 -> + match_genvs (new_globs ++ (idg :: nil)) ge1 (add_global ge2 idg). Proof. intros. destruct H. constructor; simpl. - auto. - rewrite mge_nextvar0. rewrite app_length. - simpl. rewrite inj_plus. rewrite inj_S. rewrite inj_0. unfold block; omega. (* painful! *) - intros. unfold funct_names, var_names in H. rewrite map_app in H. rewrite in_app in H. rewrite in_app in H. simpl in H. - destruct (peq id id0). subst. intuition. rewrite PTree.gso. - apply mge_symb0. intro. apply H. rewrite in_app in H0. inversion H0; intuition. intuition. - auto. - auto. - intros. rewrite ZMap.gso. auto. - rewrite mge_nextvar0. pose proof (genv_vars_range ge1 b H). intro; subst; omega. - intros. rewrite ZMap.gsspec in H. - destruct (ZIndexed.eq b (genv_nextvar ge2)). - destruct (zlt b (genv_nextvar ge1)). - exfalso. rewrite mge_nextvar0 in e. unfold block; omega. - rewrite map_app. rewrite in_app. simpl. inversion H; intuition. - pose proof (mge_rev_vars0 b tv H). - destruct (zlt b (genv_nextvar ge1)). - auto. - rewrite map_app. rewrite in_app. intuition. - -Qed. - -Lemma add_variables_augment_match: - forall vl ge1 new_functs new_vars ge2, - match_genvs new_functs new_vars ge1 ge2 -> - match_genvs new_functs (new_vars++vl) ge1 (add_variables ge2 vl). -Proof. - induction vl; simpl. + rewrite mge_next0. rewrite app_length. + simpl. rewrite inj_plus. change (Z_of_nat 1) with 1. unfold block; omega. + intros. rewrite map_app in H. rewrite in_app in H. simpl in H. + destruct (peq id idg#1). subst. intuition. rewrite PTree.gso. + apply mge_symb0. intuition. auto. + intros. destruct idg as [id1 [f1|v1]]; simpl; eauto. + rewrite ZMap.gso. eauto. exploit genv_funs_range; eauto. rewrite mge_next0. unfold ZIndexed.t; omega. + intros. rewrite map_app. destruct idg as [id1 [f1|v1]]; simpl in H. + rewrite ZMap.gsspec in H. destruct (ZIndexed.eq b (genv_next ge2)). + rewrite zlt_false. rewrite in_app. simpl; right; left. congruence. + subst b. rewrite mge_next0. omega. + exploit mge_rev_funs0; eauto. destruct (zlt b (genv_next ge1)); auto. + rewrite in_app. tauto. + exploit mge_rev_funs0; eauto. destruct (zlt b (genv_next ge1)); auto. + rewrite in_app. tauto. + intros. destruct idg as [id1 [f1|v1]]; simpl; eauto. + rewrite ZMap.gso. eauto. exploit genv_vars_range; eauto. rewrite mge_next0. unfold ZIndexed.t; omega. + intros. rewrite map_app. destruct idg as [id1 [f1|v1]]; simpl in H. + exploit mge_rev_vars0; eauto. destruct (zlt b (genv_next ge1)); auto. + rewrite in_app. tauto. + rewrite ZMap.gsspec in H. destruct (ZIndexed.eq b (genv_next ge2)). + rewrite zlt_false. rewrite in_app. simpl; right; left. congruence. + subst b. rewrite mge_next0. omega. + exploit mge_rev_vars0; eauto. destruct (zlt b (genv_next ge1)); auto. + rewrite in_app. tauto. +Qed. + +Lemma add_globals_augment_match: + forall gl new_globs ge1 ge2, + match_genvs new_globs ge1 ge2 -> + match_genvs (new_globs ++ gl) ge1 (add_globals ge2 gl). +Proof. + induction gl; simpl. intros. rewrite app_nil_r. auto. - intros. replace (new_vars ++ a :: vl) with ((new_vars ++ (a::nil)) ++ vl) - by (rewrite app_ass; auto). - apply IHvl. destruct a. apply add_variable_augment_match. auto. + intros. change (a :: gl) with ((a :: nil) ++ gl). rewrite <- app_ass. + apply IHgl. apply add_global_augment_match. auto. Qed. -Variable new_functs : list (ident * B). -Variable new_vars : list (ident * globvar W). +Variable new_globs : list (ident * globdef B W). Variable new_main : ident. Variable p: program A V. Variable p': program B W. Hypothesis progmatch: - match_program match_fun match_varinfo new_functs new_vars new_main p p'. + match_program match_fun match_varinfo new_globs new_main p p'. Lemma globalenvs_match: - match_genvs new_functs new_vars (globalenv p) (globalenv p'). -Proof. - unfold globalenv. destruct progmatch. clear progmatch. - destruct H as [tfuncts [P1 P2]]. destruct H0. clear H0. destruct H as [tvars [Q1 Q2]]. - rewrite P2. rewrite Q2. clear P2 Q2. - rewrite add_variables_app. - rewrite add_functions_app. - pattern new_vars at 1. replace new_vars with (nil++new_vars) by auto. - apply add_variables_augment_match. - apply add_variables_match; auto. - pattern new_functs at 1. replace new_functs with (nil++new_functs) by auto. - apply add_functions_augment_match. - apply add_functions_match; auto. + match_genvs new_globs (globalenv p) (globalenv p'). +Proof. + unfold globalenv. destruct progmatch as [[tglob [P Q]] R]. + rewrite Q. rewrite add_globals_app. + change new_globs with (nil ++ new_globs) at 1. + apply add_globals_augment_match. + apply add_globals_match; auto. constructor; simpl; auto; intros; rewrite ZMap.gi in H; congruence. Qed. @@ -1544,10 +1430,10 @@ Proof (mge_funs globalenvs_match). Theorem find_funct_ptr_rev_match: forall (b : block) (tf : B), find_funct_ptr (globalenv p') b = Some tf -> - if zlt (genv_nextfun (globalenv p)) b then + if zlt b (genv_next (globalenv p)) then exists f, find_funct_ptr (globalenv p) b = Some f /\ match_fun f tf else - In tf (map (@snd ident B) new_functs). + In (Gfun tf) (map snd new_globs). Proof (mge_rev_funs globalenvs_match). Theorem find_funct_match: @@ -1565,13 +1451,13 @@ Theorem find_funct_rev_match: forall (v : val) (tf : B), find_funct (globalenv p') v = Some tf -> (exists f, find_funct (globalenv p) v = Some f /\ match_fun f tf) - \/ (In tf (map (@snd ident B) new_functs)). + \/ (In (Gfun tf) (map snd new_globs)). Proof. intros. exploit find_funct_inv; eauto. intros [b EQ]. subst v. rewrite find_funct_find_funct_ptr in H. rewrite find_funct_find_funct_ptr. apply find_funct_ptr_rev_match in H. - destruct (zlt (genv_nextfun (globalenv p)) b); intuition. + destruct (zlt b (genv_next (globalenv p))); auto. Qed. Theorem find_var_info_match: @@ -1584,23 +1470,23 @@ Proof (mge_vars globalenvs_match). Theorem find_var_info_rev_match: forall (b : block) (tv : globvar W), find_var_info (globalenv p') b = Some tv -> - if zlt b (genv_nextvar (globalenv p)) then + if zlt b (genv_next (globalenv p)) then exists v, find_var_info (globalenv p) b = Some v /\ match_globvar v tv else - In tv (map (@snd ident (globvar W)) new_vars). + In (Gvar tv) (map snd new_globs). Proof (mge_rev_vars globalenvs_match). Theorem find_symbol_match: forall (s : ident), - ~In s (funct_names new_functs ++ var_names new_vars) -> + ~In s (map fst new_globs) -> find_symbol (globalenv p') s = find_symbol (globalenv p) s. Proof. intros. destruct globalenvs_match. unfold find_symbol. auto. Qed. Hypothesis new_ids_fresh : - (forall s', find_symbol (globalenv p) s' <> None -> - ~In s' (funct_names new_functs ++ var_names new_vars)). + forall s', find_symbol (globalenv p) s' <> None -> + ~In s' (map fst new_globs). Lemma store_init_data_list_match: forall idl m b ofs m', @@ -1611,46 +1497,43 @@ Proof. auto. assert (forall m', store_init_data (globalenv p) m b ofs a = Some m' -> store_init_data (globalenv p') m b ofs a = Some m'). - destruct a; simpl; auto. rewrite find_symbol_match. auto. - inversion H. case_eq (find_symbol (globalenv p) i). - intros. apply new_ids_fresh. intro. rewrite H0 in H2; inversion H2. - intro. rewrite H0 in H1. inversion H1. + destruct a; simpl; auto. rewrite find_symbol_match. auto. + simpl in H. destruct (find_symbol (globalenv p) i) as [b'|]_eqn; try discriminate. + apply new_ids_fresh. congruence. case_eq (store_init_data (globalenv p) m b ofs a); intros. rewrite H1 in H. pose proof (H0 _ H1). rewrite H2. auto. rewrite H1 in H. inversion H. Qed. -Lemma alloc_variables_match: - forall vl1 vl2, list_forall2 (match_var_entry match_varinfo) vl1 vl2 -> +Lemma alloc_globals_match: + forall gl1 gl2, list_forall2 (match_globdef match_fun match_varinfo) gl1 gl2 -> forall m m', - alloc_variables (globalenv p) m vl1 = Some m' -> - alloc_variables (globalenv p') m vl2 = Some m'. + alloc_globals (globalenv p) m gl1 = Some m' -> + alloc_globals (globalenv p') m gl2 = Some m'. Proof. - induction 1; intros until m'; simpl. + induction 1; simpl; intros. auto. - inv H. - unfold alloc_variable; simpl. - destruct (Mem.alloc m 0 (init_data_list_size init)). - destruct (store_zeros m0 b (init_data_list_size init)); auto. - case_eq (store_init_data_list (globalenv p) m1 b 0 init); intros m2 P. - rewrite (store_init_data_list_match _ _ _ _ P). - change (perm_globvar (mkglobvar info2 init ro vo)) - with (perm_globvar (mkglobvar info1 init ro vo)). - destruct (Mem.drop_perm m2 b 0 (init_data_list_size init) - (perm_globvar (mkglobvar info1 init ro vo))); auto. - inversion P. + destruct (alloc_global (globalenv p) m a1) as [m1|]_eqn; try discriminate. + assert (alloc_global (globalenv p') m b1 = Some m1). + inv H; simpl in *. + auto. + set (sz := init_data_list_size init) in *. + destruct (Mem.alloc m 0 sz) as [m2 b]_eqn. + destruct (store_zeros m2 b 0 sz) as [m3|]_eqn; try discriminate. + destruct (store_init_data_list (globalenv p) m3 b 0 init) as [m4|]_eqn; try discriminate. + erewrite store_init_data_list_match; eauto. + rewrite H2. eauto. Qed. Theorem init_mem_match: forall m, init_mem p = Some m -> - init_mem p' = alloc_variables (globalenv p') m new_vars. + init_mem p' = alloc_globals (globalenv p') m new_globs. Proof. - unfold init_mem. destruct progmatch. destruct H0. destruct H0 as [tvars [P1 P2]]. - rewrite P2. - intros. - erewrite <- alloc_variables_app; eauto. - eapply alloc_variables_match; eauto. + unfold init_mem; intros. + destruct progmatch as [[tglob [P Q]] R]. + rewrite Q. erewrite <- alloc_globals_app; eauto. + eapply alloc_globals_match; eauto. Qed. End MATCH_PROGRAMS. @@ -1661,21 +1544,20 @@ Variable A B V W: Type. Variable transf_fun: A -> res B. Variable transf_var: V -> res W. -Variable new_functs : list (ident * B). -Variable new_vars : list (ident * globvar W). +Variable new_globs : list (ident * globdef B W). Variable new_main : ident. Variable p: program A V. Variable p': program B W. Hypothesis transf_OK: - transform_partial_augment_program transf_fun transf_var new_functs new_vars new_main p = OK p'. + transform_partial_augment_program transf_fun transf_var new_globs new_main p = OK p'. Remark prog_match: match_program (fun fd tfd => transf_fun fd = OK tfd) (fun info tinfo => transf_var info = OK tinfo) - new_functs new_vars new_main + new_globs new_main p p'. Proof. apply transform_partial_augment_program_match; auto. @@ -1692,51 +1574,39 @@ Proof. intros [tf [X Y]]. exists tf; auto. Qed. - - -(* This may not yet be in the ideal form for easy use .*) Theorem find_new_funct_ptr_exists: - list_norepet (prog_funct_names p ++ funct_names new_functs) -> - list_disjoint (prog_funct_names p ++ funct_names new_functs) (prog_var_names p ++ var_names new_vars) -> - forall id f, In (id, f) new_functs -> + list_norepet (List.map fst new_globs) -> + forall id f, In (id, Gfun f) new_globs -> exists b, find_symbol (globalenv p') id = Some b /\ find_funct_ptr (globalenv p') b = Some f. Proof. - intros. - destruct p. - unfold transform_partial_augment_program in transf_OK. - monadInv transf_OK. rename x into prog_funct'. rename x0 into prog_vars'. simpl in *. - assert (funct_names prog_funct = funct_names prog_funct'). - clear - EQ. generalize dependent prog_funct'. induction prog_funct; intros. - simpl in EQ. inversion EQ; subst; auto. - simpl in EQ. destruct a. destruct (transf_fun a); try discriminate. monadInv EQ. - simpl; f_equal; auto. - assert (var_names prog_vars = var_names prog_vars'). - clear - EQ1. generalize dependent prog_vars'. induction prog_vars; intros. - simpl in EQ1. inversion EQ1; subst; auto. - simpl in EQ1. destruct a. destruct (transf_globvar transf_var g); try discriminate. monadInv EQ1. - simpl; f_equal; auto. - apply find_funct_ptr_exists. - unfold prog_funct_names in *; simpl in *. - rewrite funct_names_app. rewrite <- H2. auto. - unfold prog_funct_names, prog_var_names in *; simpl in *. - rewrite funct_names_app. rewrite var_names_app. rewrite <- H2. rewrite <- H3. auto. - simpl. intuition. + intros. destruct prog_match as [[tglob [P Q]] R]. + unfold globalenv. rewrite Q. rewrite add_globals_app. + eapply add_globals_norepet_ensures; eauto. +(* preserves *) + intros. unfold find_symbol, find_funct_ptr in *; simpl. + destruct H1 as [b [X Y]]. exists b; split. + rewrite PTree.gso; auto. + destruct g1 as [f1 | v1]. rewrite ZMap.gso. auto. + exploit genv_funs_range; eauto. unfold ZIndexed.t; omega. + auto. +(* ensures *) + intros. unfold find_symbol, find_funct_ptr in *; simpl. + exists (genv_next ge); split. apply PTree.gss. apply ZMap.gss. Qed. Theorem find_funct_ptr_rev_transf_augment: forall (b: block) (tf: B), find_funct_ptr (globalenv p') b = Some tf -> - if (zlt (genv_nextfun (globalenv p)) b) then + if zlt b (genv_next (globalenv p)) then (exists f, find_funct_ptr (globalenv p) b = Some f /\ transf_fun f = OK tf) else - In tf (map (@snd ident B) new_functs). + In (Gfun tf) (map snd new_globs). Proof. intros. - exploit find_funct_ptr_rev_match;eauto. eexact prog_match; eauto. auto. + exploit find_funct_ptr_rev_match; eauto. eexact prog_match; eauto. auto. Qed. - Theorem find_funct_transf_augment: forall (v: val) (f: A), find_funct (globalenv p) v = Some f -> @@ -1744,15 +1614,14 @@ Theorem find_funct_transf_augment: find_funct (globalenv p') v = Some f' /\ transf_fun f = OK f'. Proof. intros. - exploit find_funct_match. eexact prog_match. eauto. - intros [tf [X Y]]. exists tf; auto. + exploit find_funct_match. eexact prog_match. eauto. auto. Qed. Theorem find_funct_rev_transf_augment: forall (v: val) (tf: B), find_funct (globalenv p') v = Some tf -> (exists f, find_funct (globalenv p) v = Some f /\ transf_fun f = OK tf) \/ - In tf (map (@snd ident B) new_functs). + In (Gfun tf) (map snd new_globs). Proof. intros. exploit find_funct_rev_match. eexact prog_match. eauto. auto. @@ -1765,65 +1634,49 @@ Theorem find_var_info_transf_augment: find_var_info (globalenv p') b = Some v' /\ transf_globvar transf_var v = OK v'. Proof. intros. - exploit find_var_info_match. eexact prog_match. eauto. - intros [tv [X Y]]. exists tv; split; auto. inv Y. unfold transf_globvar; simpl. + exploit find_var_info_match. eexact prog_match. eauto. intros [tv [X Y]]. + exists tv; split; auto. inv Y. unfold transf_globvar; simpl. rewrite H0; simpl. auto. Qed. Theorem find_new_var_exists: - forall id gv, - list_norepet (var_names new_vars) -> - In (id, gv) new_vars -> - exists b, find_symbol (globalenv p') id = Some b /\ find_var_info (globalenv p') b = Some gv. -Proof. - intros. - assert (P: forall b vars (ge: t B W), - ~In id (var_names vars) -> - find_symbol ge id = Some b - /\ find_var_info ge b = Some gv -> - find_symbol (add_variables ge vars) id = Some b - /\ find_var_info (add_variables ge vars) b = Some gv). - induction vars; simpl; intros. auto. apply IHvars. tauto. - destruct a as [id1 gv1]; unfold add_variable, find_symbol, find_var_info; simpl in *. - destruct H2; split. rewrite PTree.gso. auto. intuition. - rewrite ZMap.gso. auto. exploit genv_vars_range; eauto. unfold ZIndexed.t; omega. - - assert (Q: forall vars (ge: t B W), - list_norepet (var_names vars) -> - In (id, gv) vars -> - exists b, find_symbol (add_variables ge vars) id = Some b - /\ find_var_info (add_variables ge vars) b = Some gv). - induction vars; simpl; intros. - contradiction. - destruct a as [id1 gv1]; simpl in *. inv H1. destruct H2. inv H1. - exists (genv_nextvar ge). apply P; auto. - unfold add_variable, find_symbol, find_var_info; simpl in *. - split. apply PTree.gss. apply ZMap.gss. - apply IHvars; auto. - - unfold transform_partial_augment_program in transf_OK. - monadInv transf_OK. rename x into prog_funct'. rename x0 into prog_vars'. simpl in *. - unfold globalenv; simpl. repeat rewrite add_variables_app. apply Q; auto. + list_norepet (List.map fst new_globs) -> + forall id gv, In (id, Gvar gv) new_globs -> + exists b, find_symbol (globalenv p') id = Some b + /\ find_var_info (globalenv p') b = Some gv. +Proof. + intros. destruct prog_match as [[tglob [P Q]] R]. + unfold globalenv. rewrite Q. rewrite add_globals_app. + eapply add_globals_norepet_ensures; eauto. +(* preserves *) + intros. unfold find_symbol, find_var_info in *; simpl. + destruct H1 as [b [X Y]]. exists b; split. + rewrite PTree.gso; auto. + destruct g1 as [f1 | v1]. auto. rewrite ZMap.gso. auto. + exploit genv_vars_range; eauto. unfold ZIndexed.t; omega. +(* ensures *) + intros. unfold find_symbol, find_var_info in *; simpl. + exists (genv_next ge); split. apply PTree.gss. apply ZMap.gss. Qed. Theorem find_var_info_rev_transf_augment: forall (b: block) (v': globvar W), find_var_info (globalenv p') b = Some v' -> - if zlt b (genv_nextvar (globalenv p)) then + if zlt b (genv_next (globalenv p)) then (exists v, find_var_info (globalenv p) b = Some v /\ transf_globvar transf_var v = OK v') else - (In v' (map (@snd ident (globvar W)) new_vars)). + (In (Gvar v') (map snd new_globs)). Proof. intros. exploit find_var_info_rev_match. eexact prog_match. eauto. - destruct (zlt b (genv_nextvar (globalenv p))); auto. + destruct (zlt b (genv_next (globalenv p))); auto. intros [v [X Y]]. exists v; split; auto. inv Y. unfold transf_globvar; simpl. rewrite H0; simpl. auto. Qed. Theorem find_symbol_transf_augment: forall (s: ident), - ~ In s (funct_names new_functs ++ var_names new_vars) -> + ~ In s (map fst new_globs) -> find_symbol (globalenv p') s = find_symbol (globalenv p) s. Proof. intros. eapply find_symbol_match. eexact prog_match. auto. @@ -1831,16 +1684,16 @@ Qed. Theorem init_mem_transf_augment: (forall s', find_symbol (globalenv p) s' <> None -> - ~ In s' (funct_names new_functs ++ var_names new_vars)) -> + ~ In s' (map fst new_globs)) -> forall m, init_mem p = Some m -> - init_mem p' = alloc_variables (globalenv p') m new_vars. + init_mem p' = alloc_globals (globalenv p') m new_globs. Proof. intros. eapply init_mem_match. eexact prog_match. auto. auto. Qed. Theorem init_mem_inject_transf_augment: (forall s', find_symbol (globalenv p) s' <> None -> - ~ In s' (funct_names new_functs ++ var_names new_vars)) -> + ~ In s' (map fst new_globs)) -> forall m, init_mem p = Some m -> forall m', init_mem p' = Some m' -> Mem.inject (Mem.flat_inj (Mem.nextblock m)) m m'. @@ -1848,10 +1701,9 @@ Proof. intros. pose proof (initmem_inject p H0). erewrite init_mem_transf_augment in H1; eauto. - eapply alloc_variables_augment; eauto. omega. + eapply alloc_globals_augment; eauto. omega. Qed. - End TRANSF_PROGRAM_AUGMENT. Section TRANSF_PROGRAM_PARTIAL2. @@ -1865,13 +1717,9 @@ Hypothesis transf_OK: transform_partial_program2 transf_fun transf_var p = OK p'. Remark transf_augment_OK: - transform_partial_augment_program transf_fun transf_var nil nil p.(prog_main) p = OK p'. + transform_partial_augment_program transf_fun transf_var nil p.(prog_main) p = OK p'. Proof. - rewrite <- transf_OK. - unfold transform_partial_augment_program, transform_partial_program2. - destruct (map_partial prefix_name transf_fun (prog_funct p)); auto. simpl. - destruct (map_partial prefix_name (transf_globvar transf_var) (prog_vars p)); simpl. - repeat rewrite app_nil_r. auto. auto. + rewrite <- transf_OK. apply symmetry. apply transform_partial_program2_augment. Qed. Theorem find_funct_ptr_transf_partial2: @@ -1880,7 +1728,7 @@ Theorem find_funct_ptr_transf_partial2: exists f', find_funct_ptr (globalenv p') b = Some f' /\ transf_fun f = OK f'. Proof. - exact (@find_funct_ptr_transf_augment _ _ _ _ _ _ _ _ _ _ _ transf_augment_OK). + exact (@find_funct_ptr_transf_augment _ _ _ _ _ _ _ _ _ _ transf_augment_OK). Qed. Theorem find_funct_ptr_rev_transf_partial2: @@ -1888,9 +1736,9 @@ Theorem find_funct_ptr_rev_transf_partial2: find_funct_ptr (globalenv p') b = Some tf -> exists f, find_funct_ptr (globalenv p) b = Some f /\ transf_fun f = OK tf. Proof. - pose proof (@find_funct_ptr_rev_transf_augment _ _ _ _ _ _ _ _ _ _ _ transf_augment_OK). + pose proof (@find_funct_ptr_rev_transf_augment _ _ _ _ _ _ _ _ _ _ transf_augment_OK). intros. pose proof (H b tf H0). - destruct (zlt (genv_nextfun (globalenv p)) b). auto. inversion H1. + destruct (zlt b (genv_next (globalenv p))). auto. contradiction. Qed. Theorem find_funct_transf_partial2: @@ -1899,7 +1747,7 @@ Theorem find_funct_transf_partial2: exists f', find_funct (globalenv p') v = Some f' /\ transf_fun f = OK f'. Proof. - exact (@find_funct_transf_augment _ _ _ _ _ _ _ _ _ _ _ transf_augment_OK). + exact (@find_funct_transf_augment _ _ _ _ _ _ _ _ _ _ transf_augment_OK). Qed. Theorem find_funct_rev_transf_partial2: @@ -1907,9 +1755,9 @@ Theorem find_funct_rev_transf_partial2: find_funct (globalenv p') v = Some tf -> exists f, find_funct (globalenv p) v = Some f /\ transf_fun f = OK tf. Proof. - pose proof (@find_funct_rev_transf_augment _ _ _ _ _ _ _ _ _ _ _ transf_augment_OK). + pose proof (@find_funct_rev_transf_augment _ _ _ _ _ _ _ _ _ _ transf_augment_OK). intros. pose proof (H v tf H0). - destruct H1. auto. inversion H1. + destruct H1. auto. contradiction. Qed. Theorem find_var_info_transf_partial2: @@ -1918,7 +1766,7 @@ Theorem find_var_info_transf_partial2: exists v', find_var_info (globalenv p') b = Some v' /\ transf_globvar transf_var v = OK v'. Proof. - exact (@find_var_info_transf_augment _ _ _ _ _ _ _ _ _ _ _ transf_augment_OK). + exact (@find_var_info_transf_augment _ _ _ _ _ _ _ _ _ _ transf_augment_OK). Qed. Theorem find_var_info_rev_transf_partial2: @@ -1927,23 +1775,23 @@ Theorem find_var_info_rev_transf_partial2: exists v, find_var_info (globalenv p) b = Some v /\ transf_globvar transf_var v = OK v'. Proof. - pose proof (@find_var_info_rev_transf_augment _ _ _ _ _ _ _ _ _ _ _ transf_augment_OK). + pose proof (@find_var_info_rev_transf_augment _ _ _ _ _ _ _ _ _ _ transf_augment_OK). intros. pose proof (H b v' H0). - destruct (zlt b (genv_nextvar (globalenv p))). auto. inversion H1. + destruct (zlt b (genv_next (globalenv p))). auto. contradiction. Qed. Theorem find_symbol_transf_partial2: forall (s: ident), find_symbol (globalenv p') s = find_symbol (globalenv p) s. Proof. - pose proof (@find_symbol_transf_augment _ _ _ _ _ _ _ _ _ _ _ transf_augment_OK). + pose proof (@find_symbol_transf_augment _ _ _ _ _ _ _ _ _ _ transf_augment_OK). auto. Qed. Theorem init_mem_transf_partial2: forall m, init_mem p = Some m -> init_mem p' = Some m. Proof. - pose proof (@init_mem_transf_augment _ _ _ _ _ _ _ _ _ _ _ transf_augment_OK). + pose proof (@init_mem_transf_augment _ _ _ _ _ _ _ _ _ _ transf_augment_OK). intros. simpl in H. apply H; auto. Qed. @@ -1957,24 +1805,13 @@ Variable p: program A V. Variable p': program B V. Hypothesis transf_OK: transform_partial_program transf p = OK p'. -Remark transf2_OK: - transform_partial_program2 transf (fun x => OK x) p = OK p'. -Proof. - rewrite <- transf_OK. - unfold transform_partial_program2, transform_partial_program. - destruct (map_partial prefix_name transf (prog_funct p)); auto. - simpl. replace (transf_globvar (fun (x : V) => OK x)) with (fun (v: globvar V) => OK v). - rewrite map_partial_identity; auto. - apply extensionality; intros. destruct x; auto. -Qed. - Theorem find_funct_ptr_transf_partial: forall (b: block) (f: A), find_funct_ptr (globalenv p) b = Some f -> exists f', find_funct_ptr (globalenv p') b = Some f' /\ transf f = OK f'. Proof. - exact (@find_funct_ptr_transf_partial2 _ _ _ _ _ _ _ _ transf2_OK). + exact (@find_funct_ptr_transf_partial2 _ _ _ _ _ _ _ _ transf_OK). Qed. Theorem find_funct_ptr_rev_transf_partial: @@ -1982,7 +1819,7 @@ Theorem find_funct_ptr_rev_transf_partial: find_funct_ptr (globalenv p') b = Some tf -> exists f, find_funct_ptr (globalenv p) b = Some f /\ transf f = OK tf. Proof. - exact (@find_funct_ptr_rev_transf_partial2 _ _ _ _ _ _ _ _ transf2_OK). + exact (@find_funct_ptr_rev_transf_partial2 _ _ _ _ _ _ _ _ transf_OK). Qed. Theorem find_funct_transf_partial: @@ -1991,7 +1828,7 @@ Theorem find_funct_transf_partial: exists f', find_funct (globalenv p') v = Some f' /\ transf f = OK f'. Proof. - exact (@find_funct_transf_partial2 _ _ _ _ _ _ _ _ transf2_OK). + exact (@find_funct_transf_partial2 _ _ _ _ _ _ _ _ transf_OK). Qed. Theorem find_funct_rev_transf_partial: @@ -1999,14 +1836,14 @@ Theorem find_funct_rev_transf_partial: find_funct (globalenv p') v = Some tf -> exists f, find_funct (globalenv p) v = Some f /\ transf f = OK tf. Proof. - exact (@find_funct_rev_transf_partial2 _ _ _ _ _ _ _ _ transf2_OK). + exact (@find_funct_rev_transf_partial2 _ _ _ _ _ _ _ _ transf_OK). Qed. Theorem find_symbol_transf_partial: forall (s: ident), find_symbol (globalenv p') s = find_symbol (globalenv p) s. Proof. - exact (@find_symbol_transf_partial2 _ _ _ _ _ _ _ _ transf2_OK). + exact (@find_symbol_transf_partial2 _ _ _ _ _ _ _ _ transf_OK). Qed. Theorem find_var_info_transf_partial: @@ -2014,10 +1851,10 @@ Theorem find_var_info_transf_partial: find_var_info (globalenv p') b = find_var_info (globalenv p) b. Proof. intros. case_eq (find_var_info (globalenv p) b); intros. - exploit find_var_info_transf_partial2. eexact transf2_OK. eauto. + exploit find_var_info_transf_partial2. eexact transf_OK. eauto. intros [v' [P Q]]. monadInv Q. rewrite P. inv EQ. destruct g; auto. case_eq (find_var_info (globalenv p') b); intros. - exploit find_var_info_rev_transf_partial2. eexact transf2_OK. eauto. + exploit find_var_info_rev_transf_partial2. eexact transf_OK. eauto. intros [v' [P Q]]. monadInv Q. inv EQ. congruence. auto. Qed. @@ -2025,7 +1862,7 @@ Qed. Theorem init_mem_transf_partial: forall m, init_mem p = Some m -> init_mem p' = Some m. Proof. - exact (@init_mem_transf_partial2 _ _ _ _ _ _ _ _ transf2_OK). + exact (@init_mem_transf_partial2 _ _ _ _ _ _ _ _ transf_OK). Qed. End TRANSF_PROGRAM_PARTIAL. @@ -2040,8 +1877,7 @@ Let tp := transform_program transf p. Remark transf_OK: transform_partial_program (fun x => OK (transf x)) p = OK tp. Proof. - unfold tp, transform_program, transform_partial_program. - rewrite map_partial_total. reflexivity. + unfold tp. apply transform_program_partial_program. Qed. Theorem find_funct_ptr_transf: |