aboutsummaryrefslogtreecommitdiffstats
path: root/src/hls/DHTLgenproof0.v
diff options
context:
space:
mode:
Diffstat (limited to 'src/hls/DHTLgenproof0.v')
-rw-r--r--src/hls/DHTLgenproof0.v2016
1 files changed, 2016 insertions, 0 deletions
diff --git a/src/hls/DHTLgenproof0.v b/src/hls/DHTLgenproof0.v
new file mode 100644
index 0000000..fa467eb
--- /dev/null
+++ b/src/hls/DHTLgenproof0.v
@@ -0,0 +1,2016 @@
+(*
+ * Vericert: Verified high-level synthesis.
+ * Copyright (C) 2023 Yann Herklotz <yann@yannherklotz.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *)
+
+Require Import Coq.micromega.Lia.
+
+Require Import compcert.lib.Maps.
+Require Import compcert.common.Errors.
+Require Import compcert.common.Globalenvs.
+Require compcert.backend.Registers.
+Require Import compcert.common.Linking.
+Require Import compcert.common.Memory.
+Require compcert.common.Globalenvs.
+Require Import compcert.lib.Integers.
+Require Import compcert.common.AST.
+
+Require Import vericert.common.IntegerExtra.
+Require Import vericert.common.Vericertlib.
+Require Import vericert.common.ZExtra.
+Require Import vericert.hls.Array.
+Require Import vericert.hls.AssocMap.
+Require Import vericert.hls.DHTL.
+Require Import vericert.hls.Gible.
+Require Import vericert.hls.GibleSubPar.
+Require Import vericert.hls.DHTLgen.
+Require Import vericert.hls.Predicate.
+Require Import vericert.hls.ValueInt.
+Require Import vericert.hls.Verilog.
+Require vericert.hls.Verilog.
+Require Import vericert.common.Errormonad.
+Import ErrorMonad.
+Import ErrorMonadExtra.
+
+Require Import Lia.
+
+Local Open Scope assocmap.
+
+Local Opaque Int.max_unsigned.
+
+#[export] Hint Resolve AssocMap.gss : htlproof.
+#[export] Hint Resolve AssocMap.gso : htlproof.
+
+#[export] Hint Unfold find_assocmap AssocMapExt.get_default : htlproof.
+
+Definition get_mem n r :=
+ Option.default (NToValue 0) (Option.join (array_get_error n r)).
+
+Inductive match_assocmaps : positive -> positive -> Gible.regset -> Gible.predset -> assocmap -> Prop :=
+ match_assocmap : forall rs pr am max_reg max_pred,
+ (forall r, Ple r max_reg ->
+ val_value_lessdef (Registers.Regmap.get r rs) (find_assocmap 32 (reg_enc r) am)) ->
+ (forall r, Ple r max_pred ->
+ find_assocmap 1 (pred_enc r) am = boolToValue (PMap.get r pr)) ->
+ match_assocmaps max_reg max_pred rs pr am.
+#[export] Hint Constructors match_assocmaps : htlproof.
+
+Inductive match_arrs (stack_size: Z) (stk: positive) (stk_len: nat) (sp : Values.val) (mem : mem) :
+ Verilog.assocmap_arr -> Prop :=
+| match_arr : forall asa stack,
+ asa ! stk = Some stack /\
+ stack.(arr_length) = Z.to_nat (stack_size / 4) /\
+ stack.(arr_length) = stk_len /\
+ (forall ptr,
+ 0 <= ptr < Z.of_nat stack.(arr_length) ->
+ opt_val_value_lessdef (Mem.loadv AST.Mint32 mem
+ (Values.Val.offset_ptr sp (Ptrofs.repr (4 * ptr))))
+ (get_mem (Z.to_nat ptr) stack)) ->
+ match_arrs stack_size stk stk_len sp mem asa.
+
+Definition stack_based (v : Values.val) (sp : Values.block) : Prop :=
+ match v with
+ | Values.Vptr sp' off => sp' = sp
+ | _ => True
+ end.
+
+Definition reg_stack_based_pointers (sp : Values.block) (rs : Registers.Regmap.t Values.val) : Prop :=
+ forall r, stack_based (Registers.Regmap.get r rs) sp.
+
+Definition arr_stack_based_pointers (spb : Values.block) (m : mem) (stack_length : Z)
+ (sp : Values.val) : Prop :=
+ forall ptr,
+ 0 <= ptr < (stack_length / 4) ->
+ stack_based (Option.default
+ Values.Vundef
+ (Mem.loadv AST.Mint32 m
+ (Values.Val.offset_ptr sp (Ptrofs.repr (4 * ptr)))))
+ spb.
+
+Definition stack_bounds (sp : Values.val) (hi : Z) (m : mem) : Prop :=
+ forall ptr v,
+ hi <= ptr <= Ptrofs.max_unsigned ->
+ Z.modulo ptr 4 = 0 ->
+ Mem.loadv AST.Mint32 m (Values.Val.offset_ptr sp (Ptrofs.repr ptr )) = None /\
+ Mem.storev AST.Mint32 m (Values.Val.offset_ptr sp (Ptrofs.repr ptr )) v = None.
+
+Inductive match_frames : list GibleSubPar.stackframe -> list DHTL.stackframe -> Prop :=
+| match_frames_nil :
+ match_frames nil nil.
+
+Inductive match_constants (rst fin: reg) (asr: assocmap) : Prop :=
+ match_constant :
+ asr!rst = Some (ZToValue 0) ->
+ asr!fin = Some (ZToValue 0) ->
+ match_constants rst fin asr.
+
+Definition state_st_wf (asr: assocmap) (st_reg: reg) (st: positive) :=
+ asr!st_reg = Some (posToValue st).
+#[export] Hint Unfold state_st_wf : htlproof.
+
+Inductive match_states : GibleSubPar.state -> DHTL.state -> Prop :=
+| match_state : forall asa asr sf f sp sp' rs mem m st res ps
+ (MASSOC : match_assocmaps (max_reg_function f) (max_pred_function f) rs ps asr)
+ (TF : transl_module f = Errors.OK m)
+ (WF : state_st_wf asr m.(DHTL.mod_st) st)
+ (MF : match_frames sf res)
+ (MARR : match_arrs f.(fn_stacksize) m.(DHTL.mod_stk) m.(DHTL.mod_stk_len) sp mem asa)
+ (SP : sp = Values.Vptr sp' (Ptrofs.repr 0))
+ (RSBP : reg_stack_based_pointers sp' rs)
+ (ASBP : arr_stack_based_pointers sp' mem (f.(GibleSubPar.fn_stacksize)) sp)
+ (BOUNDS : stack_bounds sp (f.(GibleSubPar.fn_stacksize)) mem)
+ (CONST : match_constants m.(DHTL.mod_reset) m.(DHTL.mod_finish) asr),
+ (* Add a relation about ps compared with the state register. *)
+ match_states (GibleSubPar.State sf f sp st rs ps mem)
+ (DHTL.State res m st asr asa)
+| match_returnstate :
+ forall
+ v v' stack mem res
+ (MF : match_frames stack res),
+ val_value_lessdef v v' ->
+ match_states (GibleSubPar.Returnstate stack v mem) (DHTL.Returnstate res v')
+| match_initial_call :
+ forall f m m0
+ (TF : transl_module f = Errors.OK m),
+ match_states (GibleSubPar.Callstate nil (AST.Internal f) nil m0) (DHTL.Callstate nil m nil).
+#[export] Hint Constructors match_states : htlproof.
+
+Inductive match_states_reduced : nat -> GibleSubPar.state -> DHTL.state -> Prop :=
+| match_states_reduced_intro : forall asa asr sf f sp sp' rs mem m st res ps n
+ (MASSOC : match_assocmaps (max_reg_function f) (max_pred_function f) rs ps asr)
+ (TF : transl_module f = Errors.OK m)
+ (WF : state_st_wf asr m.(DHTL.mod_st) (Pos.of_nat (Pos.to_nat st - n)%nat))
+ (MF : match_frames sf res)
+ (MARR : match_arrs f.(fn_stacksize) m.(DHTL.mod_stk) m.(DHTL.mod_stk_len) sp mem asa)
+ (SP : sp = Values.Vptr sp' (Ptrofs.repr 0))
+ (RSBP : reg_stack_based_pointers sp' rs)
+ (ASBP : arr_stack_based_pointers sp' mem (f.(GibleSubPar.fn_stacksize)) sp)
+ (BOUNDS : stack_bounds sp (f.(GibleSubPar.fn_stacksize)) mem)
+ (CONST : match_constants m.(DHTL.mod_reset) m.(DHTL.mod_finish) asr),
+ (* Add a relation about ps compared with the state register. *)
+ match_states_reduced n (GibleSubPar.State sf f sp st rs ps mem)
+ (DHTL.State res m (Pos.of_nat (Pos.to_nat st - n)%nat) asr asa).
+
+Definition match_prog (p: GibleSubPar.program) (tp: DHTL.program) :=
+ Linking.match_program (fun cu f tf => transl_fundef f = Errors.OK tf) eq p tp /\
+ main_is_internal p = true.
+
+Ltac unfold_match H :=
+ match type of H with
+ | context[match ?g with _ => _ end] => destruct g eqn:?; try discriminate
+ end.
+
+#[global] Instance TransfHTLLink (tr_fun: GibleSubPar.program -> Errors.res DHTL.program):
+ TransfLink (fun (p1: GibleSubPar.program) (p2: DHTL.program) => match_prog p1 p2).
+Proof.
+ red. intros. exfalso. destruct (link_linkorder _ _ _ H) as [LO1 LO2].
+ apply link_prog_inv in H.
+
+ unfold match_prog in *.
+ unfold main_is_internal in *. simplify. repeat (unfold_match H4).
+ repeat (unfold_match H3). simplify.
+ subst. rewrite H0 in *. specialize (H (AST.prog_main p2)).
+ exploit H.
+ apply Genv.find_def_symbol. exists b. split.
+ assumption. apply Genv.find_funct_ptr_iff. eassumption.
+ apply Genv.find_def_symbol. exists b0. split.
+ assumption. apply Genv.find_funct_ptr_iff. eassumption.
+ intros. inv H3. inv H5. destruct H6. inv H5.
+Qed.
+
+Definition match_prog' (p: GibleSubPar.program) (tp: DHTL.program) :=
+ Linking.match_program (fun cu f tf => transl_fundef f = Errors.OK tf) eq p tp.
+
+Lemma match_prog_matches :
+ forall p tp, match_prog p tp -> match_prog' p tp.
+Proof. unfold match_prog. tauto. Qed.
+
+Lemma transf_program_match:
+ forall p tp, transl_program p = Errors.OK tp -> match_prog p tp.
+Proof.
+ intros. unfold transl_program in H.
+ destruct (main_is_internal p) eqn:?; try discriminate.
+ unfold match_prog. split.
+ apply Linking.match_transform_partial_program; auto.
+ assumption.
+Qed.
+
+Lemma max_reg_lt_resource :
+ forall f n,
+ Plt (max_resource_function f) n ->
+ Plt (reg_enc (max_reg_function f)) n.
+Proof.
+ unfold max_resource_function, Plt, reg_enc, pred_enc in *; intros. lia.
+Qed.
+
+Lemma max_pred_lt_resource :
+ forall f n,
+ Plt (max_resource_function f) n ->
+ Plt (pred_enc (max_pred_function f)) n.
+Proof.
+ unfold max_resource_function, Plt, reg_enc, pred_enc in *; intros. lia.
+Qed.
+
+Lemma plt_reg_enc :
+ forall a b, Ple a b -> Ple (reg_enc a) (reg_enc b).
+Proof. unfold Ple, reg_enc, pred_enc in *; intros. lia. Qed.
+
+Lemma plt_pred_enc :
+ forall a b, Ple a b -> Ple (pred_enc a) (pred_enc b).
+Proof. unfold Ple, reg_enc, pred_enc in *; intros. lia. Qed.
+
+Lemma reg_enc_inj :
+ forall a b, reg_enc a = reg_enc b -> a = b.
+Proof. unfold reg_enc; intros; lia. Qed.
+
+Lemma pred_enc_inj :
+ forall a b, pred_enc a = pred_enc b -> a = b.
+Proof. unfold pred_enc; intros; lia. Qed.
+
+(* Lemma regs_lessdef_add_greater : *)
+(* forall n m rs1 ps1 rs2 n v, *)
+(* Plt (max_resource_function f) n -> *)
+(* match_assocmaps n m rs1 ps1 rs2 -> *)
+(* match_assocmaps n m rs1 ps1 (AssocMap.set n v rs2). *)
+(* Proof. *)
+(* inversion 2; subst. *)
+(* intros. constructor. *)
+(* - apply max_reg_lt_resource in H. intros. unfold find_assocmap. unfold AssocMapExt.get_default. *)
+(* rewrite AssocMap.gso. eauto. apply plt_reg_enc in H3. unfold Ple, Plt in *. lia. *)
+(* - apply max_pred_lt_resource in H. intros. unfold find_assocmap. unfold AssocMapExt.get_default. *)
+(* rewrite AssocMap.gso. eauto. apply plt_pred_enc in H3. unfold Ple, Plt in *. lia. *)
+(* Qed. *)
+(* #[export] Hint Resolve regs_lessdef_add_greater : htlproof. *)
+
+Lemma pred_enc_reg_enc_ne :
+ forall a b, pred_enc a <> reg_enc b.
+Proof. unfold not, pred_enc, reg_enc; lia. Qed.
+
+Lemma regs_lessdef_add_match :
+ forall m n rs ps am r v v',
+ val_value_lessdef v v' ->
+ match_assocmaps m n rs ps am ->
+ match_assocmaps m n (Registers.Regmap.set r v rs) ps (AssocMap.set (reg_enc r) v' am).
+Proof.
+ inversion 2; subst.
+ constructor. intros.
+ destruct (peq r0 r); subst.
+ rewrite Registers.Regmap.gss.
+ unfold find_assocmap. unfold AssocMapExt.get_default.
+ rewrite AssocMap.gss. assumption.
+
+ rewrite Registers.Regmap.gso; try assumption.
+ unfold find_assocmap. unfold AssocMapExt.get_default.
+ rewrite AssocMap.gso; eauto. unfold not in *; intros; apply n0. apply reg_enc_inj; auto.
+
+ intros. pose proof (pred_enc_reg_enc_ne r0 r) as HNE.
+ rewrite assocmap_gso by auto. now apply H2.
+Qed.
+#[export] Hint Resolve regs_lessdef_add_match : htlproof.
+
+Lemma list_combine_none :
+ forall n l,
+ length l = n ->
+ list_combine Verilog.merge_cell (list_repeat None n) l = l.
+Proof.
+ induction n; intros; crush.
+ - symmetry. apply length_zero_iff_nil. auto.
+ - destruct l; crush.
+ rewrite list_repeat_cons.
+ crush. f_equal.
+ eauto.
+Qed.
+
+Lemma combine_none :
+ forall n a,
+ a.(arr_length) = n ->
+ arr_contents (combine Verilog.merge_cell (arr_repeat None n) a) = arr_contents a.
+Proof.
+ intros.
+ unfold combine.
+ crush.
+
+ rewrite <- (arr_wf a) in H.
+ apply list_combine_none.
+ assumption.
+Qed.
+
+Lemma list_combine_lookup_first :
+ forall l1 l2 n,
+ length l1 = length l2 ->
+ nth_error l1 n = Some None ->
+ nth_error (list_combine Verilog.merge_cell l1 l2) n = nth_error l2 n.
+Proof.
+ induction l1; intros; crush.
+
+ rewrite nth_error_nil in H0.
+ discriminate.
+
+ destruct l2 eqn:EQl2. crush.
+ simpl in H. inv H.
+ destruct n; simpl in *.
+ inv H0. simpl. reflexivity.
+ eauto.
+Qed.
+
+Lemma combine_lookup_first :
+ forall a1 a2 n,
+ a1.(arr_length) = a2.(arr_length) ->
+ array_get_error n a1 = Some None ->
+ array_get_error n (combine Verilog.merge_cell a1 a2) = array_get_error n a2.
+Proof.
+ intros.
+
+ unfold array_get_error in *.
+ apply list_combine_lookup_first; eauto.
+ rewrite a1.(arr_wf). rewrite a2.(arr_wf).
+ assumption.
+Qed.
+
+Lemma list_combine_lookup_second :
+ forall l1 l2 n x,
+ length l1 = length l2 ->
+ nth_error l1 n = Some (Some x) ->
+ nth_error (list_combine Verilog.merge_cell l1 l2) n = Some (Some x).
+Proof.
+ induction l1; intros; crush; auto.
+
+ destruct l2 eqn:EQl2. crush.
+ simpl in H. inv H.
+ destruct n; simpl in *.
+ inv H0. simpl. reflexivity.
+ eauto.
+Qed.
+
+Lemma combine_lookup_second :
+ forall a1 a2 n x,
+ a1.(arr_length) = a2.(arr_length) ->
+ array_get_error n a1 = Some (Some x) ->
+ array_get_error n (combine Verilog.merge_cell a1 a2) = Some (Some x).
+Proof.
+ intros.
+
+ unfold array_get_error in *.
+ apply list_combine_lookup_second; eauto.
+ rewrite a1.(arr_wf). rewrite a2.(arr_wf).
+ assumption.
+Qed.
+
+Ltac unfold_func H :=
+ match type of H with
+ | ?f = _ => unfold f in H; repeat (unfold_match H)
+ | ?f _ = _ => unfold f in H; repeat (unfold_match H)
+ | ?f _ _ = _ => unfold f in H; repeat (unfold_match H)
+ | ?f _ _ _ = _ => unfold f in H; repeat (unfold_match H)
+ | ?f _ _ _ _ = _ => unfold f in H; repeat (unfold_match H)
+ end.
+
+Lemma init_reg_assoc_empty :
+ forall n m l,
+ match_assocmaps n m (Gible.init_regs nil l) (PMap.init false) (DHTL.init_regs nil l).
+Proof.
+ induction l; simpl; constructor; intros.
+ - rewrite Registers.Regmap.gi. unfold find_assocmap.
+ unfold AssocMapExt.get_default. rewrite AssocMap.gempty.
+ constructor.
+
+ - rewrite Registers.Regmap.gi. unfold find_assocmap.
+ unfold AssocMapExt.get_default. rewrite AssocMap.gempty.
+ constructor.
+
+ - rewrite Registers.Regmap.gi. unfold find_assocmap.
+ unfold AssocMapExt.get_default. rewrite AssocMap.gempty.
+ constructor.
+
+ - rewrite Registers.Regmap.gi. unfold find_assocmap.
+ unfold AssocMapExt.get_default. rewrite AssocMap.gempty.
+ constructor.
+Qed.
+
+Lemma arr_lookup_some:
+ forall (z : Z) (r0 : Registers.reg) (r : Verilog.reg) (asr : assocmap) (asa : Verilog.assocmap_arr)
+ (stack : Array (option value)) (H5 : asa ! r = Some stack) n,
+ exists x, Verilog.arr_assocmap_lookup asa r n = Some x.
+Proof.
+ intros z r0 r asr asa stack H5 n.
+ eexists.
+ unfold Verilog.arr_assocmap_lookup. rewrite H5. reflexivity.
+Qed.
+#[export] Hint Resolve arr_lookup_some : htlproof.
+
+Lemma regs_lessdef_add_greater :
+ forall f rs1 rs2 ps n v,
+ Plt (max_resource_function f) n ->
+ match_assocmaps (max_reg_function f) (max_pred_function f) rs1 ps rs2 ->
+ match_assocmaps (max_reg_function f) (max_pred_function f) rs1 ps (AssocMap.set n v rs2).
+Proof.
+ inversion 2; subst.
+ intros. constructor.
+ intros. unfold find_assocmap. unfold AssocMapExt.get_default.
+ rewrite AssocMap.gso. eauto.
+ eapply plt_reg_enc in H3. unfold Plt, Ple, max_resource_function in *. lia.
+ intros. unfold find_assocmap. unfold AssocMapExt.get_default.
+ rewrite AssocMap.gso. eauto.
+ eapply plt_pred_enc in H3. unfold Plt, Ple, max_resource_function in *. lia.
+Qed.
+#[export] Hint Resolve regs_lessdef_add_greater : htlproof.
+
+Ltac destr := destruct_match; try discriminate; [].
+
+Lemma pred_in_pred_uses:
+ forall A (p: A) pop,
+ PredIn p pop ->
+ In p (predicate_use pop).
+Proof.
+ induction pop; crush.
+ - destr. inv Heqp1. inv H. now constructor.
+ - inv H.
+ - inv H.
+ - apply in_or_app. inv H. inv H1; intuition.
+ - apply in_or_app. inv H. inv H1; intuition.
+Qed.
+
+Lemma le_max_pred :
+ forall p max_pred,
+ Forall (fun x : positive => Ple x max_pred) (predicate_use p) ->
+ Ple (max_predicate p) max_pred.
+Proof.
+ induction p; intros.
+ - intros; cbn. destruct_match. inv Heqp0. cbn in *. now inv H.
+ - cbn. unfold Ple. lia.
+ - cbn. unfold Ple. lia.
+ - cbn in *. eapply Forall_app in H. inv H. unfold Ple in *. eapply IHp1 in H0.
+ eapply IHp2 in H1. lia.
+ - cbn in *. eapply Forall_app in H. inv H. unfold Ple in *. eapply IHp1 in H0.
+ eapply IHp2 in H1. lia.
+Qed.
+
+Lemma max_reg_function_use:
+ forall l y m,
+ Forall (fun x => Ple x m) l ->
+ In y l ->
+ Ple y m.
+Proof.
+ intros. eapply Forall_forall in H; eauto.
+Qed.
+
+Lemma all_le_max_predicate_instr :
+ forall n ctrl bb curr_p stmnt next_p stmnt' max,
+ transf_instr n ctrl (curr_p, stmnt) bb = OK (next_p, stmnt') ->
+ Forall (fun x : positive => Ple x max) (pred_uses bb) ->
+ Ple (max_predicate curr_p) max ->
+ Ple (max_predicate next_p) max.
+Proof. Admitted.
+
+Lemma all_le_max_predicate :
+ forall n ctrl bb curr_p stmnt next_p stmnt' max,
+ mfold_left (transf_instr n ctrl) bb (OK (curr_p, stmnt)) = OK (next_p, stmnt') ->
+ Forall (fun i0 : instr => Forall (fun x : positive => Ple x max) (pred_uses i0)) bb ->
+ Ple (max_predicate curr_p) max ->
+ Ple (max_predicate next_p) max.
+Proof. Admitted.
+
+Lemma ple_max_resource_function:
+ forall f r,
+ Ple r (max_reg_function f) ->
+ Ple (reg_enc r) (max_resource_function f).
+Proof.
+ intros * Hple.
+ unfold max_resource_function, reg_enc, Ple in *. lia.
+Qed.
+
+Lemma ple_pred_max_resource_function:
+ forall f r,
+ Ple r (max_pred_function f) ->
+ Ple (pred_enc r) (max_resource_function f).
+Proof.
+ intros * Hple.
+ unfold max_resource_function, pred_enc, Ple in *. lia.
+Qed.
+
+Lemma mfold_left_error:
+ forall A B f l m, @mfold_left A B f l (Error m) = Error m.
+Proof. now induction l. Qed.
+
+Lemma mfold_left_cons:
+ forall A B f a l x y,
+ @mfold_left A B f (a :: l) x = OK y ->
+ exists x' y', @mfold_left A B f l (OK y') = OK y /\ f x' a = OK y' /\ x = OK x'.
+Proof.
+ intros.
+ destruct x; [|now rewrite mfold_left_error in H].
+ cbn in H.
+ replace (fold_left (fun (a : mon A) (b : B) => bind (fun a' : A => f a' b) a) l (f a0 a) = OK y) with
+ (mfold_left f l (f a0 a) = OK y) in H by auto.
+ destruct (f a0 a) eqn:?; [|now rewrite mfold_left_error in H].
+ eauto.
+Qed.
+
+Lemma mfold_left_app:
+ forall A B f a l x y,
+ @mfold_left A B f (a ++ l) x = OK y ->
+ exists y', @mfold_left A B f a x = OK y' /\ @mfold_left A B f l (OK y') = OK y.
+Proof.
+ induction a.
+ - intros. destruct x; [|now rewrite mfold_left_error in H]. exists a. eauto.
+ - intros. destruct x; [|now rewrite mfold_left_error in H]. rewrite <- app_comm_cons in H.
+ exploit mfold_left_cons; eauto.
+Qed.
+
+Section CORRECTNESS.
+
+ Variable prog : GibleSubPar.program.
+ Variable tprog : DHTL.program.
+
+ Hypothesis TRANSL : match_prog prog tprog.
+
+ Lemma TRANSL' :
+ Linking.match_program (fun cu f tf => transl_fundef f = Errors.OK tf) eq prog tprog.
+ Proof. intros; apply match_prog_matches; assumption. Qed.
+
+ Let ge : GibleSubPar.genv := Globalenvs.Genv.globalenv prog.
+ Let tge : DHTL.genv := Globalenvs.Genv.globalenv tprog.
+
+ Lemma symbols_preserved:
+ forall (s: AST.ident), Genv.find_symbol tge s = Genv.find_symbol ge s.
+ Proof. intros. eapply (Genv.find_symbol_match TRANSL'). Qed.
+
+ Lemma function_ptr_translated:
+ forall (b: Values.block) (f: GibleSubPar.fundef),
+ Genv.find_funct_ptr ge b = Some f ->
+ exists tf,
+ Genv.find_funct_ptr tge b = Some tf /\ transl_fundef f = Errors.OK tf.
+ Proof.
+ intros. exploit (Genv.find_funct_ptr_match TRANSL'); eauto.
+ intros (cu & tf & P & Q & R); exists tf; auto.
+ Qed.
+
+ Lemma functions_translated:
+ forall (v: Values.val) (f: GibleSubPar.fundef),
+ Genv.find_funct ge v = Some f ->
+ exists tf,
+ Genv.find_funct tge v = Some tf /\ transl_fundef f = Errors.OK tf.
+ Proof.
+ intros. exploit (Genv.find_funct_match TRANSL'); eauto.
+ intros (cu & tf & P & Q & R); exists tf; auto.
+ Qed.
+
+ Lemma senv_preserved:
+ Senv.equiv (Genv.to_senv ge) (Genv.to_senv tge).
+ Proof
+ (Genv.senv_transf_partial TRANSL').
+ #[local] Hint Resolve senv_preserved : htlproof.
+
+ Lemma ptrofs_inj :
+ forall a b,
+ Ptrofs.unsigned a = Ptrofs.unsigned b -> a = b.
+ Proof.
+ intros. rewrite <- Ptrofs.repr_unsigned. symmetry. rewrite <- Ptrofs.repr_unsigned.
+ rewrite H. auto.
+ Qed.
+
+ Lemma op_stack_based :
+ forall F V sp v m args rs op ge ver,
+ translate_instr op args = Errors.OK ver ->
+ reg_stack_based_pointers sp rs ->
+ @Op.eval_operation F V ge (Values.Vptr sp Ptrofs.zero) op
+ (List.map (fun r : positive => Registers.Regmap.get r rs) args) m = Some v ->
+ stack_based v sp.
+ Proof.
+ Ltac solve_no_ptr :=
+ match goal with
+ | H: reg_stack_based_pointers ?sp ?rs |- stack_based (Registers.Regmap.get ?r ?rs) _ =>
+ solve [apply H]
+ | H1: reg_stack_based_pointers ?sp ?rs, H2: Registers.Regmap.get _ _ = Values.Vptr ?b ?i
+ |- context[Values.Vptr ?b _] =>
+ let H := fresh "H" in
+ assert (H: stack_based (Values.Vptr b i) sp) by (rewrite <- H2; apply H1); simplify; solve [auto]
+ | |- context[Registers.Regmap.get ?lr ?lrs] =>
+ destruct (Registers.Regmap.get lr lrs) eqn:?; simplify; auto
+ | |- stack_based (?f _) _ => unfold f
+ | |- stack_based (?f _ _) _ => unfold f
+ | |- stack_based (?f _ _ _) _ => unfold f
+ | |- stack_based (?f _ _ _ _) _ => unfold f
+ | H: ?f _ _ = Some _ |- _ =>
+ unfold f in H; repeat (unfold_match H); inv H
+ | H: ?f _ _ _ _ _ _ = Some _ |- _ =>
+ unfold f in H; repeat (unfold_match H); inv H
+ | H: map (fun r : positive => Registers.Regmap.get r _) ?args = _ |- _ =>
+ destruct args; inv H
+ | |- context[if ?c then _ else _] => destruct c; try discriminate
+ | H: match _ with _ => _ end = Some _ |- _ => repeat (unfold_match H; try discriminate)
+ | H: match _ with _ => _ end = OK _ _ _ |- _ => repeat (unfold_match H; try discriminate)
+ | |- context[match ?g with _ => _ end] => destruct g; try discriminate
+ | |- _ => simplify; solve [auto]
+ end.
+ intros **.
+ unfold translate_instr in *.
+ unfold_match H; repeat (unfold_match H); simplify; try solve [repeat solve_no_ptr].
+ subst.
+ unfold translate_eff_addressing in H.
+ repeat (unfold_match H; try discriminate); simplify; try solve [repeat solve_no_ptr].
+ Qed.
+
+ Lemma int_inj :
+ forall x y,
+ Int.unsigned x = Int.unsigned y ->
+ x = y.
+ Proof.
+ intros. rewrite <- Int.repr_unsigned at 1. rewrite <- Int.repr_unsigned.
+ rewrite <- H. trivial.
+ Qed.
+
+ Lemma Ptrofs_compare_correct :
+ forall a b,
+ Ptrofs.ltu (valueToPtr a) (valueToPtr b) = Int.ltu a b.
+ Proof.
+ intros. unfold valueToPtr. unfold Ptrofs.ltu. unfold Ptrofs.of_int. unfold Int.ltu.
+ rewrite !Ptrofs.unsigned_repr in *; auto using Int.unsigned_range_2.
+ Qed.
+
+ Lemma eval_cond_correct :
+ forall stk f sp pc rs m res ml st asr asa e b f' args cond pr,
+ match_states (GibleSubPar.State stk f sp pc rs pr m) (DHTL.State res ml st asr asa) ->
+ (forall v, In v args -> Ple v (max_reg_function f)) ->
+ Op.eval_condition cond (List.map (fun r : positive => Registers.Regmap.get r rs) args) m = Some b ->
+ translate_condition cond args = OK e ->
+ Verilog.expr_runp f' asr asa e (boolToValue b).
+ Proof.
+ intros * MSTATE MAX_FUN EVAL TR_INSTR.
+ unfold translate_condition, translate_comparison, translate_comparisonu, translate_comparison_imm, translate_comparison_immu in TR_INSTR.
+ repeat (destruct_match; try discriminate); subst; unfold ret in *; match goal with H: OK _ = OK _ |- _ => inv H end; unfold bop in *; cbn in *;
+ try (solve [econstructor; try econstructor; eauto; unfold binop_run;
+ unfold Values.Val.cmp_bool, Values.Val.cmpu_bool in EVAL; repeat (destruct_match; try discriminate); inv EVAL;
+ inv MSTATE; inv MASSOC;
+ assert (X: Ple p (max_reg_function f)) by eauto;
+ assert (X1: Ple p0 (max_reg_function f)) by eauto;
+ apply H in X; apply H in X1;
+ rewrite Heqv in X;
+ rewrite Heqv0 in X1;
+ inv X; inv X1; auto; try (rewrite Ptrofs_compare_correct; auto)|
+ econstructor; try econstructor; eauto; unfold binop_run;
+ unfold Values.Val.cmp_bool, Values.Val.cmpu_bool in EVAL; repeat (destruct_match; try discriminate); inv EVAL;
+ inv MSTATE; inv MASSOC;
+ assert (X: Ple p (max_reg_function f)) by eauto;
+ apply H in X;
+ rewrite Heqv in X;
+ inv X; auto]).
+ Qed.
+
+ Lemma eval_cond_correct' :
+ forall e stk f sp pc rs m res ml st asr asa v f' args cond pr,
+ match_states (GibleSubPar.State stk f sp pc rs pr m) (DHTL.State res ml st asr asa) ->
+ (forall v, In v args -> Ple v (max_reg_function f)) ->
+ Values.Val.of_optbool None = v ->
+ translate_condition cond args = OK e ->
+ exists v', Verilog.expr_runp f' asr asa e v' /\ val_value_lessdef v v'.
+ Proof.
+ intros * MSTATE MAX_FUN EVAL TR_INSTR.
+ unfold translate_condition, translate_comparison, translate_comparisonu,
+ translate_comparison_imm, translate_comparison_immu, bop, boplit in *.
+ repeat unfold_match TR_INSTR; inv TR_INSTR; repeat econstructor.
+ Qed.
+
+ Ltac eval_correct_tac :=
+ match goal with
+ | |- context[valueToPtr] => unfold valueToPtr
+ | |- context[valueToInt] => unfold valueToInt
+ | |- context[bop] => unfold bop
+ | H : context[bop] |- _ => unfold bop in H
+ | |- context[boplit] => unfold boplit
+ | H : context[boplit] |- _ => unfold boplit in H
+ | |- context[boplitz] => unfold boplitz
+ | H : context[boplitz] |- _ => unfold boplitz in H
+ | |- val_value_lessdef Values.Vundef _ => solve [constructor]
+ | H : val_value_lessdef _ _ |- val_value_lessdef (Values.Vint _) _ => constructor; inv H
+ | |- val_value_lessdef (Values.Vint _) _ => constructor; auto
+ | H : ret _ _ = OK _ _ _ |- _ => inv H
+ | H : _ :: _ = _ :: _ |- _ => inv H
+ | |- context[match ?d with _ => _ end] => destruct d eqn:?; try discriminate
+ | H : match ?d with _ => _ end = _ |- _ => repeat unfold_match H
+ | H : match ?d with _ => _ end _ = _ |- _ => repeat unfold_match H
+ | |- Verilog.expr_runp _ _ _ ?f _ =>
+ match f with
+ | Verilog.Vternary _ _ _ => idtac
+ | _ => econstructor
+ end
+ | |- val_value_lessdef (?f _ _) _ => unfold f
+ | |- val_value_lessdef (?f _) _ => unfold f
+ | H : ?f (Registers.Regmap.get _ _) _ = Some _ |- _ =>
+ unfold f in H; repeat (unfold_match H)
+ | H1 : Registers.Regmap.get ?r ?rs = Values.Vint _, H2 : val_value_lessdef (Registers.Regmap.get ?r ?rs) _
+ |- _ => rewrite H1 in H2; inv H2
+ | |- _ => eexists; split; try constructor; solve [eauto]
+ | |- context[if ?c then _ else _] => destruct c eqn:?; try discriminate
+ | H : ?b = _ |- _ = boolToValue ?b => rewrite H
+ end.
+
+ Lemma eval_correct_Oshrximm :
+ forall sp rs m v e asr asa f f' stk pc args res ml st n pr,
+ match_states (GibleSubPar.State stk f sp pc rs pr m) (DHTL.State res ml st asr asa) ->
+ Forall (fun x => (Ple x (max_reg_function f))) args ->
+ Op.eval_operation ge sp (Op.Oshrximm n)
+ (List.map (fun r : BinNums.positive =>
+ Registers.Regmap.get r rs) args) m = Some v ->
+ translate_instr (Op.Oshrximm n) args = OK e ->
+ exists v', Verilog.expr_runp f' asr asa e v' /\ val_value_lessdef v v'.
+ Proof.
+ intros * MSTATE INSTR EVAL TR_INSTR.
+ pose proof MSTATE as MSTATE_2. inv MSTATE.
+ inv MASSOC. unfold translate_instr in TR_INSTR; repeat (unfold_match TR_INSTR); inv TR_INSTR;
+ unfold Op.eval_operation in EVAL; repeat (unfold_match EVAL); inv EVAL.
+ (*repeat (simplify; eval_correct_tac; unfold valueToInt in * ).
+ destruct (Z_lt_ge_dec (Int.signed i0) 0).
+ econstructor.*)
+ unfold Values.Val.shrx in *.
+ destruct v0; try discriminate.
+ destruct (Int.ltu n (Int.repr 31)) eqn:?; try discriminate.
+ inversion H2. clear H2.
+ assert (Int.unsigned n <= 30).
+ { unfold Int.ltu in *. destruct (zlt (Int.unsigned n) (Int.unsigned (Int.repr 31))); try discriminate.
+ rewrite Int.unsigned_repr in l by (simplify; lia).
+ replace 31 with (Z.succ 30) in l by auto.
+ apply Zlt_succ_le in l.
+ auto.
+ }
+ rewrite IntExtra.shrx_shrx_alt_equiv in H3 by auto.
+ unfold IntExtra.shrx_alt in *.
+ destruct (zlt (Int.signed i) 0).
+ - repeat econstructor; unfold valueToBool, boolToValue, uvalueToZ, natToValue;
+ repeat (simplify; eval_correct_tac).
+ unfold valueToInt in *. inv INSTR. apply H in H5. rewrite H4 in H5.
+ inv H5. clear H6.
+ unfold Int.lt in *. rewrite zlt_true in Heqb0. simplify.
+ rewrite Int.unsigned_repr in Heqb0. discriminate.
+ simplify; lia.
+ unfold ZToValue. rewrite Int.signed_repr by (simplify; lia).
+ auto.
+ rewrite IntExtra.shrx_shrx_alt_equiv; auto. unfold IntExtra.shrx_alt. rewrite zlt_true; try lia.
+ simplify. inv INSTR. clear H6. apply H in H5. rewrite H4 in H5. inv H5. auto.
+ - econstructor; econstructor; [eapply Verilog.erun_Vternary_false|idtac]; repeat econstructor; unfold valueToBool, boolToValue, uvalueToZ, natToValue;
+ repeat (simplify; eval_correct_tac).
+ inv INSTR. clear H6. apply H in H5. rewrite H4 in H5.
+ inv H5.
+ unfold Int.lt in *. rewrite zlt_false in Heqb0. simplify.
+ rewrite Int.unsigned_repr in Heqb0. lia.
+ simplify; lia.
+ unfold ZToValue. rewrite Int.signed_repr by (simplify; lia).
+ auto.
+ rewrite IntExtra.shrx_shrx_alt_equiv; auto. unfold IntExtra.shrx_alt. rewrite zlt_false; try lia.
+ simplify. inv INSTR. apply H in H5. unfold valueToInt in *. rewrite H4 in H5. inv H5. auto.
+ Qed.
+
+ Ltac eval_correct_tac' :=
+ match goal with
+ | |- context[valueToPtr] => unfold valueToPtr
+ | |- context[valueToInt] => unfold valueToInt
+ | |- context[bop] => unfold bop
+ | H : context[bop] |- _ => unfold bop in H
+ | |- context[boplit] => unfold boplit
+ | H : context[boplit] |- _ => unfold boplit in H
+ | |- context[boplitz] => unfold boplitz
+ | H : context[boplitz] |- _ => unfold boplitz in H
+ | |- val_value_lessdef Values.Vundef _ => solve [constructor]
+ | H : val_value_lessdef _ _ |- val_value_lessdef (Values.Vint _) _ => constructor; inv H
+ | |- val_value_lessdef (Values.Vint _) _ => constructor; auto
+ | H : ret _ _ = OK _ _ _ |- _ => inv H
+ | H : context[max_reg_function ?f]
+ |- context[_ (Registers.Regmap.get ?r ?rs) (Registers.Regmap.get ?r0 ?rs)] =>
+ let HPle1 := fresh "HPle" in
+ let HPle2 := fresh "HPle" in
+ assert (HPle1 : Ple r (max_reg_function f)) by (eapply max_reg_function_use; eauto; simpl; auto; repeat (apply in_cons; try solve [constructor; auto]));
+ assert (HPle2 : Ple r0 (max_reg_function f)) by (eapply max_reg_function_use; eauto; simpl; auto; repeat (apply in_cons; try solve [constructor; auto]));
+ apply H in HPle1; apply H in HPle2; eexists; split;
+ [econstructor; eauto; constructor; trivial | inv HPle1; inv HPle2; try (constructor; auto)]
+ | H : context[max_reg_function ?f]
+ |- context[_ (Registers.Regmap.get ?r ?rs) _] =>
+ let HPle1 := fresh "HPle" in
+ assert (HPle1 : Ple r (max_reg_function f)) by (eapply max_reg_function_use; eauto; simpl; auto; repeat (apply in_cons; try solve [constructor; auto]));
+ apply H in HPle1; eexists; split;
+ [econstructor; eauto; constructor; trivial | inv HPle1; try (constructor; auto)]
+ | H : _ :: _ = _ :: _ |- _ => inv H
+ | |- context[match ?d with _ => _ end] => destruct d eqn:?; try discriminate
+ | H : match ?d with _ => _ end = _ |- _ => repeat unfold_match H
+ | H : match ?d with _ => _ end _ = _ |- _ => repeat unfold_match H
+ | |- Verilog.expr_runp _ _ _ ?f _ =>
+ match f with
+ | Verilog.Vternary _ _ _ => idtac
+ | _ => econstructor
+ end
+ | |- val_value_lessdef (?f _ _) _ => unfold f
+ | |- val_value_lessdef (?f _) _ => unfold f
+ | H : ?f (Registers.Regmap.get _ _) _ = Some _ |- _ =>
+ unfold f in H; repeat (unfold_match H)
+ | H1 : Registers.Regmap.get ?r ?rs = Values.Vint _, H2 : val_value_lessdef (Registers.Regmap.get ?r ?rs) _
+ |- _ => rewrite H1 in H2; inv H2
+ | |- _ => eexists; split; try constructor; solve [eauto]
+ | H : context[max_reg_function ?f] |- context[_ (Verilog.Vvar ?r) (Verilog.Vvar ?r0)] =>
+ let HPle1 := fresh "H" in
+ let HPle2 := fresh "H" in
+ assert (HPle1 : Ple r (max_reg_function f)) by (eapply max_reg_function_use; eauto; simpl; auto; repeat (apply in_cons; try solve [constructor; auto]));
+ assert (HPle2 : Ple r0 (max_reg_function f)) by (eapply max_reg_function_use; eauto; simpl; auto; repeat (apply in_cons; try solve [constructor; auto]));
+ apply H in HPle1; apply H in HPle2; eexists; split; try constructor; eauto
+ | H : context[max_reg_function ?f] |- context[Verilog.Vvar ?r] =>
+ let HPle := fresh "H" in
+ assert (HPle : Ple r (max_reg_function f)) by (eapply max_reg_function_use; eauto; simpl; auto; repeat (apply in_cons; try solve [constructor; auto]));
+ apply H in HPle; eexists; split; try constructor; eauto
+ | |- context[if ?c then _ else _] => destruct c eqn:?; try discriminate
+ | H : ?b = _ |- _ = boolToValue ?b => rewrite H
+ end.
+
+ Lemma int_unsigned_lt_ptrofs_max :
+ forall a,
+ 0 <= Int.unsigned a <= Ptrofs.max_unsigned.
+ Proof.
+ intros. pose proof (Int.unsigned_range_2 a).
+ assert (Int.max_unsigned = Ptrofs.max_unsigned) by auto.
+ lia.
+ Qed.
+
+ Lemma ptrofs_unsigned_lt_int_max :
+ forall a,
+ 0 <= Ptrofs.unsigned a <= Int.max_unsigned.
+ Proof.
+ intros. pose proof (Ptrofs.unsigned_range_2 a).
+ assert (Int.max_unsigned = Ptrofs.max_unsigned) by auto.
+ lia.
+ Qed.
+
+ Hint Resolve int_unsigned_lt_ptrofs_max : int_ptrofs.
+ Hint Resolve ptrofs_unsigned_lt_int_max : int_ptrofs.
+ Hint Resolve Ptrofs.unsigned_range_2 : int_ptrofs.
+ Hint Resolve Int.unsigned_range_2 : int_ptrofs.
+
+(* Ptrofs.agree32_of_int_eq: forall (a : ptrofs) (b : int), Ptrofs.agree32 a b -> Ptrofs.of_int b = a *)
+(* Ptrofs.agree32_of_int: Archi.ptr64 = false -> forall b : int, Ptrofs.agree32 (Ptrofs.of_int b) b *)
+(* Ptrofs.agree32_sub: *)
+(* Archi.ptr64 = false -> *)
+(* forall (a1 : ptrofs) (b1 : int) (a2 : ptrofs) (b2 : int), *)
+(* Ptrofs.agree32 a1 b1 -> Ptrofs.agree32 a2 b2 -> Ptrofs.agree32 (Ptrofs.sub a1 a2) (Int.sub b1 b2) *)
+ Lemma eval_correct_sub :
+ forall a b a' b',
+ val_value_lessdef a a' ->
+ val_value_lessdef b b' ->
+ val_value_lessdef (Values.Val.sub a b) (Int.sub a' b').
+ Proof.
+ intros * HPLE HPLE0.
+ assert (ARCHI: Archi.ptr64 = false) by auto.
+ inv HPLE; inv HPLE0; cbn in *; unfold valueToInt; try solve [constructor; auto].
+ - rewrite ARCHI. constructor. unfold valueToPtr.
+ apply ptrofs_inj. unfold Ptrofs.of_int. rewrite Ptrofs.unsigned_repr; auto with int_ptrofs.
+ apply Ptrofs.agree32_sub; auto; rewrite <- Int.repr_unsigned; now apply Ptrofs.agree32_repr.
+ - rewrite ARCHI. destruct_match; constructor.
+ unfold Ptrofs.to_int. unfold valueToInt.
+ apply int_inj. rewrite Int.unsigned_repr; auto with int_ptrofs.
+ apply Ptrofs.agree32_sub; auto; unfold valueToPtr; now apply Ptrofs.agree32_of_int.
+ Qed.
+
+ Lemma eval_correct_mul :
+ forall a b a' b',
+ val_value_lessdef a a' ->
+ val_value_lessdef b b' ->
+ val_value_lessdef (Values.Val.mul a b) (Int.mul a' b').
+ Proof.
+ intros * HPLE HPLE0.
+ inv HPLE; inv HPLE0; cbn in *; unfold valueToInt; try solve [constructor; auto].
+ Qed.
+
+ Lemma eval_correct_mul' :
+ forall a a' n,
+ val_value_lessdef a a' ->
+ val_value_lessdef (Values.Val.mul a (Values.Vint n)) (Int.mul a' (intToValue n)).
+ Proof.
+ intros * HPLE.
+ inv HPLE; cbn in *; unfold valueToInt; try solve [constructor; auto].
+ Qed.
+
+ Lemma eval_correct_and :
+ forall a b a' b',
+ val_value_lessdef a a' ->
+ val_value_lessdef b b' ->
+ val_value_lessdef (Values.Val.and a b) (Int.and a' b').
+ Proof.
+ intros * HPLE HPLE0.
+ inv HPLE; inv HPLE0; cbn in *; unfold valueToInt; try solve [constructor; auto].
+ Qed.
+
+ Lemma eval_correct_and' :
+ forall a a' n,
+ val_value_lessdef a a' ->
+ val_value_lessdef (Values.Val.and a (Values.Vint n)) (Int.and a' (intToValue n)).
+ Proof.
+ intros * HPLE.
+ inv HPLE; cbn in *; unfold valueToInt; try solve [constructor; auto].
+ Qed.
+
+ Lemma eval_correct_or :
+ forall a b a' b',
+ val_value_lessdef a a' ->
+ val_value_lessdef b b' ->
+ val_value_lessdef (Values.Val.or a b) (Int.or a' b').
+ Proof.
+ intros * HPLE HPLE0.
+ inv HPLE; inv HPLE0; cbn in *; unfold valueToInt; try solve [constructor; auto].
+ Qed.
+
+ Lemma eval_correct_or' :
+ forall a a' n,
+ val_value_lessdef a a' ->
+ val_value_lessdef (Values.Val.or a (Values.Vint n)) (Int.or a' (intToValue n)).
+ Proof.
+ intros * HPLE.
+ inv HPLE; cbn in *; unfold valueToInt; try solve [constructor; auto].
+ Qed.
+
+ Lemma eval_correct_xor :
+ forall a b a' b',
+ val_value_lessdef a a' ->
+ val_value_lessdef b b' ->
+ val_value_lessdef (Values.Val.xor a b) (Int.xor a' b').
+ Proof.
+ intros * HPLE HPLE0.
+ inv HPLE; inv HPLE0; cbn in *; unfold valueToInt; try solve [constructor; auto].
+ Qed.
+
+ Lemma eval_correct_xor' :
+ forall a a' n,
+ val_value_lessdef a a' ->
+ val_value_lessdef (Values.Val.xor a (Values.Vint n)) (Int.xor a' (intToValue n)).
+ Proof.
+ intros * HPLE.
+ inv HPLE; cbn in *; unfold valueToInt; try solve [constructor; auto].
+ Qed.
+
+ Lemma eval_correct_shl :
+ forall a b a' b',
+ val_value_lessdef a a' ->
+ val_value_lessdef b b' ->
+ val_value_lessdef (Values.Val.shl a b) (Int.shl a' b').
+ Proof.
+ intros * HPLE HPLE0.
+ inv HPLE; inv HPLE0; cbn in *; unfold valueToInt; try destruct_match; now constructor.
+ Qed.
+
+ Lemma eval_correct_shl' :
+ forall a a' n,
+ val_value_lessdef a a' ->
+ val_value_lessdef (Values.Val.shl a (Values.Vint n)) (Int.shl a' (intToValue n)).
+ Proof.
+ intros * HPLE.
+ inv HPLE; cbn in *; unfold valueToInt; try destruct_match; now constructor.
+ Qed.
+
+ Lemma eval_correct_shr :
+ forall a b a' b',
+ val_value_lessdef a a' ->
+ val_value_lessdef b b' ->
+ val_value_lessdef (Values.Val.shr a b) (Int.shr a' b').
+ Proof.
+ intros * HPLE HPLE0.
+ inv HPLE; inv HPLE0; cbn in *; unfold valueToInt; try destruct_match; now constructor.
+ Qed.
+
+ Lemma eval_correct_shr' :
+ forall a a' n,
+ val_value_lessdef a a' ->
+ val_value_lessdef (Values.Val.shr a (Values.Vint n)) (Int.shr a' (intToValue n)).
+ Proof.
+ intros * HPLE.
+ inv HPLE; cbn in *; unfold valueToInt; try destruct_match; now constructor.
+ Qed.
+
+ Lemma eval_correct_shru :
+ forall a b a' b',
+ val_value_lessdef a a' ->
+ val_value_lessdef b b' ->
+ val_value_lessdef (Values.Val.shru a b) (Int.shru a' b').
+ Proof.
+ intros * HPLE HPLE0.
+ inv HPLE; inv HPLE0; cbn in *; unfold valueToInt; try destruct_match; now constructor.
+ Qed.
+
+ Lemma eval_correct_shru' :
+ forall a a' n,
+ val_value_lessdef a a' ->
+ val_value_lessdef (Values.Val.shru a (Values.Vint n)) (Int.shru a' (intToValue n)).
+ Proof.
+ intros * HPLE.
+ inv HPLE; cbn in *; unfold valueToInt; try destruct_match; now constructor.
+ Qed.
+
+ Lemma eval_correct_add :
+ forall a b a' b',
+ val_value_lessdef a a' ->
+ val_value_lessdef b b' ->
+ val_value_lessdef (Values.Val.add a b) (Int.add a' b').
+ Proof.
+ intros * HPLE HPLE0.
+ inv HPLE; inv HPLE0; cbn in *; unfold valueToInt;
+ try destruct_match; constructor; auto; unfold valueToPtr;
+ unfold Ptrofs.of_int; apply ptrofs_inj;
+ rewrite Ptrofs.unsigned_repr by auto with int_ptrofs;
+ [rewrite Int.add_commut|]; apply Ptrofs.agree32_add; auto;
+ rewrite <- Int.repr_unsigned; now apply Ptrofs.agree32_repr.
+ Qed.
+
+ Lemma eval_correct_add' :
+ forall a a' n,
+ val_value_lessdef a a' ->
+ val_value_lessdef (Values.Val.add a (Values.Vint n)) (Int.add a' (intToValue n)).
+ Proof.
+ intros * HPLE.
+ inv HPLE; cbn in *; unfold valueToInt; try destruct_match; try constructor; auto.
+ unfold valueToPtr. apply ptrofs_inj. unfold Ptrofs.of_int.
+ rewrite Ptrofs.unsigned_repr by auto with int_ptrofs.
+ apply Ptrofs.agree32_add; auto. rewrite <- Int.repr_unsigned.
+ apply Ptrofs.agree32_repr; auto.
+ unfold intToValue. rewrite <- Int.repr_unsigned.
+ apply Ptrofs.agree32_repr; auto.
+ Qed.
+
+ Lemma eval_correct :
+ forall sp op rs m v e asr asa f f' stk pc args res ml st pr,
+ match_states (GibleSubPar.State stk f sp pc rs pr m) (DHTL.State res ml st asr asa) ->
+ Forall (fun x => (Ple x (max_reg_function f))) args ->
+ Op.eval_operation ge sp op
+ (List.map (fun r : BinNums.positive => Registers.Regmap.get r rs) args) m = Some v ->
+ translate_instr op args = OK e ->
+ exists v', Verilog.expr_runp f' asr asa e v' /\ val_value_lessdef v v'.
+ Proof.
+ intros * MSTATE INSTR EVAL TR_INSTR.
+ pose proof MSTATE as MSTATE_2. inv MSTATE.
+ inv MASSOC. unfold translate_instr in TR_INSTR; repeat (unfold_match TR_INSTR); inv TR_INSTR;
+ unfold Op.eval_operation in EVAL; repeat (unfold_match EVAL); inv EVAL;
+ repeat (simplify; eval_correct_tac; unfold valueToInt in *);
+ repeat (apply Forall_cons_iff in INSTR; destruct INSTR as (?HPLE & INSTR));
+ try (apply H in HPLE); try (apply H in HPLE0).
+ - do 2 econstructor; eauto. repeat econstructor.
+ - do 2 econstructor; eauto. repeat econstructor. cbn.
+ inv HPLE; cbn; try solve [constructor]; unfold valueToInt in *.
+ constructor; unfold valueToInt; auto.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_sub.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_mul.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_mul'.
+ - inv H2. rewrite Heqv0 in HPLE. inv HPLE. rewrite Heqv1 in HPLE0. inv HPLE0. unfold valueToInt in *.
+ do 2 econstructor; eauto. repeat econstructor. unfold binop_run.
+ rewrite Heqb. auto. constructor; auto.
+ - inv H2. rewrite Heqv0 in HPLE. inv HPLE. rewrite Heqv1 in HPLE0. inv HPLE0. unfold valueToInt in *.
+ do 2 econstructor; eauto. repeat econstructor. unfold binop_run.
+ rewrite Heqb. auto. constructor; auto.
+ - inv H2. rewrite Heqv0 in HPLE. inv HPLE. rewrite Heqv1 in HPLE0. inv HPLE0. unfold valueToInt in *.
+ do 2 econstructor; eauto. repeat econstructor. unfold binop_run.
+ rewrite Heqb. auto. constructor; auto.
+ - inv H2. rewrite Heqv0 in HPLE. inv HPLE. rewrite Heqv1 in HPLE0. inv HPLE0. unfold valueToInt in *.
+ do 2 econstructor; eauto. repeat econstructor. unfold binop_run.
+ rewrite Heqb. auto. constructor; auto.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_and.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_and'.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_or.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_or'.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_xor.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_xor'.
+ - do 2 econstructor; eauto. repeat econstructor. cbn. inv HPLE; now constructor.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_shl.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_shl'.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_shr.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_shr'.
+ - inv H2. rewrite Heqv0 in HPLE. inv HPLE.
+ assert (0 <= 31 <= Int.max_unsigned).
+ { pose proof Int.two_wordsize_max_unsigned as Y.
+ unfold Int.zwordsize, Int.wordsize, Wordsize_32.wordsize in Y. lia. }
+ assert (Int.unsigned n <= 30).
+ { unfold Int.ltu in Heqb. destruct_match; try discriminate.
+ clear Heqs. rewrite Int.unsigned_repr in l by auto. lia. }
+ rewrite IntExtra.shrx_shrx_alt_equiv by auto.
+ case_eq (Int.lt (find_assocmap 32 (reg_enc p) asr) (ZToValue 0)); intros HLT.
+ + assert ((if zlt (Int.signed (valueToInt (find_assocmap 32 (reg_enc p) asr))) 0 then true else false) = true).
+ { destruct_match; auto; unfold valueToInt in *. exfalso.
+ assert (Int.signed (find_assocmap 32 (reg_enc p) asr) < 0 -> False) by auto. apply H3. unfold Int.lt in HLT.
+ destruct_match; try discriminate. auto. }
+ destruct_match; try discriminate.
+ do 2 econstructor; eauto. repeat econstructor. now rewrite HLT.
+ constructor; cbn. unfold IntExtra.shrx_alt. rewrite Heqs. auto.
+ + assert ((if zlt (Int.signed (valueToInt (find_assocmap 32 (reg_enc p) asr))) 0 then true else false) = false).
+ { destruct_match; auto; unfold valueToInt in *. exfalso.
+ assert (Int.signed (find_assocmap 32 (reg_enc p) asr) >= 0 -> False) by auto. apply H3. unfold Int.lt in HLT.
+ destruct_match; try discriminate. auto. }
+ destruct_match; try discriminate.
+ do 2 econstructor; eauto. eapply erun_Vternary_false; repeat econstructor.
+ now rewrite HLT.
+ constructor; cbn. unfold IntExtra.shrx_alt. rewrite Heqs. auto.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_shru.
+ - do 2 econstructor; eauto. repeat econstructor. now apply eval_correct_shru'.
+ - unfold translate_eff_addressing in H2.
+ repeat (destruct_match; try discriminate); unfold boplitz in *; simplify;
+ repeat (apply Forall_cons_iff in INSTR; destruct INSTR as (?HPLE & INSTR));
+ try (apply H in HPLE); try (apply H in HPLE0).
+ + inv H2. do 2 econstructor; eauto. repeat econstructor. unfold ZToValue.
+ now apply eval_correct_add'.
+ + inv H2. do 2 econstructor; eauto. repeat econstructor. unfold ZToValue.
+ apply eval_correct_add; auto. apply eval_correct_add; auto.
+ constructor; auto.
+ + inv H2. do 2 econstructor; eauto. repeat econstructor. unfold ZToValue.
+ apply eval_correct_add; try constructor; auto.
+ apply eval_correct_mul; try constructor; auto.
+ + inv H2. do 2 econstructor; eauto. repeat econstructor. unfold ZToValue.
+ apply eval_correct_add; try constructor; auto.
+ apply eval_correct_add; try constructor; auto.
+ apply eval_correct_mul; try constructor; auto.
+ + inv H2. do 2 econstructor; eauto. repeat econstructor. unfold ZToValue.
+ assert (X: Archi.ptr64 = false) by auto.
+ rewrite X in H3. inv H3.
+ constructor. unfold valueToPtr. unfold Ptrofs.of_int.
+ rewrite Int.unsigned_repr by auto with int_ptrofs.
+ rewrite Ptrofs.repr_unsigned. apply Ptrofs.add_zero_l.
+ - remember (Op.eval_condition cond (List.map (fun r : positive => rs !! r) args) m).
+ destruct o. cbn. symmetry in Heqo.
+ exploit eval_cond_correct; eauto. intros. apply Forall_forall with (x := v) in INSTR; auto.
+ intros. econstructor. split. eauto. destruct b; constructor; auto.
+ exploit eval_cond_correct'; eauto.
+ intros. apply Forall_forall with (x := v) in INSTR; auto.
+ - assert (HARCHI: Archi.ptr64 = false) by auto.
+ unfold Errors.bind in *. destruct_match; try discriminate; []. inv H2.
+ remember (Op.eval_condition c (List.map (fun r : positive => rs !! r) l0) m).
+ destruct o; cbn; symmetry in Heqo.
+ + exploit eval_cond_correct; eauto. intros. apply Forall_forall with (x := v) in INSTR; auto.
+ intros. destruct b.
+ * intros. econstructor. split. econstructor. eauto. econstructor; auto. auto.
+ unfold Values.Val.normalize. rewrite HARCHI. destruct_match; auto; constructor.
+ * intros. econstructor. split. eapply erun_Vternary_false; repeat econstructor. eauto. auto.
+ unfold Values.Val.normalize. rewrite HARCHI. destruct_match; auto; constructor.
+ + exploit eval_cond_correct'; eauto.
+ intros. apply Forall_forall with (x := v) in INSTR; auto. simplify.
+ case_eq (valueToBool x); intros HVALU.
+ * econstructor. econstructor. econstructor. eauto. constructor. eauto. auto. constructor.
+ * econstructor. econstructor. eapply erun_Vternary_false. eauto. constructor. eauto. auto. constructor.
+ Qed.
+
+Ltac name_goal name := refine ?[name].
+
+Ltac unfold_merge :=
+ unfold merge_assocmap; repeat (rewrite AssocMapExt.merge_add_assoc);
+ try (rewrite AssocMapExt.merge_base_1).
+
+ Lemma match_assocmaps_merge_empty:
+ forall n m rs ps ars,
+ match_assocmaps n m rs ps ars ->
+ match_assocmaps n m rs ps (AssocMapExt.merge value empty_assocmap ars).
+ Proof.
+ inversion 1; subst; clear H.
+ constructor; intros.
+ rewrite merge_get_default2 by auto. auto.
+ rewrite merge_get_default2 by auto. auto.
+ Qed.
+
+ Lemma match_constants_merge_empty:
+ forall n m ars,
+ match_constants n m ars ->
+ match_constants n m (AssocMapExt.merge value empty_assocmap ars).
+ Proof.
+ inversion 1. constructor; unfold AssocMapExt.merge.
+ - rewrite PTree.gcombine; auto.
+ - rewrite PTree.gcombine; auto.
+ Qed.
+
+ Lemma match_state_st_wf_empty:
+ forall asr st pc,
+ state_st_wf asr st pc ->
+ state_st_wf (AssocMapExt.merge value empty_assocmap asr) st pc.
+ Proof.
+ unfold state_st_wf; intros.
+ unfold AssocMapExt.merge. rewrite AssocMap.gcombine by auto. rewrite H.
+ rewrite AssocMap.gempty. auto.
+ Qed.
+
+ Lemma match_arrs_merge_empty:
+ forall sz stk stk_len sp mem asa,
+ match_arrs sz stk stk_len sp mem asa ->
+ match_arrs sz stk stk_len sp mem (merge_arrs (DHTL.empty_stack stk stk_len) asa).
+ Proof.
+ inversion 1. inv H0. inv H3. inv H1. destruct stack. econstructor; unfold AssocMapExt.merge.
+ split; [|split]; [| |split]; cbn in *.
+ - unfold merge_arrs in *. rewrite AssocMap.gcombine by auto.
+ setoid_rewrite H2. unfold DHTL.empty_stack. rewrite AssocMap.gss.
+ cbn in *. eauto.
+ - cbn. rewrite list_combine_length. rewrite list_repeat_len. lia.
+ - cbn. rewrite list_combine_length. rewrite list_repeat_len. lia.
+ - cbn; intros.
+ assert ((Datatypes.length (list_combine merge_cell (list_repeat None arr_length) arr_contents)) = arr_length).
+ { rewrite list_combine_length. rewrite list_repeat_len. lia. }
+ rewrite H3 in H1. apply H4 in H1.
+ inv H1; try constructor.
+ assert (array_get_error (Z.to_nat ptr)
+ {| arr_contents := arr_contents; arr_length := Datatypes.length arr_contents; arr_wf := eq_refl |} =
+ (array_get_error (Z.to_nat ptr)
+ (combine merge_cell (arr_repeat None (Datatypes.length arr_contents))
+ {| arr_contents := arr_contents; arr_length := Datatypes.length arr_contents; arr_wf := eq_refl |}))).
+ { apply array_get_error_equal; auto. cbn. now rewrite list_combine_none. }
+ unfold get_mem in *.
+ rewrite <- H1. auto.
+ Qed.
+
+ Lemma match_states_merge_empty :
+ forall st f sp pc rs ps m st' modle asr asa,
+ match_states (GibleSubPar.State st f sp pc rs ps m) (DHTL.State st' modle pc asr asa) ->
+ match_states (GibleSubPar.State st f sp pc rs ps m) (DHTL.State st' modle pc (AssocMapExt.merge value empty_assocmap asr) asa).
+ Proof.
+ inversion 1; econstructor; eauto using match_assocmaps_merge_empty,
+ match_constants_merge_empty, match_state_st_wf_empty.
+ Qed.
+
+ Lemma match_states_merge_empty_arr :
+ forall st f sp pc rs ps m st' modle asr asa,
+ match_states (GibleSubPar.State st f sp pc rs ps m) (DHTL.State st' modle pc asr asa) ->
+ match_states (GibleSubPar.State st f sp pc rs ps m) (DHTL.State st' modle pc asr (merge_arrs (DHTL.empty_stack modle.(DHTL.mod_stk) modle.(DHTL.mod_stk_len)) asa)).
+ Proof. inversion 1; econstructor; eauto using match_arrs_merge_empty. Qed.
+
+ Lemma match_states_merge_empty_all :
+ forall st f sp pc rs ps m st' modle asr asa,
+ match_states (GibleSubPar.State st f sp pc rs ps m) (DHTL.State st' modle pc asr asa) ->
+ match_states (GibleSubPar.State st f sp pc rs ps m) (DHTL.State st' modle pc (AssocMapExt.merge value empty_assocmap asr) (merge_arrs (DHTL.empty_stack modle.(DHTL.mod_stk) modle.(DHTL.mod_stk_len)) asa)).
+ Proof. eauto using match_states_merge_empty, match_states_merge_empty_arr. Qed.
+
+ Opaque AssocMap.get.
+ Opaque AssocMap.set.
+ Opaque AssocMapExt.merge.
+ Opaque Verilog.merge_arr.
+
+ Lemma match_assocmaps_ext :
+ forall n m rs ps ars1 ars2,
+ (forall x, Ple x n -> ars1 ! (reg_enc x) = ars2 ! (reg_enc x)) ->
+ (forall x, Ple x m -> ars1 ! (pred_enc x) = ars2 ! (pred_enc x)) ->
+ match_assocmaps n m rs ps ars1 ->
+ match_assocmaps n m rs ps ars2.
+ Proof.
+ intros * YFRL YFRL2 YMATCH.
+ inv YMATCH. constructor; intros x' YPLE.
+ unfold "#", AssocMapExt.get_default in *.
+ rewrite <- YFRL by auto. eauto.
+ unfold "#", AssocMapExt.get_default. rewrite <- YFRL2 by auto. eauto.
+ Qed.
+
+ Definition e_assoc asr : reg_associations := mkassociations asr (AssocMap.empty _).
+ Definition e_assoc_arr stk stk_len asr : arr_associations := mkassociations asr (DHTL.empty_stack stk stk_len).
+
+ Lemma option_inv :
+ forall A x y,
+ @Some A x = Some y -> x = y.
+ Proof. intros. inversion H. trivial. Qed.
+
+ Lemma main_tprog_internal :
+ forall b,
+ Globalenvs.Genv.find_symbol tge tprog.(AST.prog_main) = Some b ->
+ exists f, Genv.find_funct_ptr (Genv.globalenv tprog) b = Some (AST.Internal f).
+ Proof.
+ intros.
+ destruct TRANSL. unfold main_is_internal in H1.
+ repeat (unfold_match H1). replace b with b0.
+ exploit function_ptr_translated; eauto. intros [tf [A B]].
+ unfold transl_fundef, AST.transf_partial_fundef, Errors.bind in B.
+ unfold_match B. inv B. econstructor. apply A.
+
+ apply option_inv. rewrite <- Heqo. rewrite <- H.
+ rewrite symbols_preserved. replace (AST.prog_main tprog) with (AST.prog_main prog).
+ trivial. symmetry; eapply Linking.match_program_main; eauto.
+ Qed.
+
+ Lemma transl_initial_states :
+ forall s1 : Smallstep.state (GibleSubPar.semantics prog),
+ Smallstep.initial_state (GibleSubPar.semantics prog) s1 ->
+ exists s2 : Smallstep.state (DHTL.semantics tprog),
+ Smallstep.initial_state (DHTL.semantics tprog) s2 /\ match_states s1 s2.
+ Proof.
+ induction 1.
+ destruct TRANSL. unfold main_is_internal in H4.
+ repeat (unfold_match H4).
+ assert (f = AST.Internal f1). apply option_inv.
+ rewrite <- Heqo0. rewrite <- H1. replace b with b0.
+ auto. apply option_inv. rewrite <- H0. rewrite <- Heqo.
+ trivial.
+ exploit function_ptr_translated; eauto.
+ intros [tf [A B]].
+ unfold transl_fundef, Errors.bind in B.
+ unfold AST.transf_partial_fundef, Errors.bind in B.
+ repeat (unfold_match B). inversion B. subst.
+ exploit main_tprog_internal; eauto; intros.
+ rewrite symbols_preserved. replace (AST.prog_main tprog) with (AST.prog_main prog).
+ apply Heqo. symmetry; eapply Linking.match_program_main; eauto.
+ inversion H5.
+ econstructor; split. econstructor.
+ apply (Genv.init_mem_transf_partial TRANSL'); eauto.
+ replace (AST.prog_main tprog) with (AST.prog_main prog).
+ rewrite symbols_preserved; eauto.
+ symmetry; eapply Linking.match_program_main; eauto.
+ apply H6.
+
+ constructor. inv B.
+ assert (Some (AST.Internal x) = Some (AST.Internal m)).
+ replace (AST.fundef DHTL.module) with (DHTL.fundef).
+ rewrite <- H6. setoid_rewrite <- A. trivial.
+ trivial. inv H7. assumption.
+ Qed.
+ #[local] Hint Resolve transl_initial_states : htlproof.
+
+ Lemma transl_final_states :
+ forall (s1 : Smallstep.state (GibleSubPar.semantics prog))
+ (s2 : Smallstep.state (DHTL.semantics tprog))
+ (r : Integers.Int.int),
+ match_states s1 s2 ->
+ Smallstep.final_state (GibleSubPar.semantics prog) s1 r ->
+ Smallstep.final_state (DHTL.semantics tprog) s2 r.
+ Proof.
+ intros. inv H0. inv H. inv H4. inv MF. constructor. reflexivity.
+ Qed.
+ #[local] Hint Resolve transl_final_states : htlproof.
+
+ Lemma stack_correct_inv :
+ forall s,
+ stack_correct s = true ->
+ (0 <= s) /\ (s < Ptrofs.modulus) /\ (s mod 4 = 0).
+ Proof.
+ unfold stack_correct; intros.
+ crush.
+ Qed.
+
+ Lemma init_regs_empty:
+ forall l, init_regs nil l = (Registers.Regmap.init Values.Vundef).
+ Proof. destruct l; auto. Qed.
+
+ Lemma dhtl_init_regs_empty:
+ forall l, DHTL.init_regs nil l = (AssocMap.empty _).
+ Proof. destruct l; auto. Qed.
+
+Lemma assocmap_gempty :
+ forall n a,
+ find_assocmap n a (AssocMap.empty _) = ZToValue 0.
+Proof.
+ intros. unfold find_assocmap, AssocMapExt.get_default.
+ now rewrite AssocMap.gempty.
+Qed.
+
+ Definition mk_ctrl f := {|
+ ctrl_st := Pos.succ (max_resource_function f);
+ ctrl_stack := Pos.succ (Pos.succ (Pos.succ (Pos.succ (max_resource_function f))));
+ ctrl_fin := Pos.succ (Pos.succ (max_resource_function f));
+ ctrl_return := Pos.succ (Pos.succ (Pos.succ (max_resource_function f)))
+ |}.
+
+Transparent Mem.load.
+Transparent Mem.store.
+Transparent Mem.alloc.
+ Lemma transl_callstate_correct:
+ forall (s : list GibleSubPar.stackframe) (f : GibleSubPar.function) (args : list Values.val)
+ (m : mem) (m' : Mem.mem') (stk : Values.block),
+ Mem.alloc m 0 (GibleSubPar.fn_stacksize f) = (m', stk) ->
+ forall R1 : DHTL.state,
+ match_states (GibleSubPar.Callstate s (AST.Internal f) args m) R1 ->
+ exists R2 : DHTL.state,
+ Smallstep.plus DHTL.step tge R1 Events.E0 R2 /\
+ match_states
+ (GibleSubPar.State s f (Values.Vptr stk Integers.Ptrofs.zero) (GibleSubPar.fn_entrypoint f)
+ (Gible.init_regs args (GibleSubPar.fn_params f)) (PMap.init false) m') R2.
+ Proof.
+ intros * H R1 MSTATE.
+
+ inversion MSTATE; subst. inversion TF; subst.
+ econstructor. split. apply Smallstep.plus_one.
+ eapply DHTL.step_call.
+
+ unfold transl_module, Errors.bind, Errors.bind2, ret in *.
+ repeat (destruct_match; try discriminate; []). inv TF. cbn.
+ econstructor; eauto; inv MSTATE; inv H1; eauto.
+
+ - constructor; intros.
+ + pose proof (ple_max_resource_function f r H0) as Hple.
+ unfold Ple in *. repeat rewrite assocmap_gso by lia. rewrite init_regs_empty.
+ rewrite dhtl_init_regs_empty. rewrite assocmap_gempty. rewrite Registers.Regmap.gi.
+ constructor.
+ + pose proof (ple_pred_max_resource_function f r H0) as Hple.
+ unfold Ple in *. repeat rewrite assocmap_gso by lia.
+ rewrite dhtl_init_regs_empty. rewrite assocmap_gempty. rewrite PMap.gi.
+ auto.
+ - cbn in *. unfold state_st_wf. repeat rewrite AssocMap.gso by lia.
+ now rewrite AssocMap.gss.
+ - constructor.
+ - unfold DHTL.empty_stack. cbn in *. econstructor. repeat split; intros.
+ + now rewrite AssocMap.gss.
+ + cbn. now rewrite list_repeat_len.
+ + cbn. now rewrite list_repeat_len.
+ + destruct (Mem.loadv Mint32 m' (Values.Val.offset_ptr (Values.Vptr stk Ptrofs.zero) (Ptrofs.repr (4 * ptr)))) eqn:Heqn; constructor.
+ unfold Mem.loadv in Heqn. destruct_match; try discriminate. cbn in Heqv0.
+ symmetry in Heqv0. inv Heqv0.
+ pose proof Mem.load_alloc_same as LOAD_ALLOC.
+ pose proof H as ALLOC.
+ eapply LOAD_ALLOC in ALLOC; eauto; subst. constructor.
+ - unfold reg_stack_based_pointers; intros. unfold stack_based.
+ unfold init_regs;
+ destruct (GibleSubPar.fn_params f);
+ rewrite Registers.Regmap.gi; constructor.
+ - unfold arr_stack_based_pointers; intros. unfold stack_based.
+ destruct (Mem.loadv Mint32 m' (Values.Val.offset_ptr (Values.Vptr stk Ptrofs.zero) (Ptrofs.repr (4 * ptr)))) eqn:LOAD; cbn; auto.
+ pose proof Mem.load_alloc_same as LOAD_ALLOC.
+ pose proof H as ALLOC.
+ eapply LOAD_ALLOC in ALLOC. now rewrite ALLOC.
+ exact LOAD.
+ - unfold stack_bounds; intros. split.
+ + unfold Mem.loadv. destruct_match; auto.
+ unfold Mem.load, Mem.alloc in *. inv H. cbn -[Ptrofs.max_unsigned] in *.
+ destruct_match; auto. unfold Mem.valid_access, Mem.range_perm, Mem.perm, Mem.perm_order' in *.
+ clear Heqs2. inv v0. cbn -[Ptrofs.max_unsigned] in *. inv Heqv0. exfalso.
+ specialize (H ptr). rewrite ! Ptrofs.add_zero_l in H. rewrite ! Ptrofs.unsigned_repr in H.
+ specialize (H ltac:(lia)). destruct_match; auto. rewrite PMap.gss in Heqo.
+ destruct_match; try discriminate. simplify. apply proj_sumbool_true in H5. lia.
+ apply stack_correct_inv in Heqb. lia.
+ + unfold Mem.storev. destruct_match; auto.
+ unfold Mem.store, Mem.alloc in *. inv H. cbn -[Ptrofs.max_unsigned] in *.
+ destruct_match; auto. unfold Mem.valid_access, Mem.range_perm, Mem.perm, Mem.perm_order' in *.
+ clear Heqs2. inv v0. cbn -[Ptrofs.max_unsigned] in *. inv Heqv0. exfalso.
+ specialize (H ptr). rewrite ! Ptrofs.add_zero_l in H. rewrite ! Ptrofs.unsigned_repr in H.
+ specialize (H ltac:(lia)). destruct_match; auto. rewrite PMap.gss in Heqo.
+ destruct_match; try discriminate. simplify. apply proj_sumbool_true in H5. lia.
+ apply stack_correct_inv in Heqb. lia.
+ - cbn; constructor; repeat rewrite PTree.gso by lia; now rewrite PTree.gss.
+ Qed.
+Opaque Mem.load.
+Opaque Mem.store.
+Opaque Mem.alloc.
+
+ Lemma transl_returnstate_correct:
+ forall (res0 : Registers.reg) (f : GibleSubPar.function) (sp : Values.val) (pc : Gible.node)
+ (rs : Gible.regset) (s : list GibleSubPar.stackframe) (vres : Values.val) (m : mem) ps
+ (R1 : DHTL.state),
+ match_states (GibleSubPar.Returnstate (GibleSubPar.Stackframe res0 f sp pc rs ps :: s) vres m) R1 ->
+ exists R2 : DHTL.state,
+ Smallstep.plus DHTL.step tge R1 Events.E0 R2 /\
+ match_states (GibleSubPar.State s f sp pc (Registers.Regmap.set res0 vres rs) ps m) R2.
+ Proof.
+ intros * MSTATE.
+ inversion MSTATE. inversion MF.
+ Qed.
+ #[local] Hint Resolve transl_returnstate_correct : htlproof.
+
+ Lemma step_cf_instr_pc_ind :
+ forall s f sp rs' pr' m' pc pc' cf t state,
+ step_cf_instr ge (GibleSubPar.State s f sp pc rs' pr' m') cf t state ->
+ step_cf_instr ge (GibleSubPar.State s f sp pc' rs' pr' m') cf t state.
+ Proof. destruct cf; intros; inv H; econstructor; eauto. Qed.
+
+ Lemma step_list_inter_not_term :
+ forall A step_i sp i cf l i' cf',
+ @step_list_inter A step_i sp (Iterm i cf) l (Iterm i' cf') ->
+ i = i' /\ cf = cf'.
+ Proof. now inversion 1. Qed.
+
+ Lemma step_instr_finish :
+ forall sp i l i' cf',
+ step_instr ge sp (Iexec i) l (Iterm i' cf') ->
+ i = i'.
+ Proof. now inversion 1. Qed.
+
+ Lemma step_exec_concat2' :
+ forall sp i c a l cf,
+ SubParBB.step_instr_list ge sp (Iexec a) i (Iterm c cf) ->
+ SubParBB.step_instr_list ge sp (Iexec a) (i ++ l) (Iterm c cf).
+ Proof.
+ induction i.
+ - inversion 1.
+ - inversion 1; subst; clear H; cbn.
+ destruct i1. econstructor; eauto. eapply IHi; eauto.
+ exploit step_list_inter_not_term; eauto; intros. inv H.
+ eapply exec_term_RBcons; eauto. eapply exec_term_RBcons_term.
+ Qed.
+
+ Lemma step_exec_concat' :
+ forall sp i c a b l,
+ SubParBB.step_instr_list ge sp (Iexec a) i (Iexec c) ->
+ SubParBB.step_instr_list ge sp (Iexec c) l b ->
+ SubParBB.step_instr_list ge sp (Iexec a) (i ++ l) b.
+ Proof.
+ induction i.
+ - inversion 1. eauto.
+ - inversion 1; subst. clear H. cbn. intros. econstructor; eauto.
+ destruct i1; [|inversion H6].
+ eapply IHi; eauto.
+ Qed.
+
+ Lemma step_exec_concat:
+ forall sp bb a b,
+ SubParBB.step ge sp a bb b ->
+ SubParBB.step_instr_list ge sp a (concat bb) b.
+ Proof.
+ induction bb.
+ - inversion 1.
+ - inversion 1; subst; clear H.
+ + cbn. eapply step_exec_concat'; eauto.
+ + cbn in *. eapply step_exec_concat2'; eauto.
+ Qed.
+
+ Lemma one_ne_zero:
+ Int.repr 1 <> Int.repr 0.
+ Proof.
+ unfold not; intros.
+ assert (Int.unsigned (Int.repr 1) = Int.unsigned (Int.repr 0)) by (now rewrite H).
+ rewrite ! Int.unsigned_repr in H0 by crush. lia.
+ Qed.
+
+ Lemma int_and_boolToValue :
+ forall b1 b2,
+ Int.and (boolToValue b1) (boolToValue b2) = boolToValue (b1 && b2).
+ Proof.
+ destruct b1; destruct b2; cbn; unfold boolToValue; unfold natToValue;
+ replace (Z.of_nat 1) with 1 by auto;
+ replace (Z.of_nat 0) with 0 by auto.
+ - apply Int.and_idem.
+ - apply Int.and_zero.
+ - apply Int.and_zero_l.
+ - apply Int.and_zero.
+ Qed.
+
+ Lemma int_or_boolToValue :
+ forall b1 b2,
+ Int.or (boolToValue b1) (boolToValue b2) = boolToValue (b1 || b2).
+ Proof.
+ destruct b1; destruct b2; cbn; unfold boolToValue; unfold natToValue;
+ replace (Z.of_nat 1) with 1 by auto;
+ replace (Z.of_nat 0) with 0 by auto.
+ - apply Int.or_idem.
+ - apply Int.or_zero.
+ - apply Int.or_zero_l.
+ - apply Int.or_zero_l.
+ Qed.
+
+ Lemma pred_expr_correct :
+ forall curr_p pr asr asa,
+ (forall r, Ple r (max_predicate curr_p) ->
+ find_assocmap 1 (pred_enc r) asr = boolToValue (PMap.get r pr)) ->
+ expr_runp tt asr asa (pred_expr curr_p) (boolToValue (eval_predf pr curr_p)).
+ Proof.
+ induction curr_p.
+ - intros * HFRL. cbn. destruct p as [b p']. destruct b.
+ + constructor. eapply HFRL. cbn. unfold Ple. lia.
+ + econstructor. constructor. eapply HFRL. cbn. unfold Ple; lia.
+ econstructor. cbn. f_equal. unfold boolToValue.
+ f_equal. destruct pr !! p' eqn:?. cbn.
+ rewrite Int.eq_false; auto. unfold natToValue.
+ replace (Z.of_nat 1) with 1 by auto. unfold Int.zero.
+ apply one_ne_zero.
+ cbn. rewrite Int.eq_true; auto.
+ - intros. cbn. constructor.
+ - intros. cbn. constructor.
+ - cbn -[eval_predf]; intros. econstructor. eapply IHcurr_p1. intros. eapply H.
+ unfold Ple in *. lia.
+ eapply IHcurr_p2; intros. eapply H. unfold Ple in *; lia.
+ cbn -[eval_predf]. f_equal. symmetry. apply int_and_boolToValue.
+ - cbn -[eval_predf]; intros. econstructor. eapply IHcurr_p1. intros. eapply H.
+ unfold Ple in *. lia.
+ eapply IHcurr_p2; intros. eapply H. unfold Ple in *; lia.
+ cbn -[eval_predf]. f_equal. symmetry. apply int_or_boolToValue.
+ Qed.
+
+ Local Opaque deep_simplify.
+
+ Lemma valueToBool_correct:
+ forall b,
+ valueToBool (boolToValue b) = b.
+ Proof.
+ unfold valueToBool, boolToValue; intros.
+ unfold uvalueToZ, natToValue. destruct b; cbn;
+ rewrite Int.unsigned_repr; crush.
+ Qed.
+
+ Lemma negb_inj':
+ forall a b, a = b -> negb a = negb b.
+ Proof. intros. destruct a, b; auto. Qed.
+
+ Lemma transl_predicate_correct :
+ forall asr asa a b asr' asa' p r e max_pred max_reg rs ps,
+ stmnt_runp tt (e_assoc asr) (e_assoc_arr a b asa) (translate_predicate Vblock (Some p) (Vvar r) e) (e_assoc asr') (e_assoc_arr a b asa') ->
+ Ple (max_predicate p) max_pred ->
+ match_assocmaps max_reg max_pred rs ps asr ->
+ eval_predf ps p = false ->
+ (forall x, asr # x = asr' # x) /\ asa = asa'.
+ Proof.
+ intros * HSTMNT HPLE HMATCH HEVAL *.
+ pose proof HEVAL as HEVAL_DEEP.
+ erewrite <- eval_predf_deep_simplify in HEVAL_DEEP.
+ cbn in *. destruct_match.
+ - inv HSTMNT; inv H6. split; auto. intros.
+ exploit pred_expr_correct. inv HMATCH; eauto. intros. eapply H0. instantiate (1 := deep_simplify peq p) in H1.
+ eapply max_predicate_deep_simplify in H1. unfold Ple in *. lia.
+ intros. inv H7. unfold e_assoc in *; cbn in *.
+ pose proof H as H'. eapply expr_runp_determinate in H6; eauto. rewrite HEVAL_DEEP in H6.
+ rewrite H6 in H10. now rewrite valueToBool_correct in H10.
+ unfold e_assoc_arr, e_assoc in *; cbn in *. inv H9.
+ destruct (peq r0 x); subst; [now rewrite assocmap_gss|now rewrite assocmap_gso by auto].
+ - unfold sat_pred_simple in Heqo. repeat (destruct_match; try discriminate).
+ unfold eval_predf in HEVAL_DEEP.
+ apply negb_inj' in HEVAL_DEEP.
+ rewrite <- negate_correct in HEVAL_DEEP. rewrite e0 in HEVAL_DEEP. discriminate.
+ Qed.
+
+ Inductive lessdef_memory: option value -> option value -> Prop :=
+ | lessdef_memory_none:
+ lessdef_memory None (Some (ZToValue 0))
+ | lessdef_memory_eq: forall a,
+ lessdef_memory a a.
+
+ Lemma transl_predicate_correct_arr :
+ forall asr asa a b asr' asa' p r e max_pred max_reg rs ps e1,
+ stmnt_runp tt (e_assoc asr) (e_assoc_arr a b asa) (translate_predicate Vblock (Some p) (Vvari r e1) e) (e_assoc asr') (e_assoc_arr a b asa') ->
+ Ple (max_predicate p) max_pred ->
+ match_assocmaps max_reg max_pred rs ps asr ->
+ eval_predf ps p = false ->
+ asr = asr' /\ (forall x a, asa ! x = Some a -> exists a', asa' ! x = Some a'
+ /\ (forall y, (y < arr_length a)%nat -> exists av av', array_get_error y a = Some av /\ array_get_error y a' = Some av' /\ lessdef_memory av av')).
+ Proof.
+ intros * HSTMNT HPLE HMATCH HEVAL *.
+ pose proof HEVAL as HEVAL_DEEP.
+ erewrite <- eval_predf_deep_simplify in HEVAL_DEEP.
+ cbn in *. destruct_match.
+ - inv HSTMNT; inv H6; split; auto; intros.
+ exploit pred_expr_correct. inv HMATCH; eauto. intros. eapply H1. instantiate (1 := deep_simplify peq p) in H2.
+ eapply max_predicate_deep_simplify in H2. unfold Ple in *. lia.
+ intros. inv H7. unfold e_assoc in *; cbn in *.
+ pose proof H0 as H'. eapply expr_runp_determinate in H9; eauto. rewrite HEVAL_DEEP in H9.
+ rewrite H9 in H12. now rewrite valueToBool_correct in H12.
+ unfold e_assoc_arr, e_assoc in *; cbn in *. inv H11.
+ destruct (peq r0 x); subst.
+ + unfold arr_assocmap_set. rewrite H.
+ rewrite AssocMap.gss. eexists. split; eauto. unfold arr_assocmap_lookup in H10.
+ rewrite H in H10. inv H10. eapply expr_runp_determinate in H3; eauto. subst.
+ intros.
+ destruct (Nat.eq_dec y (valueToNat i)); subst.
+ * rewrite array_get_error_set_bound by auto.
+ destruct (array_get_error (valueToNat i) a1) eqn:?.
+ -- do 2 eexists. split; eauto. split. eauto.
+ destruct o; cbn; constructor.
+ -- exploit (@array_get_error_bound (option value)); eauto. simplify.
+ rewrite H3 in Heqo0. discriminate.
+ * rewrite array_gso by auto.
+ exploit (@array_get_error_bound (option value)); eauto. simplify.
+ rewrite H3. do 2 eexists; repeat split; constructor.
+ + unfold arr_assocmap_set. destruct_match.
+ * rewrite PTree.gso by auto. setoid_rewrite H. eexists. split; eauto.
+ intros. exploit (@array_get_error_bound (option value)); eauto. simplify.
+ rewrite H4. do 2 eexists; repeat split; constructor.
+ * eexists. split; eauto. intros. exploit (@array_get_error_bound (option value)); eauto. simplify.
+ rewrite H4. do 2 eexists; repeat split; constructor.
+ - unfold sat_pred_simple in Heqo. repeat (destruct_match; try discriminate).
+ unfold eval_predf in HEVAL_DEEP.
+ apply negb_inj' in HEVAL_DEEP.
+ rewrite <- negate_correct in HEVAL_DEEP. rewrite e0 in HEVAL_DEEP. discriminate.
+ Qed.
+
+ Lemma transl_predicate_correct2 :
+ forall asr asa a b p r e max_pred max_reg rs ps,
+ Ple (max_predicate p) max_pred ->
+ match_assocmaps max_reg max_pred rs ps asr ->
+ eval_predf ps p = false ->
+ exists asr', stmnt_runp tt (e_assoc asr) (e_assoc_arr a b asa) (translate_predicate Vblock (Some p) (Vvar r) e) (e_assoc asr') (e_assoc_arr a b asa) /\ (forall x n, asr # (x, n) = asr' # (x, n)) /\ (forall x y, asr ! x = Some y -> asr' ! x = Some y).
+ Proof.
+ intros * HPLE HMATCH HEVAL. pose proof HEVAL as HEVAL_DEEP.
+ unfold translate_predicate. erewrite <- eval_predf_deep_simplify in HEVAL_DEEP.
+ destruct_match.
+ - econstructor; split; [|split].
+ + econstructor; [econstructor|]. eapply erun_Vternary_false.
+ * eapply pred_expr_correct. intros. eapply max_predicate_deep_simplify in H.
+ inv HMATCH. eapply H1; unfold Ple in *. lia.
+ * now econstructor.
+ * rewrite HEVAL_DEEP. auto.
+ + intros. destruct (peq x r); subst.
+ * now rewrite assocmap_gss.
+ * now rewrite assocmap_gso.
+ + intros. unfold e_assoc in *; simpl in *. destruct (peq x r); subst.
+ * unfold find_assocmap, AssocMapExt.get_default. rewrite H. now rewrite AssocMap.gss.
+ * unfold find_assocmap, AssocMapExt.get_default.
+ destruct (asr ! r) eqn:HE; now rewrite AssocMap.gso by auto.
+ - unfold sat_pred_simple in Heqo. repeat (destruct_match; try discriminate).
+ apply negb_inj' in HEVAL_DEEP. unfold eval_predf in *. rewrite <- negate_correct in HEVAL_DEEP.
+ now rewrite e0 in HEVAL_DEEP.
+ Qed.
+
+ Lemma transl_predicate_correct2_true :
+ forall asr asa a b p r e max_pred max_reg rs ps v,
+ Ple (max_predicate p) max_pred ->
+ match_assocmaps max_reg max_pred rs ps asr ->
+ eval_predf ps p = true ->
+ expr_runp tt asr asa e v ->
+ stmnt_runp tt (e_assoc asr) (e_assoc_arr a b asa) (translate_predicate Vblock (Some p) (Vvar r) e) (e_assoc (asr # r <- v)) (e_assoc_arr a b asa).
+ Proof.
+ intros * HPLE HMATCH HEVAL HEXPR. pose proof HEVAL as HEVAL_DEEP.
+ unfold translate_predicate. erewrite <- eval_predf_deep_simplify in HEVAL_DEEP.
+ destruct_match.
+ - econstructor. econstructor. econstructor. eapply pred_expr_correct.
+ intros. eapply max_predicate_deep_simplify in H. inv HMATCH. eapply H1. unfold Ple in *. lia.
+ eauto. rewrite HEVAL_DEEP. eauto.
+ - econstructor. econstructor. auto.
+ Qed.
+
+ Lemma arr_assocmap_set_gss :
+ forall r i v asa ar,
+ asa ! r = Some ar ->
+ (arr_assocmap_set r i v asa) ! r = Some (array_set i (Some v) ar).
+ Proof.
+ unfold arr_assocmap_set.
+ intros. rewrite H. rewrite PTree.gss. auto.
+ Qed.
+
+ Lemma arr_assocmap_set_gso :
+ forall r x i v asa ar,
+ asa ! x = Some ar ->
+ r <> x ->
+ (arr_assocmap_set r i v asa) ! x = asa ! x.
+ Proof.
+ unfold arr_assocmap_set. intros.
+ destruct (asa!r) eqn:?; auto; now rewrite PTree.gso by auto.
+ Qed.
+
+ Lemma arr_assocmap_set_gs2 :
+ forall r x i v asa,
+ asa ! x = None ->
+ (arr_assocmap_set r i v asa) ! x = None.
+ Proof.
+ unfold arr_assocmap_set. intros.
+ destruct (peq r x); subst; [now rewrite H|].
+ destruct (asa!r) eqn:?; auto.
+ now rewrite PTree.gso by auto.
+ Qed.
+
+ Lemma get_mem_set_array_gss :
+ forall y a x,
+ (y < arr_length a)%nat ->
+ get_mem y (array_set y (Some x) a) = x.
+ Proof.
+ unfold get_mem; intros.
+ rewrite array_get_error_set_bound by eauto; auto.
+ Qed.
+
+ Lemma get_mem_set_array_gss2 :
+ forall y a,
+ (y < arr_length a)%nat ->
+ get_mem y (array_set y None a) = ZToValue 0.
+ Proof.
+ unfold get_mem; intros.
+ rewrite array_get_error_set_bound by eauto; auto.
+ Qed.
+
+ Lemma get_mem_set_array_gso :
+ forall y a x z,
+ y <> z ->
+ get_mem y (array_set z x a) = get_mem y a.
+ Proof. unfold get_mem; intros. now rewrite array_gso by auto. Qed.
+
+ Lemma get_mem_set_array_gso2 :
+ forall y a x z,
+ (y >= arr_length a)%nat ->
+ get_mem y (array_set z x a) = ZToValue 0.
+ Proof.
+ intros; unfold get_mem. unfold array_get_error.
+ erewrite array_set_len with (i:=z) (x:=x) in H.
+ remember (array_set z x a). destruct a0. cbn in *. rewrite <- arr_wf in H.
+ assert (Datatypes.length arr_contents <= y)%nat by lia.
+ apply nth_error_None in H0. rewrite H0. auto.
+ Qed.
+
+ Lemma get_mem_set_array_gss3 :
+ forall y a,
+ get_mem y (array_set y None a) = ZToValue 0.
+ Proof.
+ intros.
+ assert (y < arr_length a \/ y >= arr_length a)%nat by lia.
+ inv H.
+ - now rewrite get_mem_set_array_gss2.
+ - now rewrite get_mem_set_array_gso2.
+ Qed.
+
+ Lemma arr_assocmap_lookup_get_mem:
+ forall asa r i v,
+ arr_assocmap_lookup asa r i = Some v ->
+ exists ar, asa ! r = Some ar /\ get_mem i ar = v.
+ Proof.
+ unfold arr_assocmap_lookup in *; intros.
+ repeat (destruct_match; try discriminate). inv H.
+ eexists; eauto.
+ Qed.
+
+ Lemma transl_predicate_correct_arr2 :
+ forall asr asa a b p r e max_pred max_reg rs ps e1 v1 ar,
+ Ple (max_predicate p) max_pred ->
+ match_assocmaps max_reg max_pred rs ps asr ->
+ eval_predf ps p = false ->
+ expr_runp tt (assoc_blocking (e_assoc asr)) (assoc_blocking (e_assoc_arr a b asa)) e1 v1 ->
+ arr_assocmap_lookup (assoc_blocking (e_assoc_arr a b asa)) r (valueToNat v1) = Some ar ->
+ exists asa', stmnt_runp tt (e_assoc asr) (e_assoc_arr a b asa) (translate_predicate Vblock (Some p) (Vvari r e1) e) (e_assoc asr) (e_assoc_arr a b asa')
+ /\ (forall x a, asa ! x = Some a ->
+ exists a', asa' ! x = Some a'
+ /\ (forall y, (y < arr_length a)%nat -> get_mem y a = get_mem y a')
+ /\ (arr_length a = arr_length a')).
+ Proof.
+ intros * HPLE HMATCH HEVAL HEXPRRUN HLOOKUP. pose proof HEVAL as HEVAL_DEEP.
+ unfold translate_predicate. erewrite <- eval_predf_deep_simplify in HEVAL_DEEP.
+ destruct_match.
+ - econstructor; split.
+ + econstructor; [econstructor|]; eauto. eapply erun_Vternary_false.
+ * eapply pred_expr_correct. intros. eapply max_predicate_deep_simplify in H.
+ inv HMATCH. eapply H1; unfold Ple in *. lia.
+ * econstructor; eauto.
+ * rewrite HEVAL_DEEP. auto.
+ + intros. destruct (peq x r); subst.
+ * erewrite arr_assocmap_set_gss by eauto.
+ eexists; repeat split; eauto; intros.
+ destruct (Nat.eq_dec y (valueToNat v1)); subst.
+ -- rewrite get_mem_set_array_gss by auto.
+ exploit arr_assocmap_lookup_get_mem; eauto. intros (ar' & HASSOC & HGET).
+ unfold e_assoc_arr in HASSOC. cbn in *. rewrite HASSOC in H. inv H. auto.
+ -- now rewrite get_mem_set_array_gso by auto.
+ * erewrite arr_assocmap_set_gso by eauto. unfold e_assoc_arr; cbn. eexists; split; eauto.
+ - unfold sat_pred_simple in Heqo. repeat (destruct_match; try discriminate).
+ apply negb_inj' in HEVAL_DEEP. unfold eval_predf in *. rewrite <- negate_correct in HEVAL_DEEP.
+ now rewrite e0 in HEVAL_DEEP.
+ Qed.
+
+ Lemma transl_predicate_cond_correct_arr2 :
+ forall asr asa a b p max_pred max_reg rs ps s,
+ Ple (max_predicate p) max_pred ->
+ match_assocmaps max_reg max_pred rs ps asr ->
+ eval_predf ps p = false ->
+ stmnt_runp tt (e_assoc asr) (e_assoc_arr a b asa) (translate_predicate_cond (Some p) s) (e_assoc asr) (e_assoc_arr a b asa).
+ Proof.
+ intros * HPLE HMATCH HEVAL.
+ unfold translate_predicate_cond. inv HMATCH.
+ exploit pred_expr_correct. intros; eapply H0. unfold Ple in *. instantiate (1:=p) in H1. lia.
+ intros. rewrite HEVAL in H1. unfold boolToValue, natToValue in H1. cbn in H1.
+ eapply stmnt_runp_Vcond_false; eauto. constructor.
+ Qed.
+
+ Definition unchanged (asr : assocmap) asa asr' asa' :=
+ (forall x n, asr # (x, n) = asr' # (x, n))
+ /\ (forall x y, asr ! x = Some y -> asr' ! x = Some y)
+ /\ (forall x a, asa ! x = Some a ->
+ exists a', asa' ! x = Some a'
+ /\ (forall y, (y < arr_length a)%nat -> get_mem y a = get_mem y a')
+ /\ arr_length a = arr_length a').
+
+ Lemma unchanged_refl :
+ forall a b, unchanged a b a b.
+ Proof.
+ unfold unchanged; split; intros. eauto.
+ eexists; eauto.
+ Qed.
+
+ Lemma unchanged_trans :
+ forall a b a' b' a'' b'', unchanged a b a' b' -> unchanged a' b' a'' b'' -> unchanged a b a'' b''.
+ Proof.
+ unfold unchanged; simplify; intros.
+ congruence.
+ eauto.
+ pose proof H4 as H'. apply H5 in H'. simplify. pose proof H7 as H5'.
+ apply H3 in H5'. simplify. eexists; eauto; simplify; eauto; try congruence.
+ intros. rewrite H6 by auto. now rewrite <- H8 by lia.
+ Qed.
+
+ Opaque translate_predicate.
+ Opaque translate_predicate_cond.
+
+ Lemma calc_predicate_lt_max_function :
+ forall m next_p p,
+ Ple (max_predicate next_p) m ->
+ Forall (fun x : positive => Ple x m)
+ match p with
+ | Some p => predicate_use p
+ | None => nil
+ end ->
+ Ple (max_predicate (Pand next_p (dfltp p))) m.
+ Proof.
+ intros. destruct p.
+ - eapply le_max_pred in H0.
+ cbn. unfold Ple in *; lia.
+ - cbn. unfold Ple in *; lia.
+ Qed.
+
+Lemma truthy_dflt :
+ forall ps p,
+ truthy ps p -> eval_predf ps (dfltp p) = true.
+Proof. intros. destruct p; cbn; inv H; auto. Qed.
+
+ Lemma state_st_wf_write :
+ forall asr v st pc dst,
+ state_st_wf asr st pc ->
+ reg_enc dst <> st ->
+ state_st_wf (AssocMap.set (reg_enc dst) v asr) st pc.
+ Proof.
+ unfold state_st_wf; intros.
+ rewrite PTree.gso by auto; auto.
+ Qed.
+
+ Lemma mk_ctrl_correct :
+ forall f m,
+ OK m = transl_module f ->
+ (mk_ctrl f).(ctrl_st) = m.(DHTL.mod_st)
+ /\ (mk_ctrl f).(ctrl_stack) = m.(DHTL.mod_stk)
+ /\ (mk_ctrl f).(ctrl_fin) = m.(DHTL.mod_finish)
+ /\ (mk_ctrl f).(ctrl_return) = m.(DHTL.mod_return).
+ Proof.
+ intros. unfold transl_module, Errors.bind in *. repeat destr. inv H. auto.
+ Qed.
+
+ Lemma transl_iop_correct:
+ forall f s s' pc sp m_ d d' curr_p next_p rs ps m rs' p op args dst asr arr asr' arr' stk stk_len n,
+ transf_instr n (mk_ctrl f) (curr_p, d) (RBop p op args dst) = Errors.OK (next_p, d') ->
+ step_instr ge sp (Iexec (mk_instr_state rs ps m)) (RBop p op args dst) (Iexec (mk_instr_state rs' ps m)) ->
+ stmnt_runp tt (e_assoc asr) (e_assoc_arr stk stk_len arr) d (e_assoc asr') (e_assoc_arr stk stk_len arr') ->
+ eval_predf ps curr_p = true ->
+ truthy ps p ->
+ Ple (max_predicate curr_p) (max_pred_function f) ->
+ Forall (fun x => Ple x (max_pred_function f)) (pred_uses (RBop p op args dst)) ->
+ match_states (GibleSubPar.State s f sp pc rs ps m) (DHTL.State s' m_ pc asr' arr') ->
+ Forall (fun x : positive => Ple x (max_reg_function f)) args ->
+ Ple dst (max_reg_function f) ->
+ exists asr'', stmnt_runp tt (e_assoc asr) (e_assoc_arr stk stk_len arr) d' (e_assoc asr'') (e_assoc_arr stk stk_len arr')
+ /\ match_states (GibleSubPar.State s f sp pc rs' ps m) (DHTL.State s' m_ pc asr'' arr').
+ Proof.
+ cbn in *; unfold Errors.bind; cbn in *; intros * ? HTRANSF HSTEP HSTMNT HEVAL_PRED HTRUTHY HPLE HFRL1 HMATCH HFRL HREG.
+ move HTRANSF after HFRL1. repeat destr. inv HTRANSF. inv HSTEP.
+ 2: { inv H3. cbn in *. inv HTRUTHY. rewrite H1 in H0. discriminate. }
+ exploit eval_correct. 3: { eauto. } 3: { eauto. } eauto. eauto. intros (v' & HEXPR & HVAL).
+ eexists. split.
+ - inv HMATCH. econstructor; eauto. eapply transl_predicate_correct2_true; eauto.
+ eapply calc_predicate_lt_max_function; eauto.
+ rewrite eval_predf_Pand; rewrite HEVAL_PRED; rewrite truthy_dflt; auto.
+ - inv HMATCH. econstructor; eauto. eapply regs_lessdef_add_match; auto.
+ eapply state_st_wf_write; eauto.
+ { symmetry in TF; eapply mk_ctrl_correct in TF. inv TF. rewrite <- H. cbn.
+ eapply ple_max_resource_function in HREG. unfold Ple in *. lia. }
+ { exploit op_stack_based; eauto. intros.
+ unfold reg_stack_based_pointers. intros.
+ destruct (peq dst r); subst. now rewrite PMap.gss.
+ rewrite PMap.gso by auto. eauto. }
+ unfold transl_module, Errors.bind, ret in TF; repeat destr. inv TF; cbn in *.
+ eapply ple_max_resource_function in HREG. unfold Ple in *.
+ econstructor.
+ { inv CONST. rewrite AssocMap.gso by lia. eauto. }
+ { inv CONST. rewrite AssocMap.gso by lia. eauto. }
+ Qed.
+
+ Lemma fold_left_max :
+ forall l r n, In r l \/ Ple r n -> Ple r (fold_left Pos.max l n).
+ Proof.
+ induction l; simpl; intros.
+ tauto.
+ apply IHl. destruct H as [[A|A]|A]. right; subst; extlia. auto. right; extlia.
+ Qed.
+
+ Lemma unchanged_implies_match :
+ forall s f sp rs ps m s' m_ pc asr' asa' asa asr,
+ unchanged asr asa asr' asa' ->
+ match_states (GibleSubPar.State s f sp pc rs ps m) (DHTL.State s' m_ pc asr asa) ->
+ match_states (GibleSubPar.State s f sp pc rs ps m) (DHTL.State s' m_ pc asr' asa').
+ Proof.
+ intros * HUNCH HMATCH; unfold unchanged in *; simplify.
+ rename H into HFINDEQ, H1 into HDEF, H2 into HARR.
+ inv HMATCH.
+ econstructor; auto.
+ - econstructor; intros; inv MASSOC; rewrite <- HFINDEQ; eauto.
+ - unfold state_st_wf in *. eauto.
+ - inv MARR. simplify.
+ rename H0 into HSTACK, H into HARRLEN, H1 into HARRLEN', H3 into HEQ.
+ exploit HARR; eauto. intros (a' & HASA & HEQ' & HARRLEN'').
+ econstructor. simplify; eauto; try congruence.
+ intros. rewrite <- HARRLEN'' in H. pose proof H as H'. apply HEQ in H.
+ inv H; econstructor.
+ rewrite <- HEQ'; eauto. lia.
+ - inv CONST. constructor; eauto.
+ Qed.
+
+Lemma eval_predf_negate :
+ forall ps p,
+ eval_predf ps (negate p) = negb (eval_predf ps p).
+Proof.
+ unfold eval_predf; intros. rewrite negate_correct. auto.
+Qed.
+
+ Lemma unchanged_match_assocmaps :
+ forall a b a' b' m1 m2 rs ps,
+ unchanged a b a' b' ->
+ match_assocmaps m1 m2 rs ps a ->
+ match_assocmaps m1 m2 rs ps a'.
+ Proof.
+ unfold unchanged; inversion 2; subst. clear H0.
+ inv H. inv H3. econstructor; intros. rewrite <- H0. eauto.
+ rewrite <- H0. eauto.
+ Qed.
+
+End CORRECTNESS.