diff options
Diffstat (limited to 'common/AST.v')
-rw-r--r-- | common/AST.v | 422 |
1 files changed, 169 insertions, 253 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 *) |