include "RTLabs/syntax.ma". include "RTL/RTL.ma". include "common/AssocList.ma". include "common/FrontEndOps.ma". include "common/Graphs.ma". include "joint/TranslateUtils.ma". (* let rec register_freshes (runiverse: universe RegisterTag) (n: nat) on n ≝ match n with [ O ⇒ [ ] | S n' ⇒ register_fresh runiverse :: (register_freshes runiverse n') ]. *) definition choose_rest ≝ λA: Type[0]. λleft, right: list A. λprfl: 0 < |left|. λprfr: 0 < |right|. match left return λx. 0 < |x| → list A with [ nil ⇒ λnil_prf. match right return λx. 0 < |x| → list A with [ nil ⇒ λnil_nil_absrd. ? | _ ⇒ λnil_cons_prf. right ] prfr | _ ⇒ λcons_prf. right ] prfl. normalize in nil_prf; cases(not_le_Sn_O 0) #HYP cases(HYP nil_prf) qed. definition complete_regs ≝ λglobals. λdef. λsrcrs1. λsrcrs2. if leb (length … srcrs2) (length … srcrs1) then let 〈def, added_regs〉 ≝ fresh_regs rtl_params0 globals def (minus (length ? srcrs1) (length ? srcrs2)) in 〈〈srcrs1, srcrs2 @ added_regs〉, added_regs〉 else let 〈def, added_regs〉 ≝ fresh_regs rtl_params0 globals def (minus (length ? srcrs2) (length ? srcrs1)) in 〈〈srcrs1 @ added_regs, srcrs2〉, added_regs〉. lemma complete_regs_length: ∀globals,def,left,right. |\fst (\fst (complete_regs globals def left right))| = |\snd (\fst (complete_regs globals def left right))|. #globals #def #left #right whd in match complete_regs normalize nodelta @leb_elim normalize nodelta #H [ generalize in match (fresh_regs_length rtl_params0 globals def (minus (length … left) (length … right))) | generalize in match (fresh_regs_length rtl_params0 globals def (minus (length … right) (length … left)))] cases (fresh_regs ????) #def' #fresh normalize >append_length generalize in match H -H; generalize in match (length … left) generalize in match (length … right) generalize in match (length … fresh) [ /2/ | #x #y #z #H generalize in match (not_le_to_lt … H) -H #H #E >E >commutative_plus succ_prf // qed. definition translate_negint ≝ λdestrs. λsrcrs. λstart_lbl. λdest_lbl. λdef. λprf: | destrs | = | srcrs |. (* assert in caml code *) let 〈def, tmpr〉 ≝ fresh_reg def in let f_cmpl ≝ λdestr. λsrcr. rtl_st_op1 Cmpl destr srcr start_lbl in let insts_cmpl ≝ map2 ? ? ? f_cmpl destrs srcrs prf in let insts_init ≝ [ rtl_st_set_carry start_lbl; rtl_st_int tmpr (zero ?) start_lbl ] in let f_add ≝ λdestr. rtl_st_op2 Addc destr destr tmpr start_lbl in let insts_add ≝ map … f_add destrs in adds_graph (insts_cmpl @ insts_init @ insts_add) start_lbl dest_lbl def. definition translate_notbool ≝ λdestrs. λsrcrs. λstart_lbl. λdest_lbl. λdef. match destrs with [ nil ⇒ add_graph start_lbl (rtl_st_skip dest_lbl) def | cons destr destrs ⇒ let 〈def, tmpr〉 ≝ fresh_reg def in let 〈def, tmp_srcrs〉 ≝ fresh_regs def (length ? srcrs) in let save_srcrs ≝ translate_move tmp_srcrs srcrs in let init_destr ≝ rtl_st_int destr (bitvector_of_nat ? 1) start_lbl in let f ≝ λtmp_srcr. [ rtl_st_clear_carry start_lbl; rtl_st_int tmpr (zero ?) start_lbl; rtl_st_op2 Sub tmpr tmpr tmp_srcr start_lbl; rtl_st_int tmpr (zero ?) start_lbl; rtl_st_op2 Addc tmpr tmpr tmpr start_lbl; rtl_st_op2 Xor destr destr tmpr start_lbl ] in let insts ≝ init_destr :: (flatten ? (map … f tmp_srcrs)) in let epilogue ≝ translate_cst (Ointconst I8 (bitvector_of_nat ? 0)) destrs in add_translates [ save_srcrs; adds_graph insts; epilogue ] start_lbl dest_lbl def ]. (* TODO: examine this properly. This is a change from the O'caml code due to us dropping the explicit use of a cast destination size field. We instead infer the size of the cast's destination from the context. Is this correct? *) definition translate_op1 ≝ λop1: unary_operation. λdestrs: list register. λsrcrs: list register. λprf: |destrs| = |srcrs|. λstart_lbl: label. λdest_lbl: label. λdef: rtl_internal_function. match op1 with [ Ocastint src_sign src_size ⇒ let dest_size ≝ |destrs| * 8 in let src_size ≝ bitsize_of_intsize src_size in translate_cast src_size src_sign dest_size destrs srcrs start_lbl dest_lbl def | Onegint ⇒ translate_negint destrs srcrs start_lbl dest_lbl def prf | Onotbool ⇒ translate_notbool destrs srcrs start_lbl dest_lbl def | Onotint ⇒ let f ≝ λdestr. λsrcr. rtl_st_op1 Cmpl destr srcr start_lbl in let l ≝ map2 … f destrs srcrs prf in adds_graph l start_lbl dest_lbl def | Optrofint r ⇒ translate_move destrs srcrs start_lbl dest_lbl def | Ointofptr r ⇒ translate_move destrs srcrs start_lbl dest_lbl def | Oid ⇒ translate_move destrs srcrs start_lbl dest_lbl def | _ ⇒ ? (* float operations implemented in runtime *) ]. cases not_implemented qed. definition translate_op ≝ λop. λdestrs. λsrcrs1. λsrcrs2. λstart_lbl. λdest_lbl. λdef. match reduce_strong register register srcrs1 srcrs2 with [ dp reduced first_reduced_proof ⇒ let srcrsl_common ≝ \fst (\fst reduced) in let srcrsr_common ≝ \fst (\snd reduced) in let srcrsl_rest ≝ \snd (\fst reduced) in let srcrsr_rest ≝ \snd (\snd reduced) in let srcrs_rest ≝ choose_rest ? srcrsl_rest srcrsr_rest ? ? in match reduce_strong register register destrs srcrsl_common with [ dp reduced second_reduced_proof ⇒ let destrs_common ≝ \fst (\fst reduced) in let destrs_rest ≝ \snd (\fst reduced) in match reduce_strong register register destrs_rest srcrs_rest with [ dp reduced third_reduced_proof ⇒ let destrs_cted ≝ \fst (\fst reduced) in let destrs_rest ≝ \snd (\fst reduced) in let srcrs_cted ≝ \fst (\snd reduced) in let 〈def, tmpr〉 ≝ fresh_reg def in let insts_init ≝ [ rtl_st_clear_carry start_lbl; rtl_st_int tmpr (zero ?) start_lbl ] in let f_add ≝ λdestr. λsrcr1. λsrcr2. rtl_st_op2 op destr srcr1 srcr2 start_lbl in let insts_add ≝ map3 … f_add destrs_common srcrsl_common srcrsr_common ? ? in let f_add_cted ≝ λdestr. λsrcr. rtl_st_op2 op destr srcr tmpr start_lbl in let insts_add_cted ≝ map2 ? ? ? f_add_cted destrs_cted srcrs_cted ? in let f_rest ≝ λdestr. rtl_st_op2 op destr tmpr tmpr start_lbl in let insts_rest ≝ map … f_rest destrs_rest in adds_graph (insts_init @ insts_add @ insts_add_cted @ insts_rest) start_lbl dest_lbl def ] ] ]. [1: @third_reduced_proof |3: @first_reduced_proof |*: cases daemon (* TODO *) ] qed. let rec translate_mul1 (dummy: register) (tmpr: register) (destrs: list register) (srcrs1: list register) (srcr2: register) (start_lbl: label) on srcrs1 ≝ match destrs with [ nil ⇒ adds_graph [ rtl_st_skip start_lbl ] start_lbl | cons destr tl ⇒ match tl with [ nil ⇒ match srcrs1 with [ nil ⇒ adds_graph [ rtl_st_int tmpr (zero ?) start_lbl; rtl_st_op2 Addc destr destr tmpr start_lbl ] start_lbl | cons srcr1 tl' ⇒ adds_graph [ rtl_st_opaccs Mul tmpr dummy srcr2 srcr1 start_lbl; rtl_st_op2 Addc destr destr tmpr start_lbl ] start_lbl ] | cons destr2 destrs ⇒ match srcrs1 with [ nil ⇒ add_translates [ adds_graph [ rtl_st_int tmpr (zero ?) start_lbl; rtl_st_op2 Addc destr destr tmpr start_lbl; rtl_st_op2 Addc destr2 tmpr tmpr start_lbl ]; translate_cst (Ointconst I8 (zero ?)) destrs ] start_lbl | cons srcr1 srcrs1 ⇒ match destrs with [ nil ⇒ add_translates [ adds_graph [ rtl_st_int tmpr (zero ?) start_lbl; rtl_st_op2 Addc destr destr tmpr start_lbl; rtl_st_op2 Addc destr2 tmpr tmpr start_lbl ]; translate_cst (Ointconst I8 (zero ?)) destrs ] start_lbl | cons destr2 destrs ⇒ add_translates [ adds_graph [ rtl_st_opaccs Mul tmpr destr2 srcr2 srcr1 start_lbl; rtl_st_op2 Addc destr destr tmpr start_lbl ]; translate_mul1 dummy tmpr (destr2 :: destrs) srcrs1 srcr2 ] start_lbl ] ] ] ]. definition translate_muli ≝ λdummy: register. λtmpr: register. λdestrs: list register. λtmp_destrs: list register. λsrcrs1: list register. λdummy_lbl: label. λi: nat. λi_prf. λtranslates: list ?. λsrcr2i: register. let 〈tmp_destrs1, tmp_destrs2〉 ≝ split ? tmp_destrs i i_prf in let tmp_destrs2' ≝ match tmp_destrs2 with [ nil ⇒ [ ] | cons tmp_destr2 tmp_destrs2 ⇒ [ adds_graph [ rtl_st_clear_carry dummy_lbl; rtl_st_int tmp_destr2 (zero ?) dummy_lbl ]; translate_mul1 dummy tmpr tmp_destrs2 srcrs1 srcr2i; translate_cst (Ointconst I8 (zero ?)) tmp_destrs1; adds_graph [ rtl_st_clear_carry dummy_lbl ]; translate_op Addc destrs destrs tmp_destrs ] ] in translates @ tmp_destrs2'. axiom translate_mul: ∀destrs: list register. ∀srcrs1: list register. ∀srcrs2: list register. ∀start_lbl: label. ∀dest_lbl: label. ∀def: rtl_internal_function. rtl_internal_function. (* definition translate_mul ≝ λdestrs: list register. λsrcrs1: list register. λsrcrs2: list register. λstart_lbl: label. λdest_lbl: label. λdef: rtl_internal_function. let 〈def, dummy〉 ≝ fresh_reg def in let 〈def, tmpr〉 ≝ fresh_reg def in let 〈def, tmp_destrs〉 ≝ fresh_regs def (|destrs|) in let 〈def, fresh_srcrs1〉 ≝ fresh_regs def (|srcrs1|) in let 〈def, fresh_srcrs2〉 ≝ fresh_regs def (|srcrs2|) in let insts_init ≝ [ translate_move fresh_srcrs1 srcrs1; translate_move fresh_srcrs2 srcrs2; translate_cst (Ointconst I8 (zero ?)) destrs ] in let f ≝ λi. translate_muli dummy tmpr destrs tmp_destrs ? fresh_srcrs1 start_lbl i ? in let insts_mul ≝ foldi ? ? [ ] srcrs2 in ?. [5: check insts_init. add_translates (insts_init @ insts_mul) start_lbl dest_lbl def. *) definition translate_divumodu8 ≝ λorder: bool. λdestrs: list register. λsrcr1: register. λsrcr2: register. λstart_lbl: label. λdest_lbl: label. λdef: rtl_internal_function. match destrs with [ nil ⇒ add_graph start_lbl (rtl_st_skip dest_lbl) def | cons destr destrs ⇒ let 〈def, dummy〉 ≝ fresh_reg def in let 〈destr1, destr2〉 ≝ match order with [ true ⇒ 〈destr, dummy〉 | _ ⇒ 〈dummy, destr〉 ] in let inst_div ≝ adds_graph [ rtl_st_opaccs DivuModu destr1 destr2 srcr1 srcr2 start_lbl ] in let insts_rest ≝ translate_cst (Ointconst I8 (zero ?)) destrs in add_translates [ inst_div; insts_rest ] start_lbl dest_lbl def ]. definition translate_ne: ? → ? → ? → ? → ? → ? → rtl_internal_function ≝ λdestrs: list register. λsrcrs1: list register. λsrcrs2: list register. λstart_lbl: label. λdest_lbl: label. λdef: rtl_internal_function. match destrs with [ nil ⇒ add_graph start_lbl (rtl_st_skip dest_lbl) def | cons destr destrs ⇒ let 〈def, tmpr〉 ≝ fresh_reg def in let 〈def, tmp_zero〉 ≝ fresh_reg def in let 〈def, tmp_srcrs1〉 ≝ fresh_regs def (|srcrs1|) in let save_srcrs1 ≝ translate_move tmp_srcrs1 srcrs1 in let 〈def, tmp_srcrs2〉 ≝ fresh_regs def (|srcrs2|) in let save_srcrs2 ≝ translate_move tmp_srcrs2 srcrs2 in match reduce_strong register register tmp_srcrs1 tmp_srcrs2 with [ dp crl their_proof ⇒ let commonl ≝ \fst (\fst crl) in let commonr ≝ \fst (\snd crl) in let restl ≝ \snd (\snd crl) in let restr ≝ \snd (\snd crl) in let rest ≝ choose_rest ? restl restr ? ? in let inits ≝ [ rtl_st_int destr (zero ?) start_lbl; rtl_st_int tmp_zero (zero ?) start_lbl ] in let f_common ≝ λtmp_srcr1. λtmp_srcr2. [ rtl_st_clear_carry start_lbl; rtl_st_op2 Sub tmpr tmp_srcr1 tmp_srcr2 start_lbl; rtl_st_op2 Or destr destr tmpr start_lbl ] in let insts_common ≝ flatten ? (map2 … f_common commonl commonr ?) in let f_rest ≝ λtmp_srcr. [ rtl_st_clear_carry start_lbl; rtl_st_op2 Sub tmpr tmp_zero tmp_srcr start_lbl; rtl_st_op2 Or destr destr tmpr start_lbl ] in let insts_rest ≝ flatten ? (map ? ? f_rest rest) in let insts ≝ inits @ insts_common @ insts_rest in let epilogue ≝ translate_cst (Ointconst I8 (zero ?)) destrs in add_translates [ save_srcrs1; save_srcrs2; adds_graph insts; epilogue ] start_lbl dest_lbl def ] ]. [1: @their_proof |*: cases not_implemented (* choose rest requires non-emptiness proofs but these appear impossible to obtain, similar proof to above *) ] qed. definition translate_eq_reg ≝ λtmp_zero: register. λtmp_one: register. λtmpr1: register. λtmpr2: register. λdestr: register. λdummy_lbl: label. λsrcr12: register × register. let 〈srcr1, srcr2〉 ≝ srcr12 in [ rtl_st_clear_carry dummy_lbl; rtl_st_op2 Sub tmpr1 srcr1 srcr2 dummy_lbl; rtl_st_op2 Addc tmpr1 tmp_zero tmp_zero dummy_lbl; rtl_st_op2 Sub tmpr2 srcr2 srcr1 dummy_lbl; rtl_st_op2 Addc tmpr2 tmp_zero tmp_zero dummy_lbl; rtl_st_op2 Or tmpr1 tmpr1 tmpr2 dummy_lbl; rtl_st_op2 Xor tmpr1 tmpr1 tmp_one dummy_lbl; rtl_st_op2 And destr destr tmpr1 dummy_lbl ]. definition translate_eq_list ≝ λtmp_zero: register. λtmp_one: register. λtmpr1: register. λtmpr2: register. λdestr: register. λleq: list (register × register). λdummy_lbl: label. let f ≝ translate_eq_reg tmp_zero tmp_one tmpr1 tmpr2 destr dummy_lbl in (rtl_st_int destr (bitvector_of_nat ? 1) dummy_lbl) :: flatten ? (map ? ? f leq). definition translate_atom ≝ λtmp_zero: register. λtmp_one: register. λtmpr1: register. λtmpr2: register. λtmpr3: register. λdestr: register. λdummy_lbl: label. λleq: list (register × register). λsrcr1: register. λsrcr2: register. translate_eq_list tmp_zero tmp_one tmpr1 tmpr2 tmpr3 leq dummy_lbl @ [ rtl_st_clear_carry dummy_lbl; rtl_st_op2 Sub tmpr1 srcr1 srcr2 dummy_lbl; rtl_st_op2 Addc tmpr1 tmp_zero tmp_zero dummy_lbl; rtl_st_op2 And tmpr3 tmpr3 tmpr1 dummy_lbl; rtl_st_op2 Or destr destr tmpr3 dummy_lbl ]. definition translate_lt_main ≝ λtmp_zero: register. λtmp_one: register. λtmpr1: register. λtmpr2: register. λtmpr3: register. λdestr: register. λdummy_lbl: label. λsrcrs1: list register. λsrcrs2: list register. λproof: |srcrs1| = |srcrs2|. let f ≝ λinsts_leq. λsrcr1. λsrcr2. let 〈insts, leq〉 ≝ insts_leq in let added_insts ≝ translate_atom tmp_zero tmp_one tmpr1 tmpr2 tmpr3 destr dummy_lbl leq srcr1 srcr2 in 〈insts @ added_insts, leq @ [〈srcr1, srcr2〉]〉 in \fst (fold_left2 ? ? ? f 〈[ ], [ ]〉 srcrs1 srcrs2 proof). definition fresh_regs_strong: rtl_internal_function → ∀n: nat. Σfresh: rtl_internal_function × (list register). |\snd fresh| = n ≝ λdef. λn. fresh_regs def n. @fresh_regs_length qed. definition complete_regs_strong: rtl_internal_function → list register → list register → Σcomplete: (list register) × (list register) × (list register). |\fst (\fst complete)| = |\snd (\fst complete)| ≝ λdef. λleft. λright. complete_regs def left right. @complete_regs_length qed. definition translate_lt ≝ λdestrs: list register. λprf_destrs: lt 0 (|destrs|). λsrcrs1: list register. λsrcrs2: list register. λstart_lbl: label. λdest_lbl: label. λdef: rtl_internal_function. match destrs with [ nil ⇒ add_graph start_lbl (rtl_st_skip dest_lbl) def | _ ⇒ match fresh_regs_strong def (|destrs|) with [ dp def_tmp_destrs tmp_destrs_proof ⇒ let def ≝ \fst def_tmp_destrs in let tmp_destrs ≝ \snd def_tmp_destrs in let tmp_destr ≝ hd_safe ? tmp_destrs ? in let 〈def, tmp_zero〉 ≝ fresh_reg def in let 〈def, tmp_one〉 ≝ fresh_reg def in let 〈def, tmpr1〉 ≝ fresh_reg def in let 〈def, tmpr2〉 ≝ fresh_reg def in let 〈def, tmpr3〉 ≝ fresh_reg def in match complete_regs_strong def srcrs1 srcrs2 with [ dp srcrs12_added srcrs12_proof ⇒ let srcrs1 ≝ \fst (\fst srcrs12_added) in let srcrs2 ≝ \snd (\fst srcrs12_added) in let added ≝ \snd srcrs12_added in let srcrs1' ≝ rev ? srcrs1 in let srcrs2' ≝ rev ? srcrs2 in let insts_init ≝ [ translate_cst (Ointconst I8 (zero ?)) tmp_destrs; translate_cst (Ointconst I8 (zero ?)) added; adds_graph [ rtl_st_int tmp_zero (zero ?) start_lbl; rtl_st_int tmp_one (bitvector_of_nat ? 1) start_lbl ] ] in let insts_main ≝ translate_lt_main tmp_zero tmp_one tmpr1 tmpr2 tmpr3 tmp_destr start_lbl srcrs1' srcrs2' ? in let insts_main ≝ [ adds_graph insts_main ] in let insts_exit ≝ [ translate_move destrs tmp_destrs ] in add_translates (insts_init @ insts_main @ insts_exit) start_lbl dest_lbl def ] ] ]. [2: >tmp_destrs_proof @prf_destrs |1: normalize nodelta generalize in match srcrs12_proof #HYP >rev_length >rev_length @HYP ] qed. definition add_128_to_last ≝ λtmp_128: register. λrs. λprf: 0 < |rs|. λstart_lbl: label. match rs with [ nil ⇒ adds_graph [ ] start_lbl | _ ⇒ let r ≝ last_safe ? rs prf in adds_graph [ rtl_st_op2 Add r r tmp_128 start_lbl ] start_lbl ]. definition translate_lts ≝ λdestrs: list register. λdestrs_prf: lt 0 (|destrs|). λsrcrs1: list register. λsrcrs2: list register. λsrcrs1_lt_prf: 0 < |srcrs1|. λsrcrs2_lt_prf: 0 < |srcrs2|. λstart_lbl: label. λdest_lbl: label. λdef: rtl_internal_function. match fresh_regs_strong def (|srcrs1|) with [ dp def_tmp_srcrs1 srcrs1_prf ⇒ let def ≝ \fst def_tmp_srcrs1 in let tmp_srcrs1 ≝ \snd def_tmp_srcrs1 in match fresh_regs_strong def (|srcrs2|) with [ dp def_tmp_srcrs2 srcrs2_prf ⇒ let def ≝ \fst def_tmp_srcrs2 in let tmp_srcrs2 ≝ \snd def_tmp_srcrs2 in let 〈def, tmp_128〉 ≝ fresh_reg def in add_translates [ translate_move tmp_srcrs1 srcrs1; translate_move tmp_srcrs2 srcrs2; adds_graph [ rtl_st_int tmp_128 (bitvector_of_nat ? 128) start_lbl ]; add_128_to_last tmp_128 tmp_srcrs1 ?; add_128_to_last tmp_128 tmp_srcrs2 ?; translate_lt destrs destrs_prf tmp_srcrs1 tmp_srcrs2 ] start_lbl dest_lbl def ] ]. [1: >srcrs1_prf @srcrs1_lt_prf |2: >srcrs2_prf @srcrs2_lt_prf ] qed. definition translate_op2 ≝ λop2. λdestrs: list register. λdestrs_prf: lt 0 (|destrs|). λsrcrs1: list register. λsrcrs2: list register. λsrcrs1_prf: lt 0 (|srcrs1|). (* can this be relaxed? i think it can but we need more dep. typ. in modu/divu cases *) λsrcrs2_prf: lt 0 (|srcrs2|). λstart_lbl: label. λdest_lbl: label. λdef: rtl_internal_function. match op2 with [ Oadd ⇒ translate_op Addc destrs srcrs1 srcrs2 start_lbl dest_lbl def | Oaddp ⇒ translate_op Addc destrs srcrs1 srcrs2 start_lbl dest_lbl def | Osub ⇒ translate_op Sub destrs srcrs1 srcrs2 start_lbl dest_lbl def | Osubpi ⇒ translate_op Sub destrs srcrs1 srcrs2 start_lbl dest_lbl def | Osubpp sz ⇒ translate_op Sub destrs srcrs1 srcrs2 start_lbl dest_lbl def | Omul ⇒ translate_mul destrs srcrs1 srcrs2 start_lbl dest_lbl def | Odivu ⇒ match srcrs1 return λx. 0 < |x| → rtl_internal_function with [ cons hd tl ⇒ λcons_prf. match tl with [ nil ⇒ translate_divumodu8 true destrs hd (hd_safe register srcrs2 ?) start_lbl dest_lbl def | _ ⇒ ? (* not implemented *) ] | nil ⇒ λnil_absrd. ? ] srcrs1_prf | Omodu ⇒ match srcrs1 return λx. 0 < |x| → rtl_internal_function with [ cons hd tl ⇒ λcons_prf. match tl with [ nil ⇒ translate_divumodu8 false destrs hd (hd_safe register srcrs2 ?) start_lbl dest_lbl def | _ ⇒ ? (* not implemented *) ] | nil ⇒ λnil_absrd. ? ] srcrs1_prf | Oand ⇒ translate_op And destrs srcrs1 srcrs2 start_lbl dest_lbl def | Oor ⇒ translate_op Or destrs srcrs1 srcrs2 start_lbl dest_lbl def | Oxor ⇒ translate_op Xor destrs srcrs1 srcrs2 start_lbl dest_lbl def | Ocmp c ⇒ match c with [ Ceq ⇒ add_translates [ translate_ne destrs srcrs1 srcrs2; translate_op1 Onotbool destrs destrs (refl ? (|destrs|)) ] start_lbl dest_lbl def | Cne ⇒ translate_ne destrs srcrs1 srcrs2 start_lbl dest_lbl def | Clt ⇒ translate_lts destrs destrs_prf srcrs1 srcrs2 ? ? start_lbl dest_lbl def | Cgt ⇒ translate_lts destrs destrs_prf srcrs2 srcrs1 ? ? start_lbl dest_lbl def | Cle ⇒ add_translates [ translate_lts destrs destrs_prf srcrs2 srcrs1 ? ?; translate_op1 Onotbool destrs destrs (refl ? (|destrs|)) ] start_lbl dest_lbl def | Cge ⇒ add_translates [ translate_lts destrs destrs_prf srcrs1 srcrs2 ? ?; translate_op1 Onotbool destrs destrs (refl ? (|destrs|)) ] start_lbl dest_lbl def ] | Ocmpu c ⇒ match c with [ Ceq ⇒ add_translates [ translate_ne destrs srcrs1 srcrs2; translate_op1 Onotbool destrs destrs (refl ? (|destrs|)) ] start_lbl dest_lbl def | Cne ⇒ translate_ne destrs srcrs1 srcrs2 start_lbl dest_lbl def | Clt ⇒ translate_lt destrs destrs_prf srcrs1 srcrs2 start_lbl dest_lbl def | Cgt ⇒ translate_lt destrs destrs_prf srcrs2 srcrs1 start_lbl dest_lbl def | Cle ⇒ add_translates [ translate_lt destrs destrs_prf srcrs2 srcrs1; translate_op1 Onotbool destrs destrs (refl ? (|destrs|)) ] start_lbl dest_lbl def | Cge ⇒ add_translates [ translate_lt destrs destrs_prf srcrs1 srcrs2; translate_op1 Onotbool destrs destrs (refl ? (|destrs|)) ] start_lbl dest_lbl def ] | Ocmpp c ⇒ match c with [ Ceq ⇒ add_translates [ translate_ne destrs srcrs1 srcrs2; translate_op1 Onotbool destrs destrs (refl ? (|destrs|)) ] start_lbl dest_lbl def | Cne ⇒ translate_ne destrs srcrs1 srcrs2 start_lbl dest_lbl def | Clt ⇒ translate_lt destrs destrs_prf srcrs1 srcrs2 start_lbl dest_lbl def | Cgt ⇒ translate_lt destrs destrs_prf srcrs2 srcrs1 start_lbl dest_lbl def | Cle ⇒ add_translates [ translate_lt destrs destrs_prf srcrs2 srcrs1; translate_op1 Onotbool destrs destrs (refl ? (|destrs|)) ] start_lbl dest_lbl def | Cge ⇒ add_translates [ translate_lt destrs destrs_prf srcrs1 srcrs2; translate_op1 Onotbool destrs destrs (refl ? (|destrs|)) ] start_lbl dest_lbl def ] | _ ⇒ ? (* assert false, implemented in run time or float op *) ]. [ 2,6: normalize in nil_absrd; cases(not_le_Sn_O 0) #HYP cases(HYP nil_absrd) | 3,7,12,17,13,15,18,19,20,21,14,16: assumption | *: cases not_implemented (* yes, really *) ] qed. definition translate_cond ≝ λsrcrs: list register. λstart_lbl: label. λlbl_true: label. λlbl_false: label. λdef: rtl_internal_function. let 〈def, tmpr〉 ≝ fresh_reg def in let 〈def, tmp_lbl〉 ≝ fresh_label def in let init ≝ rtl_st_int tmpr (zero ?) start_lbl in let f ≝ λsrcr. rtl_st_op2 Or tmpr tmpr srcr start_lbl in let def ≝ adds_graph (init :: (map … f srcrs)) start_lbl tmp_lbl def in add_graph tmp_lbl (rtl_st_cond tmpr lbl_true lbl_false) def. definition translate_load ≝ λaddr. λaddr_prf: 2 ≤ |addr|. λdestrs: list register. λstart_lbl: label. λdest_lbl: label. λdef: rtl_internal_function. match fresh_regs_strong def (|addr|) with [ dp def_save_addr save_addr_prf ⇒ let def ≝ \fst def_save_addr in let save_addr ≝ \snd def_save_addr in match fresh_regs_strong def (|addr|) with [ dp def_tmp_addr tmp_addr_prf ⇒ let def ≝ \fst def_tmp_addr in let tmp_addr ≝ \snd def_tmp_addr in let 〈tmp_addr1, tmp_addr2〉 ≝ make_addr ? tmp_addr ? in let 〈def, tmpr〉 ≝ fresh_reg def in let insts_save_addr ≝ translate_move save_addr addr in let f ≝ λtranslates_off. λr. let 〈translates, off〉 ≝ translates_off in let translates ≝ translates @ [ adds_graph [ rtl_st_int tmpr off start_lbl ]; translate_op2 Oaddp tmp_addr ? save_addr [tmpr] ? ?; adds_graph [ rtl_st_load r tmp_addr1 tmp_addr2 dest_lbl ] ] in let 〈carry, result〉 ≝ half_add ? off int_size in 〈translates, result〉 in let 〈translates, ignore〉 ≝ foldl ? ? f 〈[ ], (zero ?)〉 destrs in add_translates (insts_save_addr :: translates) start_lbl dest_lbl def ] ]. [1: normalize // |2: >save_addr_prf normalize @(transitive_le 1 2 (|addr|)) // |3: >tmp_addr_prf normalize @(transitive_le 1 2 (|addr|)) // |*: >tmp_addr_prf assumption ] qed. definition translate_store ≝ λaddr. λaddr_prf: 2 ≤ |addr|. λsrcrs: list register. λstart_lbl: label. λdest_lbl: label. λdef: rtl_internal_function. match fresh_regs_strong def (|addr|) with [ dp def_tmp_addr tmp_addr_prf ⇒ let def ≝ \fst def_tmp_addr in let tmp_addr ≝ \snd def_tmp_addr in let 〈tmp_addr1, tmp_addr2〉 ≝ make_addr ? tmp_addr ? in let 〈def, tmpr〉 ≝ fresh_reg def in let f ≝ λtranslate_off. λsrcr. let 〈translates, off〉 ≝ translate_off in let translates ≝ translates @ [ adds_graph [ rtl_st_int tmpr off start_lbl ]; translate_op2 Oaddp tmp_addr ? addr [tmpr] ? ?; adds_graph [ rtl_st_store tmp_addr1 tmp_addr2 srcr dest_lbl ] ] in let 〈carry, result〉 ≝ half_add ? off int_size in 〈translates, result〉 in let 〈translates, ignore〉 ≝ foldl ? ? f 〈[ ], zero ?〉 srcrs in add_translates translates start_lbl dest_lbl def ]. [1: normalize // |2: >tmp_addr_prf normalize @(transitive_le 1 2 (|addr|)) // |3: >tmp_addr_prf normalize @(transitive_le 1 2 (|addr|)) // |*: >tmp_addr_prf assumption ] qed. definition translate_stmt ≝ λlenv. λlbl: label. λstmt. λdef: rtl_internal_function. match stmt with [ St_skip lbl' ⇒ add_graph lbl (rtl_st_skip lbl') def | St_cost cost_lbl lbl' ⇒ add_graph lbl (rtl_st_cost cost_lbl lbl') def | St_const destr cst lbl' ⇒ translate_cst cst (find_local_env destr lenv) lbl lbl' def | St_op1 op1 destr srcr lbl' ⇒ translate_op1 op1 (find_local_env destr lenv) (find_local_env srcr lenv) ? lbl lbl' def | St_op2 op2 destr srcr1 srcr2 lbl' ⇒ translate_op2 op2 (find_local_env destr lenv) ? (find_local_env srcr1 lenv) (find_local_env srcr2 lenv) ? ? lbl lbl' def | St_load ignore addr destr lbl' ⇒ translate_load (find_local_env addr lenv) ? (find_local_env destr lenv) lbl lbl' def | St_store ignore addr srcr lbl' ⇒ translate_store (find_local_env addr lenv) ? (find_local_env srcr lenv) lbl lbl' def | St_call_id f args retr lbl' ⇒ match retr with [ Some retr ⇒ add_graph lbl (rtl_st_call_id f (rtl_args args lenv) (find_local_env retr lenv) lbl') def | None ⇒ add_graph lbl (rtl_st_call_id f (rtl_args args lenv) [ ] lbl') def ] | St_call_ptr f args retr lbl' ⇒ match retr with [ None ⇒ let 〈f1, f2〉 ≝ find_and_addr f lenv ? in add_graph lbl (rtl_st_call_ptr f1 f2 (rtl_args args lenv) [ ] lbl') def | Some retr ⇒ let 〈f1, f2〉 ≝ find_and_addr f lenv ? in add_graph lbl (rtl_st_call_ptr f1 f2 (rtl_args args lenv) (find_local_env retr lenv) lbl') def ] | St_tailcall_id f args ⇒ add_graph lbl (rtl_st_tailcall_id f (rtl_args args lenv)) def | St_tailcall_ptr f args ⇒ let 〈f1, f2〉 ≝ find_and_addr f lenv ? in add_graph lbl (rtl_st_tailcall_ptr f1 f2 (rtl_args args lenv)) def | St_cond r lbl_true lbl_false ⇒ translate_cond (find_local_env r lenv) lbl lbl_true lbl_false def | St_jumptable r l ⇒ ? (* assert false: not implemented yet *) | St_return ⇒ add_graph lbl rtl_st_return def ]. [10: cases not_implemented (* jtable case *) |*: cases daemon (* TODO: proofs regarding lengths of lists, examine! *) ] qed. (* XXX: we use a "hack" here to circumvent the proof obligations required to create res, an empty internal_function record. we insert into our graph the start and end nodes to ensure that they are in, and place dummy skip instructions at these nodes. *) definition translate_internal ≝ λdef. let runiverse ≝ f_reggen def in let lenv ≝ initialize_local_env runiverse (f_params def @ f_locals def) (f_result def) in let params ≝ map_list_local_env lenv (map ? ? \fst (f_params def)) in let locals ≝ map_list_local_env lenv (map ? ? \fst (f_locals def)) in let result ≝ match (f_result def) with [ None ⇒ [ ] | Some r_typ ⇒ let 〈r, typ〉 ≝ r_typ in find_local_env r lenv ] in let luniverse' ≝ f_labgen def in let runiverse' ≝ runiverse in let result' ≝ result in let params' ≝ params in let locals' ≝ locals in let stack_size' ≝ f_stacksize def in let entry' ≝ f_entry def in let exit' ≝ f_exit def in let graph' ≝ add ? ? (empty_map ? ?) entry' (rtl_st_skip entry') in let graph' ≝ add ? ? graph' exit' (rtl_st_skip exit') in let res ≝ mk_rtl_internal_function luniverse' runiverse' result' params' locals' stack_size' graph' ? ? in foldi ? ? ? (translate_stmt lenv) (f_graph def) res. [1: % [1: @entry' |2: normalize nodelta; @graph_add_lookup @graph_add ] |2: % [1: @exit' |2: normalize nodelta; @graph_add ] ] qed. (*CSC: here we are not doing any alignment on variables, like it is done in OCaml because of CompCert heritage *) definition rtlabs_to_rtl : RTLabs_program → rtl_program ≝ λp. transform_program … p (transf_fundef … translate_internal).