(** This module performs a switch simplification: they are replaced by
equivalent if-then-else statements. This is a temporary hack before
implementing switch tables. *)
let type_of (Clight.Expr (_, t)) = t
let rec simplify_switch e cases stmts = match cases, stmts with
| Clight.LSdefault _, stmt :: _ -> stmt
| Clight.LScase (i, _, lbl_stmts), stmt :: stmts ->
let next_cases = simplify_switch e lbl_stmts stmts in
let ret_type = Clight.Tint (Clight.I32, AST.Signed) in
let cst_i = Clight.Expr (Clight.Econst_int i, type_of e) in
let test = Clight.Expr (Clight.Ebinop (Clight.Oeq, e, cst_i), ret_type) in
Clight.Sifthenelse (test, stmt, next_cases)
| _ -> assert false (* do not use on these arguments *)
let f_expr e _ = e
let f_stmt stmt sub_exprs_res sub_stmts_res = match stmt, sub_stmts_res with
| Clight.Sswitch (e, cases), sub_stmts -> simplify_switch e cases sub_stmts
| _ -> ClightFold.statement_fill_subs stmt sub_exprs_res sub_stmts_res
let simplify_statement = ClightFold.statement2 f_expr f_stmt
let simplify_fundef = function
| Clight.Internal cfun ->
let cfun =
{ cfun with Clight.fn_body = simplify_statement cfun.Clight.fn_body } in
Clight.Internal cfun
| fundef -> fundef
let simplify p =
let f (id, fundef) = (id, simplify_fundef fundef) in
{ p with Clight.prog_funct = List.map f p.Clight.prog_funct }