summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/c_backend.ml65
-rw-r--r--src/sail.ml6
2 files changed, 42 insertions, 29 deletions
diff --git a/src/c_backend.ml b/src/c_backend.ml
index 6ab45574..cdd955c4 100644
--- a/src/c_backend.ml
+++ b/src/c_backend.ml
@@ -1522,7 +1522,7 @@ let rec compile_match ctx apat cval case_label =
| CT_tup ctyps ->
let instrs, cleanup, _ = List.fold_left2 fold ([], [], 0) apats ctyps in
instrs, cleanup
- | _ -> assert false
+ | _ -> failwith ("AP_tup with ctyp " ^ string_of_ctyp ctyp)
end
| AP_app (ctor, apat), (frag, ctyp) ->
begin match ctyp with
@@ -1855,21 +1855,6 @@ and compile_block ctx = function
let gs = gensym () in
setup @ [idecl CT_unit gs; call (CL_id gs)] @ cleanup @ rest
-(* FIXME: this function is a bit of a hack *)
-let rec pat_ids (Typ_aux (arg_typ_aux, _) as arg_typ) (P_aux (p_aux, (l, _)) as pat) =
- match p_aux, arg_typ_aux with
- | P_id id, _ -> [id]
- | P_tup pats, Typ_tup arg_typs when List.length pats = List.length arg_typs ->
- List.concat (List.map2 pat_ids arg_typs pats)
- | P_tup pats, _ -> c_error ~loc:l ("Cannot compile tuple pattern " ^ string_of_pat pat ^ " to C, as it doesn't have tuple type.")
- | P_lit (L_aux (L_unit, _)), _ -> let gs = gensym () in [gs]
- | P_wild, Typ_tup arg_typs -> List.map (fun _ -> let gs = gensym () in gs) arg_typs
- | P_wild, _ -> let gs = gensym () in [gs]
- | P_var (pat, _), _ -> pat_ids arg_typ pat
- | P_typ (_, pat), _ -> pat_ids arg_typ pat
- | P_app _, _ -> let gs = gensym () in [gs]
- | _, _ -> c_error ~loc:l ("Cannot compile pattern " ^ string_of_pat pat ^ " : " ^ string_of_typ arg_typ ^ " to C")
-
(** Compile a sail type definition into a IR one. Most of the
actual work of translating the typedefs into C is done by the code
generator, as it's easy to keep track of structs, tuples and unions
@@ -2066,6 +2051,34 @@ let fix_exception ctx instrs =
let instrs = List.map (map_try_block (fix_exception_block ctx)) instrs in
fix_exception_block ctx instrs
+let arg_pats ctx (Typ_aux (arg_typ_aux, _) as arg_typ) (P_aux (p_aux, (l, _)) as pat) =
+ match p_aux, arg_typ_aux with
+ | P_tup pats, Typ_tup arg_typs when List.length pats = List.length arg_typs ->
+ List.map2 (fun pat arg_typ -> pat, ctyp_of_typ ctx arg_typ) pats arg_typs
+ | P_wild, Typ_tup arg_typs -> List.map (fun arg_typ -> pat, ctyp_of_typ ctx arg_typ) arg_typs
+ | _, _ -> [(pat, ctyp_of_typ ctx arg_typ)]
+
+let rec compile_arg_pat ctx label (P_aux (p_aux, (l, _)) as pat, ctyp) =
+ match p_aux with
+ | P_id id -> (id, ([], []))
+ | P_wild -> let gs = gensym () in (gs, ([], []))
+ | P_tup [] | P_lit (L_aux (L_unit, _)) -> let gs = gensym () in (gs, ([], []))
+ | P_var (pat, _) -> compile_arg_pat ctx label (pat, ctyp)
+ | P_typ (_, pat) -> compile_arg_pat ctx label (pat, ctyp)
+ | _ ->
+ let apat = anf_pat pat in
+ let gs = gensym () in
+ let destructure, cleanup = compile_match ctx apat (F_id gs, ctyp) label in
+ (gs, (destructure, cleanup))
+
+let combine_destructure_cleanup xs = List.concat (List.map fst xs), List.concat (List.rev (List.map snd xs))
+
+let fix_destructure fail_label = function
+ | ([], cleanup) -> ([], cleanup)
+ | destructure, cleanup ->
+ let body_label = label "fundef_body_" in
+ (destructure @ [igoto body_label; ilabel fail_label; imatch_failure (); ilabel body_label], cleanup)
+
let letdef_count = ref 0
(** Compile a Sail toplevel definition into an IR definition **)
@@ -2086,28 +2099,28 @@ let rec compile_def ctx = function
| DEF_fundef (FD_aux (FD_function (_, _, _, [FCL_aux (FCL_Funcl (id, Pat_aux (Pat_exp (pat, exp), _)), _)]), _)) ->
let aexp = map_functions (analyze_primop ctx) (c_literals ctx (no_shadow IdSet.empty (anf exp))) in
- if string_of_id id = "main" then prerr_endline (Pretty_print_sail.to_string (pp_aexp aexp)) else ();
let setup, ctyp, call, cleanup = compile_aexp ctx aexp in
- let gs = gensym () in
- let pat = match pat with
- | P_aux (P_tup [], annot) -> P_aux (P_lit (mk_lit L_unit), annot)
- | _ -> pat
- in
+ let fundef_label = label "fundef_fail_" in
let _, Typ_aux (fn_typ, _) = Env.get_val_spec id ctx.tc_env in
let arg_typ, ret_typ = match fn_typ with
| Typ_fn (arg_typ, ret_typ, _) -> arg_typ, ret_typ
| _ -> assert false
in
+ let compiled_args = List.map (compile_arg_pat ctx fundef_label) (arg_pats ctx arg_typ pat) in
+ let gs = gensym () in
+ let destructure, destructure_cleanup =
+ compiled_args |> List.map snd |> combine_destructure_cleanup |> fix_destructure fundef_label
+ in
if is_stack_ctyp ctyp then
- let instrs = [idecl ctyp gs] @ setup @ [call (CL_id gs)] @ cleanup @ [ireturn (F_id gs, ctyp)] in
+ let instrs = destructure @ [idecl ctyp gs] @ setup @ [call (CL_id gs)] @ cleanup @ destructure_cleanup @ [ireturn (F_id gs, ctyp)] in
let instrs = fix_early_stack_return ctx instrs in
let instrs = fix_exception ctx instrs in
- [CDEF_fundef (id, None, pat_ids arg_typ pat, instrs)], ctx
+ [CDEF_fundef (id, None, List.map fst compiled_args, instrs)], ctx
else
- let instrs = setup @ [call (CL_addr gs)] @ cleanup in
+ let instrs = destructure @ setup @ [call (CL_addr gs)] @ cleanup @ destructure_cleanup in
let instrs = fix_early_return (CL_addr gs) ctx instrs in
let instrs = fix_exception ctx instrs in
- [CDEF_fundef (id, Some gs, pat_ids arg_typ pat, instrs)], ctx
+ [CDEF_fundef (id, Some gs, List.map fst compiled_args, instrs)], ctx
| DEF_fundef (FD_aux (FD_function (_, _, _, []), (l, _))) ->
c_error ~loc:l "Encountered function with no clauses"
diff --git a/src/sail.ml b/src/sail.ml
index 888e8eb6..2fada970 100644
--- a/src/sail.ml
+++ b/src/sail.ml
@@ -97,9 +97,9 @@ let options = Arg.align ([
( "-O",
Arg.Tuple [Arg.Set C_backend.optimize_primops;
Arg.Set C_backend.optimize_hoist_allocations;
- Arg.Set C_backend.optimize_enum_undefined;
- Arg.Set C_backend.optimize_struct_updates;
- Arg.Set C_backend.optimize_struct_undefined],
+ (* Arg.Set C_backend.optimize_enum_undefined; *)
+ (* Arg.Set C_backend.optimize_struct_undefined; *)
+ Arg.Set C_backend.optimize_struct_updates ],
" turn on optimizations for C compilation");
( "-lem_ast",
Arg.Set opt_print_lem_ast,