include "ASM/I8051.ma". include "common/CostLabel.ma". include "common/AST.ma". include "common/Registers.ma". include "common/Graphs.ma". (* Here is the structure of parameter records (downward edges are coercions, the ¦ edge is the only explicitly defined coercion): _____graph_params___ / ¦ \ / params \ / / \ | / stmt_params local_params \ | | inst_params funct_params inst_params : types needed to define instructions stmt_params : adds successor type needed to define statements funct_params : types of result register and parameters of function local_params : adds types of local registers params : adds type of code and lookup function graph_params : is made just of inst_params and local_params, and the coercion to params adds structure common to graph languages *) record inst_params : Type[1] ≝ { acc_a_reg: Type[0] (* registers that will eventually need to be A *) ; acc_b_reg: Type[0] (* registers that will eventually need to be B *) ; acc_a_arg: Type[0] (* arguments that will eventually need to be A *) ; acc_b_arg: Type[0] (* arguments that will eventually need to be B *) ; dpl_reg: Type[0] (* low address registers *) ; dph_reg: Type[0] (* high address registers *) ; dpl_arg: Type[0] (* low address registers *) ; dph_arg: Type[0] (* high address registers *) ; snd_arg : Type[0] (* second argument of binary op *) ; operator1 : Type[0] (* = Op1 in all but RTLabs *) ; operator2 : Type[0] (* = Op2 in all but RTLabs *) ; pair_move: Type[0] (* argument of move instructions *) ; call_args: Type[0] (* arguments of function calls *) ; call_dest: Type[0] (* possible destination of function computation *) ; extend_statements: Type[0] (* other statements not fitting in the general framework *) ; ext_forall_labels : (label → Prop) → extend_statements → Prop }. inductive joint_instruction (p:inst_params) (globals: list ident): Type[0] ≝ | COMMENT: String → joint_instruction p globals | COST_LABEL: costlabel → joint_instruction p globals | MOVE: pair_move p → joint_instruction p globals | POP: acc_a_reg p → joint_instruction p globals | PUSH: acc_a_arg p → joint_instruction p globals | ADDRESS: ∀i: ident. (member i (eq_identifier ?) globals) → dpl_reg p → dph_reg p → joint_instruction p globals | OPACCS: OpAccs → acc_a_reg p → acc_b_reg p → acc_a_arg p → acc_b_arg p → joint_instruction p globals | OP1: operator1 p → acc_a_reg p → acc_a_reg p → joint_instruction p globals | OP2: operator2 p → acc_a_reg p → acc_a_arg p → snd_arg p → joint_instruction p globals (* int, clear and set carry can be done with generic move *) (*| INT: generic_reg p → Byte → joint_instruction p globals | CLEAR_CARRY: joint_instruction p globals | SET_CARRY: joint_instruction p globals *) | LOAD: acc_a_reg p → dpl_arg p → dph_arg p → joint_instruction p globals | STORE: dpl_arg p → dph_arg p → acc_a_arg p → joint_instruction p globals | CALL_ID: ident → call_args p → call_dest p → joint_instruction p globals | COND: acc_a_reg p → label → joint_instruction p globals | extension: extend_statements p → joint_instruction p globals. definition inst_forall_labels : ∀p : inst_params.∀globals. (label → Prop) → joint_instruction p globals → Prop ≝ λp,g,P,inst. match inst with [ COND _ l ⇒ P l | extension ext_s ⇒ ext_forall_labels p P ext_s | _ ⇒ True ]. record stmt_params : Type[1] ≝ { inst_pars :> inst_params ; succ : Type[0] ; succ_choice : (succ = label) + (succ = unit) }. inductive joint_statement (p: stmt_params) (globals: list ident): Type[0] ≝ | sequential: joint_instruction p globals → succ p → joint_statement p globals | GOTO: label → joint_statement p globals | RETURN: joint_statement p globals. (* for all labels in statement. Uses succ_choice to consider the successor of a statement when such successors are labels *) definition stmt_forall_labels : ∀p : stmt_params.∀globals. (label → Prop) → joint_statement p globals → Prop. *#i_pr#succ#succ_choice#globals#P* [#instr cases succ_choice #eq >eq #next [@(inst_forall_labels … P instr ∧ P next) |@(inst_forall_labels … P instr) ] |@P |@True ]qed. record funct_params : Type[1] ≝ { resultT : Type[0] ; paramsT : Type[0] }. record local_params : Type[1] ≝ { funct_pars :> funct_params ; localsT: Type[0] }. record params : Type[1] ≝ { stmt_pars :> stmt_params ; local_pars :> local_params ; codeT: list ident → Type[0] ; lookup: ∀globals.codeT globals → label → option (joint_statement stmt_pars globals) }. record graph_params : Type[1] ≝ { g_inst_pars :> inst_params ; g_local_pars :> local_params }. definition labels_present : ∀p : params.∀globals. codeT p globals → (joint_statement p globals) → Prop ≝ λglobals,p,code,s. stmt_forall_labels globals p (λl.lookup … code l ≠ None ?) s. definition forall_stmts : ∀p : params.∀globals. ∀P: joint_statement p globals → Prop. codeT p globals → Prop ≝ λglobals,p,P,code. ∀l,s. lookup … code l = Some ? s → P s. definition code_closed : ∀p : params.∀globals. codeT p globals → Prop ≝ λp,globals,code. forall_stmts … (labels_present … code) code. include alias "common/Graphs.ma". (* To pick the right lookup *) (* One common instantiation of params via Graphs of joint_statements (all languages but LIN) *) definition params_of_graph_params: graph_params → params ≝ λgp. let stmt_pars ≝ mk_stmt_params gp label (inl … (refl …)) in mk_params stmt_pars gp (* codeT ≝ *)(λglobals.graph (joint_statement stmt_pars globals)) (λglobals.lookup …). coercion graph_params_to_params : ∀gp : graph_params.params ≝ λgp.params_of_graph_params gp on _gp : graph_params to params. (* CSC: special case where localsT is a list of registers (RTL and ERTL) *) definition rtl_ertl_params ≝ λinst_pars,funct_pars. params_of_graph_params (mk_graph_params inst_pars (mk_local_params funct_pars (list register))). record joint_internal_function (globals: list ident) (p:params) : Type[0] ≝ { joint_if_luniverse: universe LabelTag; (*CSC: used only for compilation*) joint_if_runiverse: universe RegisterTag; (*CSC: used only for compilation*) (* Paolo: if we want this machinery to work for RTLabs too, we will need the following, right? *) (* joint_if_sig: signature; -- dropped in front end *) joint_if_result : resultT p; joint_if_params : paramsT p; joint_if_locals : localsT p; (*CSC: XXXXX stacksize unused for LTL-...*) joint_if_stacksize: nat; joint_if_code : codeT p globals ; (*CSC: XXXXX entry unused for LIN, but invariant in that case... *) joint_if_entry : Σl: label. lookup … joint_if_code l ≠ None ?; (*CSC: XXXXX exit only used up to RTL (and only for tailcall removal) *) joint_if_exit : Σl: label. lookup … joint_if_code l ≠ None ? }. definition joint_closed_internal_function ≝ λglobals,p. Σdef : joint_internal_function globals p. code_closed … (joint_if_code … def). (* Currified form *) definition set_joint_if_exit ≝ λglobals,pars. λexit: label. λp:joint_internal_function globals pars. λprf: lookup … (joint_if_code … p) exit ≠ None ?. mk_joint_internal_function globals pars (joint_if_luniverse … p) (joint_if_runiverse … p) (joint_if_result … p) (joint_if_params … p) (joint_if_locals … p) (joint_if_stacksize … p) (joint_if_code … p) (joint_if_entry … p) (mk_Sig … exit prf). definition set_joint_code ≝ λglobals: list ident. λpars: params. λint_fun: joint_internal_function globals pars. λgraph: codeT pars globals. λentry. λexit. mk_joint_internal_function globals pars (joint_if_luniverse … int_fun) (joint_if_runiverse … int_fun) (joint_if_result … int_fun) (joint_if_params … int_fun) (joint_if_locals … int_fun) (joint_if_stacksize … int_fun) graph entry exit. definition set_joint_if_graph ≝ λglobals,pars. λgraph. λp:joint_internal_function globals pars. λentry_prf: lookup … graph (joint_if_entry … p) ≠ None ?. λexit_prf: lookup … graph (joint_if_exit … p) ≠ None ?. set_joint_code globals pars p graph (mk_Sig … (joint_if_entry … p) entry_prf) (mk_Sig … (joint_if_exit … p) exit_prf). definition set_luniverse ≝ λglobals,pars. λp : joint_internal_function globals pars. λluniverse: universe LabelTag. mk_joint_internal_function globals pars luniverse (joint_if_runiverse … p) (joint_if_result … p) (joint_if_params … p) (joint_if_locals … p) (joint_if_stacksize … p) (joint_if_code … p) (joint_if_entry … p) (joint_if_exit … p). definition set_runiverse ≝ λglobals,pars. λp : joint_internal_function globals pars. λruniverse: universe RegisterTag. mk_joint_internal_function globals pars (joint_if_luniverse … p) runiverse (joint_if_result … p) (joint_if_params … p) (joint_if_locals … p) (joint_if_stacksize … p) (joint_if_code … p) (joint_if_entry … p) (joint_if_exit … p). (* Paolo: probably should move these elsewhere *) definition graph_dom ≝ λX.λg : graph X.Σl : label.lookup … g l ≠ None ?. definition graph_dom_add_incl : ∀X.∀g : graph X.∀l : label.∀x : X. graph_dom ? g → graph_dom ? (add … g l x) ≝ λX,g,l,x,sig_l. mk_Sig … (pi1 ?? sig_l) ?. @graph_add_lookup @(pi2 … sig_l) qed. (* Specialized for graph_params *) definition add_graph ≝ λg_pars : graph_params.λglobals.λl:label.λstmt. λp:joint_internal_function globals g_pars. let code ≝ add … (joint_if_code … p) l stmt in mk_joint_internal_function ? g_pars (joint_if_luniverse … p) (joint_if_runiverse … p) (joint_if_result … p) (joint_if_params … p) (joint_if_locals … p) (joint_if_stacksize … p) code (graph_dom_add_incl … (joint_if_entry … p)) (graph_dom_add_incl … (joint_if_exit … p)). definition set_locals ≝ λglobals,pars. λp : joint_internal_function globals pars. λlocals. mk_joint_internal_function globals pars (joint_if_luniverse … p) (joint_if_runiverse … p) (joint_if_result … p) (joint_if_params … p) locals (joint_if_stacksize … p) (joint_if_code … p) (joint_if_entry … p) (joint_if_exit … p). definition joint_function ≝ λp,globals. fundef (joint_internal_function p globals). definition joint_program ≝ λp:params. program (λglobals. joint_function globals p) nat.