summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlasdair2018-06-30 00:44:48 +0100
committerAlasdair2018-07-05 20:23:05 +0100
commit53210d77dafb13ba1d84c7fbf2e12ce570a20ad0 (patch)
tree038a3628106dc83cc27b90c37218875393f1dbc6 /src
parent4a0fbe2a1c7e535aacbf53e56a2322b1a97ac2ef (diff)
Passes all tests and now builds mips and cheri again
Diffstat (limited to 'src')
-rw-r--r--src/anf.ml2
-rw-r--r--src/bytecode_util.ml21
-rw-r--r--src/c_backend.ml268
3 files changed, 161 insertions, 130 deletions
diff --git a/src/anf.ml b/src/anf.ml
index a5ef5f5e..2cb9da17 100644
--- a/src/anf.ml
+++ b/src/anf.ml
@@ -133,7 +133,7 @@ and 'a aval =
| AV_C_fragment of fragment * 'a
(* Renaming variables in ANF expressions *)
-
+
let rec apat_bindings (AP_aux (apat_aux, _, _)) =
match apat_aux with
| AP_tup apats -> List.fold_left IdSet.union IdSet.empty (List.map apat_bindings apats)
diff --git a/src/bytecode_util.ml b/src/bytecode_util.ml
index 5f2ec7ae..b11b70d0 100644
--- a/src/bytecode_util.ml
+++ b/src/bytecode_util.ml
@@ -73,11 +73,11 @@ let iinit ?loc:(l=Parse_ast.Unknown) ctyp id cval =
let iif ?loc:(l=Parse_ast.Unknown) cval then_instrs else_instrs ctyp =
I_aux (I_if (cval, then_instrs, else_instrs, ctyp), (instr_number (), l))
-let ifuncall ?loc:(l=Parse_ast.Unknown) clexp id cvals ctyp =
- I_aux (I_funcall (clexp, false, id, cvals, ctyp), (instr_number (), l))
+let ifuncall ?loc:(l=Parse_ast.Unknown) clexp id cvals =
+ I_aux (I_funcall (clexp, false, id, cvals), (instr_number (), l))
-let iextern ?loc:(l=Parse_ast.Unknown) clexp id cvals ctyp =
- I_aux (I_funcall (clexp, true, id, cvals, ctyp), (instr_number (), l))
+let iextern ?loc:(l=Parse_ast.Unknown) clexp id cvals =
+ I_aux (I_funcall (clexp, true, id, cvals), (instr_number (), l))
let icopy ?loc:(l=Parse_ast.Unknown) clexp cval =
I_aux (I_copy (clexp, cval), (instr_number (), l))
@@ -104,6 +104,9 @@ let ilabel ?loc:(l=Parse_ast.Unknown) label =
let igoto ?loc:(l=Parse_ast.Unknown) label =
I_aux (I_goto label, (instr_number (), l))
+let iundefined ?loc:(l=Parse_ast.Unknown) ctyp =
+ I_aux (I_undefined ctyp, (instr_number (), l))
+
let imatch_failure ?loc:(l=Parse_ast.Unknown) () =
I_aux (I_match_failure, (instr_number (), l))
@@ -235,10 +238,9 @@ let rec pp_instr ?short:(short=false) (I_aux (instr, aux)) =
pp_keyword "create" ^^ pp_id id ^^ string " : " ^^ pp_ctyp ctyp ^^ string " = " ^^ pp_cval cval
| I_reinit (ctyp, id, cval) ->
pp_keyword "recreate" ^^ pp_id id ^^ string " : " ^^ pp_ctyp ctyp ^^ string " = " ^^ pp_cval cval
- | I_funcall (x, _, f, args, ctyp2) ->
+ | I_funcall (x, _, f, args) ->
separate space [ pp_clexp x; string "=";
- string (string_of_id f |> Util.green |> Util.clear) ^^ parens (separate_map (string ", ") pp_cval args);
- string ":"; pp_ctyp ctyp2 ]
+ string (string_of_id f |> Util.green |> Util.clear) ^^ parens (separate_map (string ", ") pp_cval args) ]
| I_copy (clexp, cval) ->
separate space [pp_clexp clexp; string "="; pp_cval cval]
| I_clear (ctyp, id) ->
@@ -255,6 +257,8 @@ let rec pp_instr ?short:(short=false) (I_aux (instr, aux)) =
pp_keyword "goto" ^^ string (str |> Util.blue |> Util.clear)
| I_match_failure ->
pp_keyword "match_failure"
+ | I_undefined ctyp ->
+ pp_keyword "undefined" ^^ pp_ctyp ctyp
| I_raw str ->
pp_keyword "C" ^^ string (str |> Util.cyan |> Util.clear)
@@ -364,7 +368,7 @@ let instr_deps = function
| I_init (ctyp, id, cval) | I_reinit (ctyp, id, cval) -> cval_deps cval, NS.singleton (G_id id)
| I_if (cval, _, _, _) -> cval_deps cval, NS.empty
| I_jump (cval, label) -> cval_deps cval, NS.singleton (G_label label)
- | I_funcall (clexp, _, _, cvals, _) -> List.fold_left NS.union NS.empty (List.map cval_deps cvals), clexp_deps clexp
+ | I_funcall (clexp, _, _, cvals) -> List.fold_left NS.union NS.empty (List.map cval_deps cvals), clexp_deps clexp
| I_copy (clexp, cval) -> cval_deps cval, clexp_deps clexp
| I_clear (_, id) -> NS.singleton (G_id id), NS.singleton (G_id id)
| I_throw cval | I_return cval -> cval_deps cval, NS.empty
@@ -372,6 +376,7 @@ let instr_deps = function
| I_comment _ | I_raw _ -> NS.empty, NS.empty
| I_label label -> NS.singleton (G_label label), NS.empty
| I_goto label -> NS.empty, NS.singleton (G_label label)
+ | I_undefined _ -> NS.empty, NS.empty
| I_match_failure -> NS.empty, NS.empty
let add_link from_node to_node graph =
diff --git a/src/c_backend.ml b/src/c_backend.ml
index 112fefd4..b0d5fb98 100644
--- a/src/c_backend.ml
+++ b/src/c_backend.ml
@@ -222,7 +222,7 @@ let rec is_stack_ctyp ctyp = match ctyp with
let is_stack_typ ctx typ = is_stack_ctyp (ctyp_of_typ ctx typ)
let ctor_bindings = List.fold_left (fun map (id, ctyp) -> Bindings.add id ctyp map) Bindings.empty
-
+
(**************************************************************************)
(* 3. Optimization of primitives and literals *)
(**************************************************************************)
@@ -545,7 +545,7 @@ let rec map_instrs f (I_aux (instr, aux)) =
| I_funcall _ | I_copy _ | I_clear _ | I_jump _ | I_throw _ | I_return _ -> instr
| I_block instrs -> I_block (f (List.map (map_instrs f) instrs))
| I_try_block instrs -> I_try_block (f (List.map (map_instrs f) instrs))
- | I_comment _ | I_label _ | I_goto _ | I_raw _ | I_match_failure -> instr
+ | I_comment _ | I_label _ | I_goto _ | I_raw _ | I_match_failure | I_undefined _ -> instr
in
I_aux (instr, aux)
@@ -553,12 +553,12 @@ let cval_rename from_id to_id (frag, ctyp) = (frag_rename from_id to_id frag, ct
let rec instr_ctyps (I_aux (instr, aux)) =
match instr with
- | I_decl (ctyp, _) | I_reset (ctyp, _) | I_clear (ctyp, _) -> [ctyp]
+ | I_decl (ctyp, _) | I_reset (ctyp, _) | I_clear (ctyp, _) | I_undefined ctyp -> [ctyp]
| I_init (ctyp, _, cval) | I_reinit (ctyp, _, cval) -> [ctyp; cval_ctyp cval]
| I_if (cval, instrs1, instrs2, ctyp) ->
ctyp :: cval_ctyp cval :: List.concat (List.map instr_ctyps instrs1 @ List.map instr_ctyps instrs2)
- | I_funcall (_, _, _, cvals, ctyp) ->
- ctyp :: List.map cval_ctyp cvals
+ | I_funcall (clexp, _, _, cvals) ->
+ clexp_ctyp clexp :: List.map cval_ctyp cvals
| I_copy (clexp, cval) -> [clexp_ctyp clexp; cval_ctyp cval]
| I_block instrs | I_try_block instrs -> List.concat (List.map instr_ctyps instrs)
| I_throw cval | I_jump (cval, _) | I_return cval -> [cval_ctyp cval]
@@ -726,8 +726,7 @@ let rec compile_aval ctx = function
[iinit (CT_bits true) gs (first_chunk, CT_bits64 (len mod 64, true))]
@ List.map (fun chunk -> ifuncall (CL_id (gs, CT_bits true))
(mk_id "append_64")
- [(F_id gs, CT_bits true); (chunk, CT_bits64 (64, true))]
- (CT_bits true)) chunks,
+ [(F_id gs, CT_bits true); (chunk, CT_bits64 (64, true))]) chunks,
(F_id gs, CT_bits true),
[iclear (CT_bits true) gs]
@@ -774,11 +773,11 @@ let rec compile_aval ctx = function
setup
@ [iextern (CL_id (gs, vector_ctyp))
(mk_id "internal_vector_update")
- [(F_id gs, vector_ctyp); (F_lit (V_int (Big_int.of_int i)), CT_int64); cval] vector_ctyp]
+ [(F_id gs, vector_ctyp); (F_lit (V_int (Big_int.of_int i)), CT_int64); cval]]
@ cleanup
in
[idecl vector_ctyp gs;
- iextern (CL_id (gs, vector_ctyp)) (mk_id "internal_vector_init") [(F_lit (V_int (Big_int.of_int len)), CT_int64)] vector_ctyp]
+ iextern (CL_id (gs, vector_ctyp)) (mk_id "internal_vector_init") [(F_lit (V_int (Big_int.of_int len)), CT_int64)]]
@ List.concat (List.mapi aval_set avals),
(F_id gs, vector_ctyp),
[iclear vector_ctyp gs]
@@ -794,7 +793,7 @@ let rec compile_aval ctx = function
let gs = gensym () in
let mk_cons aval =
let setup, cval, cleanup = compile_aval ctx aval in
- setup @ [ifuncall (CL_id (gs, CT_list ctyp)) (mk_id ("cons#" ^ string_of_ctyp ctyp)) [cval; (F_id gs, CT_list ctyp)] (CT_list ctyp)] @ cleanup
+ setup @ [ifuncall (CL_id (gs, CT_list ctyp)) (mk_id ("cons#" ^ string_of_ctyp ctyp)) [cval; (F_id gs, CT_list ctyp)]] @ cleanup
in
[idecl (CT_list ctyp) gs]
@ List.concat (List.map mk_cons (List.rev avals)),
@@ -835,20 +834,20 @@ let compile_funcall l ctx id args typ =
assert (List.length arg_ctyps = List.length args);
- let sargs = List.map2 setup_arg arg_ctyps args in
-
- let call =
- if ctyp_equal final_ctyp ret_ctyp then
- fun ret -> ifuncall ret id sargs ret_ctyp
- else
- let gs = gensym () in
- setup := idecl ret_ctyp gs :: !setup;
- setup := ifuncall (CL_id (gs, ret_ctyp)) id sargs ret_ctyp :: !setup;
- cleanup := iclear ret_ctyp gs :: !cleanup;
- (fun ret -> icopy ret (F_id gs, ret_ctyp))
- in
+ let setup_args = List.map2 setup_arg arg_ctyps args in
- (List.rev !setup @ [icomment (string_of_id id ^ " : " ^ Util.string_of_list ", " string_of_ctyp arg_ctyps)], final_ctyp, call, !cleanup)
+ List.rev !setup,
+ begin fun clexp ->
+ if ctyp_equal (clexp_ctyp clexp) ret_ctyp then
+ ifuncall clexp id setup_args
+ else
+ let gs = gensym () in
+ iblock [idecl ret_ctyp gs;
+ ifuncall (CL_id (gs, ret_ctyp)) id setup_args;
+ icopy clexp (F_id gs, ret_ctyp);
+ iclear ret_ctyp gs]
+ end,
+ !cleanup
let rec compile_match ctx (AP_aux (apat_aux, env, l)) cval case_label =
let ctx = { ctx with local_env = env } in
@@ -925,26 +924,31 @@ let label str =
incr label_counter;
str
+let pointer_assign ctyp1 ctyp2 =
+ match ctyp1 with
+ | CT_ref ctyp1 when ctyp_equal ctyp1 ctyp2 -> true
+ | CT_ref ctyp1 -> c_error "Incompatible type in pointer assignment"
+ | _ -> false
+
let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
let ctx = { ctx with local_env = env } in
match aexp_aux with
- | AE_let (mut, id, binding_typ, binding, body, typ) ->
+ | AE_let (mut, id, binding_typ, binding, body, body_typ) ->
let binding_ctyp = ctyp_of_typ ctx binding_typ in
- let setup, ctyp, call, cleanup = compile_aexp ctx binding in
+ let setup, call, cleanup = compile_aexp ctx binding in
let letb_setup, letb_cleanup =
[idecl binding_ctyp id; iblock (setup @ [call (CL_id (id, binding_ctyp))] @ cleanup)], [iclear binding_ctyp id]
in
let ctx = { ctx with locals = Bindings.add id (mut, binding_ctyp) ctx.locals } in
- let setup, ctyp, call, cleanup = compile_aexp ctx body in
- let body_ctyp = ctyp_of_typ ctx typ in
- letb_setup @ setup, body_ctyp, call, cleanup @ letb_cleanup
+ let setup, call, cleanup = compile_aexp ctx body in
+ letb_setup @ setup, call, cleanup @ letb_cleanup
| AE_app (id, vs, typ) ->
compile_funcall l ctx id vs typ
| AE_val aval ->
let setup, cval, cleanup = compile_aval ctx aval in
- setup, cval_ctyp cval, (fun clexp -> icopy clexp cval), cleanup
+ setup, (fun clexp -> icopy clexp cval), cleanup
(* Compile case statements *)
| AE_case (aval, cases, typ) ->
@@ -962,8 +966,8 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
c_debug (lazy ("Compiling match"));
let destructure, destructure_cleanup, ctx = compile_match ctx apat cval case_label in
c_debug (lazy ("Compiled match"));
- let guard_setup, _, guard_call, guard_cleanup = compile_aexp ctx guard in
- let body_setup, body_ctyp, body_call, body_cleanup = compile_aexp ctx body in
+ let guard_setup, guard_call, guard_cleanup = compile_aexp ctx guard in
+ let body_setup, body_call, body_cleanup = compile_aexp ctx body in
let gs = gensym () in
let case_instrs =
destructure @ [icomment "end destructuring"]
@@ -982,15 +986,15 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
@ List.concat (List.map compile_case cases)
@ [imatch_failure ()]
@ [ilabel finish_match_label],
- ctyp,
(fun clexp -> icopy clexp (F_id case_return_id, ctyp)),
- (if is_stack_ctyp ctyp then [] else [iclear ctyp case_return_id])
+ [iclear ctyp case_return_id]
@ aval_cleanup
@ [icomment "end match"]
(* Compile try statement *)
| AE_try (aexp, cases, typ) ->
- let aexp_setup, ctyp, aexp_call, aexp_cleanup = compile_aexp ctx aexp in
+ let ctyp = ctyp_of_typ ctx typ in
+ let aexp_setup, aexp_call, aexp_cleanup = compile_aexp ctx aexp in
let try_return_id = gensym () in
let handled_exception_label = label "handled_exception_" in
let compile_case (apat, guard, body) =
@@ -1002,8 +1006,8 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
let try_label = label "try_" in
let exn_cval = (F_current_exception, ctyp_of_typ ctx (mk_typ (Typ_id (mk_id "exception")))) in
let destructure, destructure_cleanup, ctx = compile_match ctx apat exn_cval try_label in
- let guard_setup, _, guard_call, guard_cleanup = compile_aexp ctx guard in
- let body_setup, _, body_call, body_cleanup = compile_aexp ctx body in
+ let guard_setup, guard_call, guard_cleanup = compile_aexp ctx guard in
+ let body_setup, body_call, body_cleanup = compile_aexp ctx body in
let gs = gensym () in
let case_instrs =
destructure @ [icomment "end destructuring"]
@@ -1026,19 +1030,17 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
@ [imatch_failure ();
ilabel handled_exception_label;
icopy CL_have_exception (F_lit (V_bool false), CT_bool)],
- ctyp,
(fun clexp -> icopy clexp (F_id try_return_id, ctyp)),
[]
| AE_if (aval, then_aexp, else_aexp, if_typ) ->
let if_ctyp = ctyp_of_typ ctx if_typ in
let compile_branch aexp =
- let setup, ctyp, call, cleanup = compile_aexp ctx aexp in
+ let setup, call, cleanup = compile_aexp ctx aexp in
fun clexp -> setup @ [call clexp] @ cleanup
in
let setup, cval, cleanup = compile_aval ctx aval in
setup,
- if_ctyp,
(fun clexp -> iif cval
(compile_branch then_aexp clexp)
(compile_branch else_aexp clexp)
@@ -1052,7 +1054,7 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
let compile_fields (id, aval) =
let field_setup, cval, field_cleanup = compile_aval ctx aval in
field_setup
- @ [icopy (CL_field (gs, string_of_id id, ctyp)) cval]
+ @ [icopy (CL_field (gs, string_of_id id, cval_ctyp cval)) cval]
@ field_cleanup
in
let setup, cval, cleanup = compile_aval ctx aval in
@@ -1061,13 +1063,12 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
@ [icopy (CL_id (gs, ctyp)) cval]
@ cleanup
@ List.concat (List.map compile_fields (Bindings.bindings fields)),
- ctyp,
(fun clexp -> icopy clexp (F_id gs, ctyp)),
[iclear ctyp gs]
| AE_short_circuit (SC_and, aval, aexp) ->
let left_setup, cval, left_cleanup = compile_aval ctx aval in
- let right_setup, _, call, right_cleanup = compile_aexp ctx aexp in
+ let right_setup, call, right_cleanup = compile_aexp ctx aexp in
let gs = gensym () in
left_setup
@ [ idecl CT_bool gs;
@@ -1076,12 +1077,11 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
[icopy (CL_id (gs, CT_bool)) (F_lit (V_bool false), CT_bool)]
CT_bool ]
@ left_cleanup,
- CT_bool,
(fun clexp -> icopy clexp (F_id gs, CT_bool)),
[]
| AE_short_circuit (SC_or, aval, aexp) ->
let left_setup, cval, left_cleanup = compile_aval ctx aval in
- let right_setup, _, call, right_cleanup = compile_aexp ctx aexp in
+ let right_setup, call, right_cleanup = compile_aexp ctx aexp in
let gs = gensym () in
left_setup
@ [ idecl CT_bool gs;
@@ -1090,7 +1090,6 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
(right_setup @ [call (CL_id (gs, CT_bool))] @ right_cleanup)
CT_bool ]
@ left_cleanup,
- CT_bool,
(fun clexp -> icopy clexp (F_id gs, CT_bool)),
[]
@@ -1106,38 +1105,24 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
@ field_cleanup
in
List.concat (List.map compile_fields (Bindings.bindings fields)),
- CT_unit,
(fun clexp -> icopy clexp unit_fragment),
[]
| AE_assign (id, assign_typ, aexp) ->
- (* assign_ctyp is the type of the C variable we are assigning to,
- ctyp is the type of the C expression being assigned. These may
- be different. *)
- let pointer_assign ctyp1 ctyp2 =
- match ctyp1 with
- | CT_ref ctyp1 when ctyp_equal ctyp1 ctyp2 -> true
- | CT_ref ctyp1 -> c_error ~loc:l "Incompatible type in pointer assignment"
- | _ -> false
- in
let assign_ctyp = ctyp_of_typ ctx assign_typ in
- let setup, ctyp, call, cleanup = compile_aexp ctx aexp in
- let comment = "assign " ^ string_of_ctyp assign_ctyp ^ " := " ^ string_of_ctyp ctyp in
- if pointer_assign assign_ctyp ctyp then
- setup @ [call (CL_addr (id, assign_ctyp))], CT_unit, (fun clexp -> icopy clexp unit_fragment), cleanup
- else
- setup @ [call (CL_id (id, assign_ctyp))], CT_unit, (fun clexp -> icopy clexp unit_fragment), cleanup
+ let setup, call, cleanup = compile_aexp ctx aexp in
+ setup @ [call (CL_id (id, assign_ctyp))], (fun clexp -> icopy clexp unit_fragment), cleanup
| AE_block (aexps, aexp, _) ->
let block = compile_block ctx aexps in
- let setup, ctyp, call, cleanup = compile_aexp ctx aexp in
- block @ setup, ctyp, call, cleanup
+ let setup, call, cleanup = compile_aexp ctx aexp in
+ block @ setup, call, cleanup
| AE_loop (While, cond, body) ->
let loop_start_label = label "while_" in
let loop_end_label = label "wend_" in
- let cond_setup, _, cond_call, cond_cleanup = compile_aexp ctx cond in
- let body_setup, _, body_call, body_cleanup = compile_aexp ctx body in
+ let cond_setup, cond_call, cond_cleanup = compile_aexp ctx cond in
+ let body_setup, body_call, body_cleanup = compile_aexp ctx body in
let gs = gensym () in
let unit_gs = gensym () in
let loop_test = (F_unary ("!", F_id gs), CT_bool) in
@@ -1152,15 +1137,14 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
@ body_cleanup
@ [igoto loop_start_label])]
@ [ilabel loop_end_label],
- CT_unit,
(fun clexp -> icopy clexp unit_fragment),
[]
| AE_loop (Until, cond, body) ->
let loop_start_label = label "repeat_" in
let loop_end_label = label "until_" in
- let cond_setup, _, cond_call, cond_cleanup = compile_aexp ctx cond in
- let body_setup, _, body_call, body_cleanup = compile_aexp ctx body in
+ let cond_setup, cond_call, cond_cleanup = compile_aexp ctx cond in
+ let body_setup, body_call, body_cleanup = compile_aexp ctx body in
let gs = gensym () in
let unit_gs = gensym () in
let loop_test = (F_id gs, CT_bool) in
@@ -1175,7 +1159,6 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
@ [ijump loop_test loop_end_label]
@ [igoto loop_start_label])]
@ [ilabel loop_end_label],
- CT_unit,
(fun clexp -> icopy clexp unit_fragment),
[]
@@ -1198,7 +1181,6 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
ireturn (F_id gs, fn_return_ctyp)]
in
return_setup @ creturn,
- ctyp_of_typ ctx typ,
(fun clexp -> icomment "unreachable after return"),
[]
@@ -1206,7 +1188,6 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
(* Cleanup info will be handled by fix_exceptions *)
let throw_setup, cval, _ = compile_aval ctx aval in
throw_setup @ [ithrow cval],
- ctyp_of_typ ctx typ,
(fun clexp -> icomment "unreachable after throw"),
[]
@@ -1214,7 +1195,6 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
let ctyp = ctyp_of_typ ctx typ in
let setup, cval, cleanup = compile_aval ctx aval in
setup,
- ctyp,
(fun clexp -> icopy clexp (F_field (fst cval, Util.zencode_string (string_of_id id)), ctyp)),
cleanup
@@ -1235,24 +1215,24 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
in
(* Loop variables *)
- let from_setup, from_ctyp, from_call, from_cleanup = compile_aexp ctx loop_from in
+ let from_setup, from_call, from_cleanup = compile_aexp ctx loop_from in
let from_gs = gensym () in
- let to_setup, to_ctyp, to_call, to_cleanup = compile_aexp ctx loop_to in
+ let to_setup, to_call, to_cleanup = compile_aexp ctx loop_to in
let to_gs = gensym () in
- let step_setup, step_ctyp, step_call, step_cleanup = compile_aexp ctx loop_step in
+ let step_setup, step_call, step_cleanup = compile_aexp ctx loop_step in
let step_gs = gensym () in
- let variable_init gs setup ctyp call cleanup =
+ let variable_init gs setup call cleanup =
[idecl CT_int64 gs;
iblock (setup @ [call (CL_id (gs, CT_int64))] @ cleanup)]
in
let loop_start_label = label "for_start_" in
- let body_setup, _, body_call, body_cleanup = compile_aexp ctx body in
+ let body_setup, body_call, body_cleanup = compile_aexp ctx body in
let body_gs = gensym () in
- variable_init from_gs from_setup from_ctyp from_call from_cleanup
- @ variable_init to_gs to_setup to_ctyp to_call to_cleanup
- @ variable_init step_gs step_setup step_ctyp step_call step_cleanup
+ variable_init from_gs from_setup from_call from_cleanup
+ @ variable_init to_gs to_setup to_call to_cleanup
+ @ variable_init step_gs step_setup step_call step_cleanup
@ [iblock ([idecl CT_int64 loop_var;
icopy (CL_id (loop_var, CT_int64)) (F_id from_gs, CT_int64);
ilabel loop_start_label;
@@ -1266,7 +1246,6 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
else
[icopy (CL_id (loop_var, CT_int64)) (F_op (F_id loop_var, "-", F_id step_gs), CT_int64);
ijump (F_op (F_id loop_var, ">=", F_id to_gs), CT_bool) loop_start_label])])],
- CT_unit,
(fun clexp -> icopy clexp unit_fragment),
[]
@@ -1277,7 +1256,7 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) =
and compile_block ctx = function
| [] -> []
| exp :: exps ->
- let setup, _, call, cleanup = compile_aexp ctx exp in
+ let setup, call, cleanup = compile_aexp ctx exp in
let rest = compile_block ctx exps in
let gs = gensym () in
iblock (setup @ [idecl CT_unit gs; call (CL_id (gs, CT_unit))] @ cleanup) :: rest
@@ -1416,7 +1395,7 @@ let fix_early_stack_return ctx instrs =
in
rewrite_return [] instrs
-let fix_exception_block ctx instrs =
+let fix_exception_block ?return:(return=None) ctx instrs =
let end_block_label = label "end_block_exception_" in
let is_exception_stop (I_aux (instr, _)) =
match instr with
@@ -1446,7 +1425,7 @@ let fix_exception_block ctx instrs =
@ generate_cleanup (historic @ before)
@ [igoto end_block_label]
@ rewrite_exception (historic @ before) after
- | before, (I_aux (I_funcall (x, _, f, args, ctyp), _) as funcall) :: after ->
+ | before, (I_aux (I_funcall (x, _, f, args), _) as funcall) :: after ->
let effects = match Env.get_val_spec f ctx.tc_env with
| _, Typ_aux (Typ_fn (_, _, effects), _) -> effects
| exception (Type_error _) -> no_effect (* nullary union constructor, so no val spec *)
@@ -1461,9 +1440,12 @@ let fix_exception_block ctx instrs =
before @ funcall :: rewrite_exception (historic @ before) after
| _, _ -> assert false (* unreachable *)
in
- rewrite_exception [] instrs
- @ [ilabel end_block_label]
-
+ match return with
+ | None ->
+ rewrite_exception [] instrs @ [ilabel end_block_label]
+ | Some ctyp ->
+ rewrite_exception [] instrs @ [ilabel end_block_label; iundefined ctyp]
+
let rec map_try_block f (I_aux (instr, aux)) =
let instr = match instr with
| I_decl _ | I_reset _ | I_init _ | I_reinit _ -> instr
@@ -1472,13 +1454,13 @@ let rec map_try_block f (I_aux (instr, aux)) =
| I_funcall _ | I_copy _ | I_clear _ | I_throw _ | I_return _ -> instr
| I_block instrs -> I_block (List.map (map_try_block f) instrs)
| I_try_block instrs -> I_try_block (f (List.map (map_try_block f) instrs))
- | I_comment _ | I_label _ | I_goto _ | I_raw _ | I_jump _ | I_match_failure -> instr
+ | I_comment _ | I_label _ | I_goto _ | I_raw _ | I_jump _ | I_match_failure | I_undefined _ -> instr
in
I_aux (instr, aux)
-let fix_exception ctx instrs =
+let fix_exception ?return:(return=None) ctx instrs =
let instrs = List.map (map_try_block (fix_exception_block ctx)) instrs in
- fix_exception_block ctx instrs
+ fix_exception_block ~return:return ctx instrs
let rec 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
@@ -1517,7 +1499,7 @@ let rec compile_def ctx = function
[CDEF_reg_dec (id, ctyp_of_typ ctx typ, [])], ctx
| DEF_reg_dec (DEC_aux (DEC_config (id, typ, exp), _)) ->
let aexp = analyze_functions ctx analyze_primop (c_literals ctx (no_shadow IdSet.empty (anf exp))) in
- let setup, ctyp, call, cleanup = compile_aexp ctx aexp in
+ let setup, call, cleanup = compile_aexp ctx aexp in
let instrs = setup @ [call (CL_id (id, ctyp_of_typ ctx typ))] @ cleanup in
[CDEF_reg_dec (id, ctyp_of_typ ctx typ, instrs)], ctx
@@ -1564,7 +1546,7 @@ let rec compile_def ctx = function
c_debug (lazy (Pretty_print_sail.to_string (pp_aexp aexp)));
let aexp = analyze_functions ctx analyze_primop (c_literals ctx aexp) in
c_debug (lazy (Pretty_print_sail.to_string (pp_aexp aexp)));
- let setup, ctyp, call, cleanup = compile_aexp ctx aexp in
+ let setup, call, cleanup = compile_aexp ctx aexp in
c_debug (lazy "Compiled aexp");
let gs = gensym () in
let destructure, destructure_cleanup =
@@ -1574,16 +1556,16 @@ let rec compile_def ctx = function
c_verbosity := 0;
(* This better be true or something has gone badly wrong. *)
- assert (ctyp_equal (ctyp_of_typ ctx ret_typ) ctyp);
+ let ret_ctyp = ctyp_of_typ ctx ret_typ in
- if is_stack_ctyp ctyp then
- let instrs = destructure @ [idecl ctyp gs] @ setup @ [call (CL_id (gs, ctyp))] @ cleanup @ destructure_cleanup @ [ireturn (F_id gs, ctyp)] in
+ if is_stack_ctyp ret_ctyp then
+ let instrs = destructure @ [idecl ret_ctyp gs] @ setup @ [call (CL_id (gs, ret_ctyp))] @ cleanup @ destructure_cleanup @ [ireturn (F_id gs, ret_ctyp)] in
let instrs = fix_early_stack_return ctx instrs in
- let instrs = fix_exception ctx instrs in
+ let instrs = fix_exception ~return:(Some ret_ctyp) ctx instrs in
[CDEF_fundef (id, None, List.map fst compiled_args, instrs)], orig_ctx
else
- let instrs = destructure @ setup @ [call (CL_addr (gs, ctyp))] @ cleanup @ destructure_cleanup in
- let instrs = fix_early_return (CL_addr (gs, ctyp)) ctx instrs in
+ let instrs = destructure @ setup @ [call (CL_addr (gs, ret_ctyp))] @ cleanup @ destructure_cleanup in
+ let instrs = fix_early_return (CL_addr (gs, ret_ctyp)) ctx instrs in
let instrs = fix_exception ctx instrs in
[CDEF_fundef (id, Some gs, List.map fst compiled_args, instrs)], orig_ctx
@@ -1602,14 +1584,15 @@ let rec compile_def ctx = function
| DEF_val (LB_aux (LB_val (pat, exp), _)) ->
c_debug (lazy ("Compiling letbind " ^ string_of_pat pat));
+ let ctyp = ctyp_of_typ ctx (pat_typ_of pat) in
let aexp = analyze_functions ctx analyze_primop (c_literals ctx (no_shadow IdSet.empty (anf exp))) in
- let setup, ctyp, call, cleanup = compile_aexp ctx aexp in
+ let setup, call, cleanup = compile_aexp ctx aexp in
let apat = anf_pat ~global:true pat in
let gs = gensym () in
let end_label = label "let_end_" in
let destructure, destructure_cleanup, _ = compile_match ctx apat (F_id gs, ctyp) end_label in
let gs_setup, gs_cleanup =
- [idecl ctyp gs], [iclear ctyp gs]
+ [idecl ctyp gs], [iclear ctyp gs]
in
let bindings = List.map (fun (id, typ) -> id, ctyp_of_typ ctx typ) (apat_globals apat) in
let n = !letdef_count in
@@ -1698,15 +1681,15 @@ let rec instrs_rename from_id to_id =
| I_aux (I_if (cval, then_instrs, else_instrs, ctyp), aux) :: instrs ->
I_aux (I_if (crename cval, irename then_instrs, irename else_instrs, ctyp), aux) :: irename instrs
| I_aux (I_jump (cval, label), aux) :: instrs -> I_aux (I_jump (crename cval, label), aux) :: irename instrs
- | I_aux (I_funcall (clexp, extern, id, cvals, ctyp), aux) :: instrs ->
- I_aux (I_funcall (lrename clexp, extern, rename id, List.map crename cvals, ctyp), aux) :: irename instrs
+ | I_aux (I_funcall (clexp, extern, id, cvals), aux) :: instrs ->
+ I_aux (I_funcall (lrename clexp, extern, rename id, List.map crename cvals), aux) :: irename instrs
| I_aux (I_copy (clexp, cval), aux) :: instrs -> I_aux (I_copy (lrename clexp, crename cval), aux) :: irename instrs
| I_aux (I_clear (ctyp, id), aux) :: instrs -> I_aux (I_clear (ctyp, rename id), aux) :: irename instrs
| I_aux (I_return cval, aux) :: instrs -> I_aux (I_return (crename cval), aux) :: irename instrs
| I_aux (I_block block, aux) :: instrs -> I_aux (I_block (irename block), aux) :: irename instrs
| I_aux (I_try_block block, aux) :: instrs -> I_aux (I_try_block (irename block), aux) :: irename instrs
| I_aux (I_throw cval, aux) :: instrs -> I_aux (I_throw (crename cval), aux) :: irename instrs
- | (I_aux ((I_comment _ | I_raw _ | I_label _ | I_goto _ | I_match_failure), _) as instr) :: instrs -> instr :: irename instrs
+ | (I_aux ((I_comment _ | I_raw _ | I_label _ | I_goto _ | I_match_failure | I_undefined _), _) as instr) :: instrs -> instr :: irename instrs
| [] -> []
let hoist_ctyp = function
@@ -1922,7 +1905,7 @@ let rec sgen_ctyp_name = function
| CT_string -> "sail_string"
| CT_real -> "real"
| CT_ref ctyp -> "ref_" ^ sgen_ctyp_name ctyp
-
+
let sgen_cval_param (frag, ctyp) =
match ctyp with
| CT_bits direction ->
@@ -1967,7 +1950,9 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) =
else
string (Printf.sprintf " COPY(%s)(%s, %s);" (sgen_ctyp_name lctyp) (sgen_clexp clexp) (sgen_cval cval))
else
- if is_stack_ctyp lctyp then
+ if pointer_assign lctyp rctyp then
+ string (Printf.sprintf " %s = %s;" (sgen_clexp_pure clexp) (sgen_cval cval))
+ else if is_stack_ctyp lctyp then
string (Printf.sprintf " %s = CONVERT_OF(%s, %s)(%s);"
(sgen_clexp_pure clexp) (sgen_ctyp_name lctyp) (sgen_ctyp_name rctyp) (sgen_cval cval))
else
@@ -1995,8 +1980,9 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) =
string " { /* try */"
^^ jump 2 2 (separate_map hardline (codegen_instr fid ctx) instrs) ^^ hardline
^^ string " }"
- | I_funcall (x, extern, f, args, ctyp) ->
+ | I_funcall (x, extern, f, args) ->
let c_args = Util.string_of_list ", " sgen_cval args in
+ let ctyp = clexp_ctyp x in
let fname =
if Env.is_extern f ctx.tc_env "c" then
Env.get_extern f ctx.tc_env "c"
@@ -2043,13 +2029,10 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) =
else
string (Printf.sprintf " COPY(%s)(&%s, *(%s));" (sgen_ctyp_name ctyp) (sgen_clexp_pure x) c_args)
else
- if ctyp_equal (clexp_ctyp x) ctyp then
- if is_stack_ctyp ctyp then
- string (Printf.sprintf " %s = %s(%s);" (sgen_clexp_pure x) fname c_args)
- else
- string (Printf.sprintf " %s(%s, %s);" fname (sgen_clexp x) c_args)
+ if is_stack_ctyp ctyp then
+ string (Printf.sprintf " %s = %s(%s);" (sgen_clexp_pure x) fname c_args)
else
- failwith "funcall type change!"
+ string (Printf.sprintf " %s(%s, %s);" fname (sgen_clexp x) c_args)
| I_clear (ctyp, id) when is_stack_ctyp ctyp ->
empty
@@ -2086,6 +2069,31 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) =
| I_throw cval ->
c_error "I_throw reached code generator"
+ | I_undefined ctyp ->
+ let rec codegen_exn_return ctyp =
+ match ctyp with
+ | CT_unit -> "UNIT", []
+ | CT_bit -> "UINT64_C(0)", []
+ | CT_int64 -> "INT64_C(0xdeadc0de)", []
+ | CT_bits64 _ -> "UINT64_C(0xdeadc0de)", []
+ | CT_bool -> "false", []
+ | CT_struct (id, ctors) when is_stack_ctyp ctyp ->
+ let gs = gensym () in
+ let fold (inits, prev) (id, ctyp) =
+ let init, prev' = codegen_exn_return ctyp in
+ Printf.sprintf ".%s = %s" (sgen_id id) init :: inits, prev @ prev'
+ in
+ let inits, prev = List.fold_left fold ([], []) ctors in
+ sgen_id gs,
+ [Printf.sprintf "struct %s %s = { " (sgen_ctyp_name ctyp) (sgen_id gs)
+ ^ Util.string_of_list ", " (fun x -> x) inits ^ " };"] @ prev
+ | _ -> assert false
+ in
+ let ret, prev = codegen_exn_return ctyp in
+ separate_map hardline (fun str -> string (" " ^ str)) (List.rev prev)
+ ^^ hardline
+ ^^ string (Printf.sprintf " return %s;" ret)
+
| I_comment str ->
string (" /* " ^ str ^ " */")
@@ -2103,17 +2111,26 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) =
string (" sail_match_failure(\"" ^ String.escaped (string_of_id fid) ^ "\");")
let codegen_type_def ctx = function
- | CTD_enum (id, ids) ->
+ | CTD_enum (id, ((first_id :: _) as ids)) ->
let codegen_eq =
let name = sgen_id id in
string (Printf.sprintf "bool eq_%s(enum %s op1, enum %s op2) { return op1 == op2; }" name name name)
in
+ let codegen_undefined =
+ let name = sgen_id id in
+ string (Printf.sprintf "enum %s UNDEFINED(%s)(unit u) { return %s; }" name name (upper_sgen_id first_id))
+ in
string (Printf.sprintf "// enum %s" (string_of_id id)) ^^ hardline
^^ separate space [string "enum"; codegen_id id; lbrace; separate_map (comma ^^ space) upper_codegen_id ids; rbrace ^^ semi]
^^ twice hardline
^^ codegen_eq
+ ^^ twice hardline
+ ^^ codegen_undefined
+
+ | CTD_enum (id, []) -> c_error ("Cannot compile empty enum " ^ string_of_id id)
| CTD_struct (id, ctors) ->
+ let struct_ctyp = CT_struct (id, ctors) in
(* Generate a set_T function for every struct T *)
let codegen_set (id, ctyp) =
if is_stack_ctyp ctyp then
@@ -2139,9 +2156,11 @@ let codegen_type_def ctx = function
(separate hardline (Bindings.bindings ctors |> List.map (codegen_field_init f) |> List.concat))
rbrace
in
+ (*
let codegen_eq =
string (Printf.sprintf "bool eq_%s(struct %s op1, struct %s op2) { return true; }" (sgen_id id) (sgen_id id) (sgen_id id))
in
+ *)
(* Generate the struct and add the generated functions *)
let codegen_ctor (id, ctyp) =
string (sgen_ctyp ctyp) ^^ space ^^ codegen_id id
@@ -2153,14 +2172,18 @@ let codegen_type_def ctx = function
rbrace
^^ semi ^^ twice hardline
^^ codegen_setter id (ctor_bindings ctors)
- ^^ twice hardline
- ^^ codegen_init "CREATE" id (ctor_bindings ctors)
- ^^ twice hardline
- ^^ codegen_init "RECREATE" id (ctor_bindings ctors)
- ^^ twice hardline
- ^^ codegen_init "KILL" id (ctor_bindings ctors)
+ ^^ if not (is_stack_ctyp struct_ctyp) then
+ twice hardline
+ ^^ codegen_init "CREATE" id (ctor_bindings ctors)
+ ^^ twice hardline
+ ^^ codegen_init "RECREATE" id (ctor_bindings ctors)
+ ^^ twice hardline
+ ^^ codegen_init "KILL" id (ctor_bindings ctors)
+ else empty
+ (*
^^ twice hardline
^^ codegen_eq
+ *)
| CTD_variant (id, tus) ->
let codegen_tu (ctor_id, ctyp) =
@@ -2639,11 +2662,12 @@ let sgen_finish = function
Printf.sprintf " finish_%s();" (sgen_id id)
| _ -> assert false
+ (*
let instrument_tracing ctx =
let module StringSet = Set.Make(String) in
let traceable = StringSet.of_list ["mach_bits"; "sail_string"; "sail_bits"; "sail_int"; "unit"; "bool"] in
let rec instrument = function
- | (I_aux (I_funcall (clexp, _, id, args, ctyp), _) as instr) :: instrs ->
+ | (I_aux (I_funcall (clexp, _, id, args), _) as instr) :: instrs ->
let trace_start =
iraw (Printf.sprintf "trace_start(\"%s\");" (String.escaped (string_of_id id)))
in
@@ -2689,6 +2713,7 @@ let instrument_tracing ctx =
| CDEF_fundef (function_id, heap_return, args, body) ->
CDEF_fundef (function_id, heap_return, args, instrument body)
| cdef -> cdef
+ *)
let bytecode_ast ctx rewrites (Defs defs) =
let assert_vs = Initial_check.extern_of_string dec_ord (mk_id "sail_assert") "(bool, string) -> unit effect {escape}" in
@@ -2720,8 +2745,9 @@ let compile_ast ctx (Defs defs) =
let cdefs = List.concat (List.rev chunks) in
let cdefs = optimize ctx cdefs in
+ (*
let cdefs = if !opt_trace then List.map (instrument_tracing ctx) cdefs else cdefs in
-
+ *)
let docs = List.map (codegen_def ctx) cdefs in
let preamble = separate hardline