include "joint/SemanticUtils.ma". include "RTL/RTL.ma". (* CSC: syntax.ma in RTLabs *) include alias "common/Identifiers.ma". include alias "ASM/Util.ma". record frame: Type[0] ≝ { fr_ret_regs: list register ; fr_pc: address ; fr_sp: pointer ; fr_carry: beval ; fr_regs: register_env beval }. definition rtl_more_sem_params: more_sem_params rtl_params_ := mk_more_sem_params rtl_params_ (list frame) [] (register_env beval) (λ_.empty_map …) [] [](*dummy*) reg_store reg_retrieve reg_store reg_retrieve reg_store reg_retrieve reg_store reg_retrieve reg_store reg_retrieve (λlocals,dest_src. do v ← reg_retrieve locals (\snd dest_src) ; reg_store (\fst dest_src) v locals). definition rtl_sem_params: sem_params ≝ mk_sem_params … rtl_more_sem_params. definition rtl_init_locals : list register → register_env beval → register_env beval ≝ λlocals,env. foldl ?? (λlenv,reg. add … lenv reg BVundef) env locals. (*CSC: could we use here a dependent type to avoid the Error case? *) axiom EmptyStack: String. axiom OutOfBounds: String. definition rtl_fetch_ra: state … rtl_sem_params → res ((state … rtl_sem_params) × address) ≝ λst. match st_frms ? st with [ nil ⇒ Error ? [MSG EmptyStack] | cons hd tl ⇒ OK … 〈st, fr_pc hd〉 ]. definition rtl_result_regs: ∀globals. genv … (rtl_params globals) → state rtl_sem_params → res (list register) ≝ λglobals,ge,st. do fn ← graph_fetch_function … globals ge st ; OK … (joint_if_result … fn). (*CSC: we could use a dependent type here: the list of return values should have the same length of the list of return registers that store the values. This saves the OutOfBounds exception *) definition rtl_pop_frame: ∀globals. genv … (rtl_params globals) → state … rtl_sem_params → res (state … rtl_sem_params) ≝ λglobals,ge,st. do ret_regs ← rtl_result_regs … ge st ; do ret_vals ← mmap … (λreg.greg_retrieve rtl_sem_params st reg) ret_regs ; match st_frms ? st with [ nil ⇒ Error ? [MSG EmptyStack] | cons hd tl ⇒ do st ← mfold_left_i ?? (λi.λst.λreg. do v ← opt_to_res ? [MSG OutOfBounds] (nth_opt … i ret_vals) ; greg_store rtl_sem_params reg v st) (OK … st) (fr_ret_regs hd) ; OK … (set_frms rtl_sem_params tl (set_regs rtl_sem_params (fr_regs hd) (set_sp … (fr_sp hd) (set_carry … (fr_carry hd) (set_m … (free … (m … st) (pblock (sp … st))) st)))))]. definition rtl_call_function: nat → list register → list register → state … rtl_sem_params → res (state … rtl_sem_params) ≝ λstacksize,formal_arg_regs,actual_arg_regs,st. let 〈mem,b〉 ≝ alloc … (m … st) 0 stacksize XData in do new_regs ← mfold_left2 … (λlenv,dest,src. do v ← greg_retrieve … st src ; OK … (add … lenv dest v)) (OK … (empty_map …)) formal_arg_regs actual_arg_regs ; OK … (set_regs rtl_sem_params new_regs (set_m … mem (set_sp … (mk_pointer XData b ? (mk_offset 0)) st))). cases b * #r #off #E >E % qed. definition rtl_save_frame: address → nat → list register → list register → list register → state … rtl_sem_params → res (state … rtl_sem_params) ≝ λl,stacksize,formal_arg_regs,actual_arg_regs,retregs,st. let frame ≝ mk_frame retregs l (sp … st) (carry … st) (regs … st) :: (st_frms … st) in let st ≝ set_frms rtl_sem_params frame st in rtl_call_function stacksize formal_arg_regs actual_arg_regs st. (*CSC: XXXX, for external functions only*) axiom rtl_fetch_external_args: external_function → state rtl_sem_params → res (list val). axiom rtl_set_result: list val → state rtl_sem_params → res (state rtl_sem_params). definition rtl_more_sem_params1: ∀globals. more_sem_params1 … (rtl_params globals) ≝ λglobals. mk_more_sem_params1 … rtl_more_sem_params graph_succ_p (graph_pointer_of_label …) (graph_fetch_statement …) rtl_fetch_ra (rtl_result_regs …) rtl_init_locals rtl_save_frame (rtl_pop_frame …) rtl_fetch_external_args rtl_set_result. definition rtl_sem_params1: ∀globals. sem_params1 … globals ≝ λglobals. mk_sem_params1 … (rtl_more_sem_params1 globals). definition block_of_register_pair: register → register → state rtl_sem_params → res block ≝ λr1,r2,st. do v1 ← greg_retrieve rtl_sem_params st r1 ; do v2 ← greg_retrieve rtl_sem_params st r2 ; do ptr ← pointer_of_address 〈v1,v2〉 ; OK … (pblock ptr). (* This code is quite similar to eval_call_block: can we factorize it out? *) definition eval_tail_call_block: ∀globals.genv … (rtl_params globals) → state rtl_sem_params → block → call_args rtl_sem_params → IO io_out io_in (trace×(state rtl_sem_params)) ≝ λglobals,ge,st,b,args. ! fd ← opt_to_res … [MSG BadPointer] (find_funct_ptr ?? ge b); match fd with [ Internal fn ⇒ let st ≝ set_m … (free … (m … st) (pblock (sp … st))) st in ! st ← rtl_call_function (joint_if_stacksize … fn) (joint_if_params … fn) args st ; let regs ≝ rtl_init_locals … (joint_if_locals … fn) (regs … st) in let l' ≝ joint_if_entry … fn in ! st ← next … (rtl_sem_params1 …) l' (set_regs rtl_sem_params regs st) ; ret ? 〈 E0, st〉 | External fn ⇒ ?(* ! params ← fetch_external_args … fn st; ! evargs ← check_eventval_list params (sig_args (ef_sig fn)); ! evres ← do_io (ef_id fn) evargs (proj_sig_res (ef_sig fn)); (* CSC: XXX bug here; I think I should split it into Byte-long components; instead I am making a singleton out of it. To be fixed once we fully implement external functions. *) let vs ≝ [mk_val ? evres] in ! st ← set_result … vs st; let st ≝ set_pc … ra st in ret ? 〈Eextcall (ef_id fn) evargs (mk_eventval ? evres), st〉 *) ]. cases daemon (*CSC: XXX tailcall to external function not implemented yet; it needs alls other functions on external calls *) qed. definition rtl_exec_extended: ∀globals. genv globals (rtl_params globals) → rtl_statement_extension → label → state rtl_sem_params → IO io_out io_in (trace × (state rtl_sem_params)) ≝ λglobals,ge,stm,l,st. match stm with [ rtl_st_ext_stack_address dreg1 dreg2 ⇒ let sp ≝ sp ? st in ! 〈dpl,dph〉 ← beval_pair_of_pointer sp ; ! st ← greg_store rtl_sem_params dreg1 dpl st ; ! st ← greg_store rtl_sem_params dreg2 dph st ; ! st ← next … (rtl_sem_params1 globals) l st ; ret ? 〈E0, st〉 | rtl_st_ext_call_ptr r1 r2 args dest ⇒ ! b ← block_of_register_pair r1 r2 st ; ! ra ← succ_pc … (rtl_more_sem_params1 globals) l (pc … st) ; eval_call_block … (mk_sem_params1 … (rtl_more_sem_params1 globals)) ge st b args dest ra | rtl_st_ext_tailcall_id id args ⇒ ! b ← opt_to_res … [MSG MissingSymbol; CTX ? id] (find_symbol ?? ge id); eval_tail_call_block … ge st b args | rtl_st_ext_tailcall_ptr r1 r2 args ⇒ ! b ← block_of_register_pair r1 r2 st ; eval_tail_call_block … ge st b args ]. definition rtl_more_sem_params2: ∀globals. more_sem_params2 … (rtl_params globals) ≝ λglobals. mk_more_sem_params2 … (rtl_more_sem_params1 globals) (rtl_exec_extended …). definition rtl_fullexec ≝ joint_fullexec … (λp. rtl_more_sem_params2 (prog_var_names … p)).