include "Clight/Csyntax.ma". definition add_cost_before : statement → universe CostTag → statement × (universe CostTag) ≝ λs,gen. let 〈l,gen〉 ≝ fresh … gen in 〈Scost l s, gen〉. definition add_cost_after : statement → universe CostTag → statement × (universe CostTag) ≝ λs,gen. let 〈l,gen〉 ≝ fresh … gen in 〈Ssequence s (Scost l Sskip), gen〉. definition add_cost_expr : expr → universe CostTag → expr × (universe CostTag) ≝ λe,gen. let 〈l,gen〉 ≝ fresh … gen in 〈Expr (Ecost l e) (typeof e), gen〉. let rec label_expr (e:expr) (costgen:universe CostTag) on e : expr × (universe CostTag) ≝ match e with [ Expr ed ty ⇒ let 〈ed,costgen〉 ≝ label_expr_descr ed costgen in 〈Expr ed ty, costgen〉 ] and label_expr_descr (e:expr_descr) (costgen:universe CostTag) on e : expr_descr × (universe CostTag) ≝ match e with [ Ederef e' ⇒ let 〈e',costgen〉 ≝ label_expr e' costgen in 〈Ederef e', costgen〉 | Eaddrof e' ⇒ let 〈e',costgen〉 ≝ label_expr e' costgen in 〈Eaddrof e', costgen〉 | Eunop op e' ⇒ let 〈e',costgen〉 ≝ label_expr e' costgen in 〈Eunop op e', costgen〉 | Ebinop op e1 e2 ⇒ let 〈e1,costgen〉 ≝ label_expr e1 costgen in let 〈e2,costgen〉 ≝ label_expr e2 costgen in 〈Ebinop op e1 e2, costgen〉 | Ecast ty e' ⇒ let 〈e',costgen〉 ≝ label_expr e' costgen in 〈Ecast ty e', costgen〉 | Econdition e' e1 e2 ⇒ let 〈e',costgen〉 ≝ label_expr e' costgen in let 〈e1,costgen〉 ≝ label_expr e1 costgen in let 〈e1,costgen〉 ≝ add_cost_expr e1 costgen in let 〈e2,costgen〉 ≝ label_expr e2 costgen in let 〈e2,costgen〉 ≝ add_cost_expr e2 costgen in 〈Econdition e' e1 e2, costgen〉 (* andbool and orbool are changed to conditionals to capture their short-circuiting cost difference *) | Eandbool e1 e2 ⇒ let 〈e1,costgen〉 ≝ label_expr e1 costgen in let 〈e2,costgen〉 ≝ label_expr e2 costgen in let 〈e2,costgen〉 ≝ add_cost_expr e2 costgen in let 〈ef,costgen〉 ≝ add_cost_expr (Expr (Econst_int I32 (zero ?)) (Tint I32 Signed)) costgen in 〈Econdition e1 e2 ef, costgen〉 | Eorbool e1 e2 ⇒ let 〈e1,costgen〉 ≝ label_expr e1 costgen in let 〈et,costgen〉 ≝ add_cost_expr (Expr (Econst_int I32 (repr ? 1)) (Tint I32 Signed)) costgen in let 〈e2,costgen〉 ≝ label_expr e2 costgen in let 〈e2,costgen〉 ≝ add_cost_expr e2 costgen in 〈Econdition e1 et e2, costgen〉 | Efield e' id ⇒ let 〈e',costgen〉 ≝ label_expr e' costgen in 〈Efield e' id, costgen〉 (* The prototype asserts on preexisting cost labels, but I'd quite like to keep them. *) | Ecost l e' ⇒ let 〈e',costgen〉 ≝ label_expr e' costgen in 〈Ecost l e', costgen〉 (* The remaining expressions don't have subexpressions. *) | _ ⇒ 〈e,costgen〉 ]. let rec label_exprs (l:list expr) (costgen:universe CostTag) on l : list expr × (universe CostTag) ≝ match l with [ nil ⇒ 〈nil ?,costgen〉 | cons e es ⇒ let 〈e,costgen〉 ≝ label_expr e costgen in let 〈es,costgen〉 ≝ label_exprs es costgen in 〈e::es,costgen〉 ]. definition label_opt_expr ≝ λoe,costgen. match oe with [ None ⇒ 〈None ?, costgen〉 | Some e ⇒ let 〈e,costgen〉 ≝ label_expr e costgen in 〈Some ? e,costgen〉 ]. let rec label_statement (s:statement) (costgen:universe CostTag) on s : statement × (universe CostTag) ≝ match s with [ Sskip ⇒ 〈Sskip,costgen〉 | Sassign e1 e2 ⇒ let 〈e1,costgen〉 ≝ label_expr e1 costgen in let 〈e2,costgen〉 ≝ label_expr e2 costgen in 〈Sassign e1 e2, costgen〉 | Scall e_ret e_fn e_args ⇒ let 〈e_ret,costgen〉 ≝ label_opt_expr e_ret costgen in let 〈e_fn,costgen〉 ≝ label_expr e_fn costgen in let 〈e_args,costgen〉 ≝ label_exprs e_args costgen in 〈Scall e_ret e_fn e_args, costgen〉 | Ssequence s1 s2 ⇒ let 〈s1,costgen〉 ≝ label_statement s1 costgen in let 〈s2,costgen〉 ≝ label_statement s2 costgen in 〈Ssequence s1 s2, costgen〉 | Sifthenelse e s1 s2 ⇒ let 〈e,costgen〉 ≝ label_expr e costgen in let 〈s1,costgen〉 ≝ label_statement s1 costgen in let 〈s1,costgen〉 ≝ add_cost_before s1 costgen in let 〈s2,costgen〉 ≝ label_statement s2 costgen in let 〈s2,costgen〉 ≝ add_cost_before s2 costgen in 〈Sifthenelse e s1 s2, costgen〉 | Swhile e s' ⇒ let 〈e,costgen〉 ≝ label_expr e costgen in let 〈s',costgen〉 ≝ label_statement s' costgen in let 〈s',costgen〉 ≝ add_cost_before s' costgen in let 〈s,costgen〉 ≝ add_cost_after (Swhile e s') costgen in 〈s,costgen〉 | Sdowhile e s' ⇒ let 〈e,costgen〉 ≝ label_expr e costgen in let 〈s',costgen〉 ≝ label_statement s' costgen in let 〈s',costgen〉 ≝ add_cost_before s' costgen in let 〈s,costgen〉 ≝ add_cost_after (Sdowhile e s') costgen in 〈s,costgen〉 | Sfor s1 e s2 s3 ⇒ let 〈e,costgen〉 ≝ label_expr e costgen in let 〈s1,costgen〉 ≝ label_statement s1 costgen in let 〈s2,costgen〉 ≝ label_statement s2 costgen in let 〈s3,costgen〉 ≝ label_statement s3 costgen in let 〈s3,costgen〉 ≝ add_cost_before s3 costgen in let 〈s,costgen〉 ≝ add_cost_after (Sfor s1 e s2 s3) costgen in 〈s,costgen〉 | Sbreak ⇒ 〈Sbreak,costgen〉 | Scontinue ⇒ 〈Scontinue,costgen〉 | Sreturn opt_e ⇒ let 〈opt_e,costgen〉 ≝ label_opt_expr opt_e costgen in 〈Sreturn opt_e,costgen〉 | Sswitch e ls ⇒ let 〈e,costgen〉 ≝ label_expr e costgen in let 〈ls,costgen〉 ≝ label_lstatements ls costgen in 〈Sswitch e ls, costgen〉 | Slabel l s' ⇒ let 〈s',costgen〉 ≝ label_statement s' costgen in let 〈s',costgen〉 ≝ add_cost_before s' costgen in 〈Slabel l s', costgen〉 | Sgoto l ⇒ 〈Sgoto l, costgen〉 (* The prototype asserts on preexisting cost labels, but I'd quite like to keep them. *) | Scost l s' ⇒ let 〈s',costgen〉 ≝ label_statement s' costgen in 〈Scost l s', costgen〉 ] and label_lstatements (ls:labeled_statements) (costgen:universe CostTag) on ls : labeled_statements × (universe CostTag) ≝ match ls with [ LSdefault s ⇒ let 〈s,costgen〉 ≝ label_statement s costgen in let 〈s,costgen〉 ≝ add_cost_before s costgen in 〈LSdefault s, costgen〉 | LScase sz i s ls' ⇒ let 〈s,costgen〉 ≝ label_statement s costgen in let 〈s,costgen〉 ≝ add_cost_before s costgen in let 〈ls',costgen〉 ≝ label_lstatements ls' costgen in 〈LScase sz i s ls', costgen〉 ]. definition label_function : function → res function ≝ λf. let costgen ≝ new_universe CostTag in let 〈body,costgen〉 ≝ label_statement (fn_body f) costgen in let 〈body,costgen〉 ≝ add_cost_before body costgen in do u ← check_universe_ok ? costgen; OK ? (mk_function (fn_return f) (fn_params f) (fn_vars f) body). definition label_fundef : clight_fundef → res clight_fundef ≝ λf. match f with [ CL_Internal f ⇒ do f ← label_function f; OK ? (CL_Internal f) | CL_External id args ty ⇒ OK ? (CL_External id args ty) ]. definition clight_label : clight_program → res clight_program ≝ λp. transform_partial_program … p label_fundef.