summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/c_backend.ml286
1 files changed, 177 insertions, 109 deletions
diff --git a/src/c_backend.ml b/src/c_backend.ml
index 25c1669b..99fd71d1 100644
--- a/src/c_backend.ml
+++ b/src/c_backend.ml
@@ -276,10 +276,11 @@ let rec split_block = function
exp :: exps, last
| [] -> failwith "empty block"
-let anf_pat (P_aux (p_aux, _) as pat) =
+let rec anf_pat (P_aux (p_aux, _) as pat) =
match p_aux with
| P_id id -> AP_id id
| P_wild -> AP_wild
+ | P_tup pats -> AP_tup (List.map anf_pat pats)
| _ -> assert false
let rec anf (E_aux (e_aux, exp_annot) as exp) =
@@ -360,7 +361,6 @@ let rec anf (E_aux (e_aux, exp_annot) as exp) =
let record = List.fold_left (fun r (id, aval) -> Bindings.add id aval r) Bindings.empty (List.map fst fexps) in
exp_wrap (wrap (AE_record_update (aval, record, typ_of exp)))
-
| E_app (id, exps) ->
let aexps = List.map anf exps in
let avals = List.map to_aval aexps in
@@ -420,11 +420,15 @@ let rec anf (E_aux (e_aux, exp_annot) as exp) =
match_wrap (AE_case (match_aval, List.map anf_pexp pexps, typ_of exp))
| E_var (LEXP_aux (LEXP_id id, _), binding, body)
+ | E_var (LEXP_aux (LEXP_cast (_, id), _), binding, body)
| E_let (LB_aux (LB_val (P_aux (P_id id, _), binding), _), body) ->
let env = env_of body in
let lvar = Env.lookup_id id env in
AE_let (id, lvar_typ lvar, anf binding, anf body, typ_of exp)
+ | E_let (LB_aux (LB_val (pat, binding), _), body) ->
+ anf (E_aux (E_case (binding, [Pat_aux (Pat_exp (pat, body), (Parse_ast.Unknown, None))]), exp_annot))
+
| E_tuple exps ->
let aexps = List.map anf exps in
let avals = List.map to_aval aexps in
@@ -485,6 +489,7 @@ type ctyp =
| CT_struct of id * ctyp Bindings.t
| CT_enum of id * IdSet.t
| CT_variant of id * ctyp Bindings.t
+ | CT_string
type ctx =
{ records : (ctyp Bindings.t) Bindings.t;
@@ -513,6 +518,7 @@ let rec ctyp_equal ctyp1 ctyp2 =
| CT_enum (id1, _), CT_enum (id2, _) -> Id.compare id1 id2 = 0
| CT_variant (id1, _), CT_variant (id2, _) -> Id.compare id1 id2 = 0
| CT_tup ctyps1, CT_tup ctyps2 -> List.for_all2 ctyp_equal ctyps1 ctyps2
+ | CT_string, CT_string -> true
| _, _ -> false
let rec string_of_ctyp = function
@@ -527,6 +533,7 @@ let rec string_of_ctyp = function
| CT_bool -> "bool"
| CT_tup ctyps -> "(" ^ Util.string_of_list ", " string_of_ctyp ctyps ^ ")"
| CT_struct (id, _) | CT_enum (id, _) | CT_variant (id, _) -> string_of_id id
+ | CT_string -> "string"
(* Convert a sail type into a C-type *)
let rec ctyp_of_typ ctx (Typ_aux (typ_aux, _) as typ) =
@@ -556,6 +563,7 @@ let rec ctyp_of_typ ctx (Typ_aux (typ_aux, _) as typ) =
| _ -> CT_bv direction
end
| Typ_id id when string_of_id id = "unit" -> CT_unit
+ | Typ_id id when string_of_id id = "string" -> CT_string
| Typ_id id when Bindings.mem id ctx.records -> CT_struct (id, Bindings.find id ctx.records)
| Typ_id id when Bindings.mem id ctx.enums -> CT_enum (id, Bindings.find id ctx.enums)
@@ -567,7 +575,7 @@ let rec ctyp_of_typ ctx (Typ_aux (typ_aux, _) as typ) =
let rec is_stack_ctyp ctyp = match ctyp with
| CT_uint64 _ | CT_int64 | CT_int | CT_unit | CT_bool | CT_enum _ -> true
- | CT_bv _ | CT_mpz -> false
+ | CT_bv _ | CT_mpz | CT_string _ -> false
| CT_struct (_, fields) -> Bindings.for_all (fun _ ctyp -> is_stack_ctyp ctyp) fields
| CT_variant (_, ctors) -> Bindings.for_all (fun _ ctyp -> is_stack_ctyp ctyp) ctors
| CT_tup ctyps -> List.for_all is_stack_ctyp ctyps
@@ -591,13 +599,14 @@ let literal_to_cstring (L_aux (l_aux, _) as lit) =
| _ -> None
let c_literals ctx =
- let c_literal = function
+ let rec c_literal = function
| AV_lit (lit, typ) as v when is_stack_ctyp (ctyp_of_typ ctx typ) ->
begin
match literal_to_cstring lit with
| Some str -> AV_C_fragment (str, typ)
| None -> v
end
+ | AV_tuple avals -> AV_tuple (List.map c_literal avals)
| v -> v
in
map_aval c_literal
@@ -611,7 +620,7 @@ let mask m =
else
failwith "Tried to create a mask literal for a vector greater than 64 bits."
-let c_aval ctx = function
+let rec c_aval ctx = function
| AV_lit (lit, typ) as v ->
begin
match literal_to_cstring lit with
@@ -627,7 +636,7 @@ let c_aval ctx = function
AV_C_fragment (Util.zencode_string (string_of_id id), typ)
| _ -> v
end
- | AV_tuple avals -> AV_tuple avals
+ | AV_tuple avals -> AV_tuple (List.map (c_aval ctx) avals)
let is_c_fragment = function
| AV_C_fragment _ -> true
@@ -643,6 +652,7 @@ let analyze_primop' ctx id args typ =
(* primops add_range and add_atom *)
if string_of_id id = "add_range" || string_of_id id = "add_atom" then
begin
+ prerr_endline "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
let n, m, x, y = match destruct_range typ, args with
| Some (n, m), [x; y] -> n, m, x, y
| _ -> failwith ("add_range has incorrect return type or arity ^ " ^ string_of_typ typ)
@@ -654,9 +664,11 @@ let analyze_primop' ctx id args typ =
if is_c_fragment x && is_c_fragment y then
AE_val (AV_C_fragment (c_fragment_string x ^ " + " ^ c_fragment_string y, typ))
else
- no_change
+ (print_endline "QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ";
+ no_change)
else
- no_change
+ (print_endline "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY";
+ no_change)
| _ -> no_change
end
@@ -736,14 +748,15 @@ let cval_ctyp = function
type clexp =
| CL_id of id
| CL_field of id * id
+ | CL_addr of clexp
type instr =
| I_decl of ctyp * id
| I_alloc of ctyp * id
| I_init of ctyp * id * cval
| I_if of cval * instr list * instr list * ctyp
- | I_funcall of id * id * cval list * ctyp
- | I_convert of id * ctyp * id * ctyp
+ | I_funcall of clexp * id * cval list * ctyp
+ | I_convert of clexp * ctyp * id * ctyp
| I_assign of id * cval
| I_copy of clexp * cval
| I_clear of ctyp * id
@@ -786,9 +799,10 @@ let pp_cval = function
| CV_id (id, ctyp) -> parens (pp_ctyp ctyp) ^^ (pp_id id)
| CV_C_fragment (str, ctyp) -> parens (pp_ctyp ctyp) ^^ (string (str |> Util.cyan |> Util.clear))
-let pp_clexp = function
+let rec pp_clexp = function
| CL_id id -> pp_id id
| CL_field (id, field) -> pp_id id ^^ string "." ^^ pp_id field
+ | CL_addr clexp -> string "*" ^^ pp_clexp clexp
let rec pp_instr = function
| I_decl (ctyp, id) ->
@@ -806,11 +820,11 @@ let rec pp_instr = function
| I_init (ctyp, id, cval) ->
pp_keyword "INIT" ^^ pp_ctyp ctyp ^^ parens (pp_id id ^^ string ", " ^^ pp_cval cval)
| I_funcall (x, f, args, ctyp2) ->
- separate space [ pp_id x; string ":=";
+ separate space [ pp_clexp x; string ":=";
pp_id ~color:Util.red f ^^ parens (separate_map (string ", ") pp_cval args);
string "->"; pp_ctyp ctyp2 ]
| I_convert (x, ctyp1, y, ctyp2) ->
- separate space [ pp_id x; string ":=";
+ separate space [ pp_clexp x; string ":=";
pp_keyword "CONVERT" ^^ pp_ctyp ctyp2 ^^ parens (pp_id y);
string "->"; pp_ctyp ctyp1 ]
| I_assign (id, cval) ->
@@ -830,62 +844,6 @@ let rec pp_instr = function
| I_raw str ->
pp_keyword "C" ^^ string str
-let compile_funcall ctx id args typ =
- let setup = ref [] in
- let cleanup = ref [] in
-
- let _, Typ_aux (fn_typ, _) = Env.get_val_spec id ctx.tc_env in
- let arg_typs, ret_typ = match fn_typ with
- | Typ_fn (Typ_aux (Typ_tup arg_typs, _), ret_typ, _) -> arg_typs, ret_typ
- | Typ_fn (arg_typ, ret_typ, _) -> [arg_typ], ret_typ
- | _ -> assert false
- in
- let arg_ctyps, ret_ctyp = List.map (ctyp_of_typ ctx) arg_typs, ctyp_of_typ ctx ret_typ in
- let final_ctyp = ctyp_of_typ ctx typ in
-
- let setup_arg ctyp aval =
- match aval with
- | AV_C_fragment (c, typ) ->
- if is_stack_ctyp ctyp then
- CV_C_fragment (c, ctyp_of_typ ctx typ)
- else
- let gs = gensym () in
- setup := I_decl (ctyp, gs) :: !setup;
- setup := I_init (ctyp, gs, CV_C_fragment (c, ctyp_of_typ ctx typ)) :: !setup;
- cleanup := I_clear (ctyp, gs) :: !cleanup;
- CV_id (gs, ctyp)
- | AV_id (id, lvar) ->
- let have_ctyp = ctyp_of_typ ctx (lvar_typ lvar) in
- if ctyp_equal ctyp have_ctyp then
- CV_id (id, ctyp)
- else if is_stack_ctyp have_ctyp && not (is_stack_ctyp ctyp) then
- let gs = gensym () in
- setup := I_decl (ctyp, gs) :: !setup;
- setup := I_init (ctyp, gs, CV_id (id, have_ctyp)) :: !setup;
- cleanup := I_clear (ctyp, gs) :: !cleanup;
- CV_id (gs, ctyp)
- else
- CV_id (mk_id ("????" ^ string_of_ctyp (ctyp_of_typ ctx (lvar_typ lvar))), ctyp)
- | _ -> CV_id (mk_id "???", ctyp)
- in
-
- let sargs = List.map2 setup_arg arg_ctyps args in
-
- let call =
- if ctyp_equal final_ctyp ret_ctyp then
- fun ret -> I_funcall (ret, id, sargs, ret_ctyp)
- else if not (is_stack_ctyp ret_ctyp) && is_stack_ctyp final_ctyp then
- let gs = gensym () in
- setup := I_alloc (ret_ctyp, gs) :: !setup;
- setup := I_funcall (gs, id, sargs, ret_ctyp) :: !setup;
- cleanup := I_clear (ret_ctyp, gs) :: !cleanup;
- fun ret -> I_convert (ret, final_ctyp, gs, ret_ctyp)
- else
- assert false
- in
-
- (List.rev !setup, final_ctyp, call, !cleanup)
-
let is_ct_enum = function
| CT_enum _ -> true
| _ -> false
@@ -907,6 +865,23 @@ let rec compile_aval ctx = function
[], CV_id (id, ctyp_of_typ ctx (lvar_typ typ)), []
end
+ | AV_lit (L_aux (L_string str, _), typ) ->
+ [], CV_C_fragment ("\"" ^ str ^ "\"", ctyp_of_typ ctx typ), []
+
+ | AV_lit (L_aux (L_num n, _), typ) when Big_int.less_equal min_int64 n && Big_int.less_equal n max_int64 ->
+ let gs = gensym () in
+ [I_decl (CT_mpz, gs);
+ I_init (CT_mpz, gs, CV_C_fragment (Big_int.to_string n ^ "L", CT_int64))],
+ CV_id (gs, CT_mpz),
+ [I_clear (CT_mpz, gs)]
+
+ | AV_lit (L_aux (L_num n, _), typ) ->
+ let gs = gensym () in
+ [ I_decl (CT_mpz, gs);
+ I_init (CT_mpz, gs, CV_C_fragment ("\"" ^ Big_int.to_string n ^ "\"", CT_string)) ],
+ CV_id (gs, CT_mpz),
+ [I_clear (CT_mpz, gs)]
+
| AV_tuple avals ->
let elements = List.map (compile_aval ctx) avals in
let cvals = List.map (fun (_, cval, _) -> cval) elements in
@@ -920,6 +895,53 @@ let rec compile_aval ctx = function
CV_id (gs, CT_tup (List.map cval_ctyp cvals)),
cleanup
+let compile_funcall ctx id args typ =
+ let setup = ref [] in
+ let cleanup = ref [] in
+
+ let _, Typ_aux (fn_typ, _) = Env.get_val_spec id ctx.tc_env in
+ let arg_typs, ret_typ = match fn_typ with
+ | Typ_fn (Typ_aux (Typ_tup arg_typs, _), ret_typ, _) -> arg_typs, ret_typ
+ | Typ_fn (arg_typ, ret_typ, _) -> [arg_typ], ret_typ
+ | _ -> assert false
+ in
+ let arg_ctyps, ret_ctyp = List.map (ctyp_of_typ ctx) arg_typs, ctyp_of_typ ctx ret_typ in
+ let final_ctyp = ctyp_of_typ ctx typ in
+
+ let setup_arg ctyp aval =
+ let arg_setup, cval, arg_cleanup = compile_aval ctx aval in
+ setup := List.rev arg_setup @ !setup;
+ cleanup := arg_cleanup @ !cleanup;
+ let have_ctyp = cval_ctyp cval in
+ if ctyp_equal ctyp have_ctyp then
+ cval
+ else if is_stack_ctyp have_ctyp && not (is_stack_ctyp ctyp) then
+ let gs = gensym () in
+ setup := I_decl (ctyp, gs) :: !setup;
+ setup := I_init (ctyp, gs, cval) :: !setup;
+ cleanup := I_clear (ctyp, gs) :: !cleanup;
+ CV_id (gs, ctyp)
+ else
+ assert false
+ in
+
+ let sargs = List.map2 setup_arg arg_ctyps args in
+
+ let call =
+ if ctyp_equal final_ctyp ret_ctyp then
+ fun ret -> I_funcall (ret, id, sargs, ret_ctyp)
+ else if not (is_stack_ctyp ret_ctyp) && is_stack_ctyp final_ctyp then
+ let gs = gensym () in
+ setup := I_alloc (ret_ctyp, gs) :: !setup;
+ setup := I_funcall (CL_id gs, id, sargs, ret_ctyp) :: !setup;
+ cleanup := I_clear (ret_ctyp, gs) :: !cleanup;
+ fun ret -> I_convert (ret, final_ctyp, gs, ret_ctyp)
+ else
+ assert false
+ in
+
+ (List.rev !setup, final_ctyp, call, !cleanup)
+
let rec compile_match ctx apat cval case_label =
match apat, cval with
| AP_id pid, CV_C_fragment (code, ctyp) when is_ct_enum ctyp ->
@@ -927,9 +949,17 @@ let rec compile_match ctx apat cval case_label =
| AP_id pid, CV_id (id, ctyp) when is_ct_enum ctyp ->
[ I_if (CV_C_fragment (Util.zencode_upper_string (string_of_id pid) ^ " != " ^ Util.zencode_string (string_of_id id), CT_bool), [I_goto case_label], [], CT_unit) ]
| AP_id pid, CV_C_fragment (code, ctyp) ->
- [ I_init (ctyp, pid, cval) ]
+ [ I_decl (cval_ctyp cval, pid); I_copy (CL_id pid, cval) ]
| AP_id pid, CV_id _ ->
[ I_decl (cval_ctyp cval, pid); I_copy (CL_id pid, cval) ]
+ | AP_tup apats, CV_id (id, ctyp) ->
+ begin
+ let get_tup n ctyp = CV_C_fragment (Util.zencode_string (string_of_id id) ^ ".ztup" ^ string_of_int n, ctyp) in
+ match ctyp with
+ | CT_tup ctyps ->
+ fst (List.fold_left2 (fun (instrs, n) apat ctyp -> instrs @ compile_match ctx apat (get_tup n ctyp) case_label, n + 1) ([], 0) apats ctyps)
+ | _ -> assert false
+ end
| _, _ -> []
let label_counter = ref 0
@@ -944,9 +974,9 @@ let rec compile_aexp ctx = function
let setup, ctyp, call, cleanup = compile_aexp ctx binding in
let letb1, letb1c =
if is_stack_ctyp ctyp then
- [I_decl (ctyp, id); call id], []
+ [I_decl (ctyp, id); call (CL_id id)], []
else
- [I_alloc (ctyp, id); call id], [I_clear (ctyp, id)]
+ [I_alloc (ctyp, id); call (CL_id id)], [I_clear (ctyp, id)]
in
let letb2 = setup @ letb1 @ cleanup in
let setup, ctyp, call, cleanup = compile_aexp ctx body in
@@ -957,7 +987,7 @@ let rec compile_aexp ctx = function
| AE_val aval ->
let setup, cval, cleanup = compile_aval ctx aval in
- setup, cval_ctyp cval, (fun id -> I_copy (CL_id id, cval)), cleanup
+ setup, cval_ctyp cval, (fun clexp -> I_copy (clexp, cval)), cleanup
(* Compile case statements *)
| AE_case (aval, cases, typ) ->
@@ -979,11 +1009,11 @@ let rec compile_aexp ctx = function
let case_instrs =
destructure @ [I_comment "end destructuring"]
@ (if not trivial_guard then
- guard_setup @ [I_decl (CT_bool, gs); guard_call gs] @ guard_cleanup
+ guard_setup @ [I_decl (CT_bool, gs); guard_call (CL_id gs)] @ guard_cleanup
@ [I_if (CV_C_fragment (Printf.sprintf "!%s" (Util.zencode_string (string_of_id gs)), CT_bool), [I_goto case_label], [], CT_unit)]
@ [I_comment "end guard"]
else [])
- @ body_setup @ [body_call case_return_id] @ body_cleanup
+ @ body_setup @ [body_call (CL_id case_return_id)] @ body_cleanup
@ [I_goto finish_match_label]
in
[I_block case_instrs; I_label case_label]
@@ -994,7 +1024,7 @@ let rec compile_aexp ctx = function
@ [I_raw "sail_match_failure();"]
@ [I_label finish_match_label],
ctyp,
- (fun id -> I_copy (CL_id id, CV_id (case_return_id, ctyp))),
+ (fun clexp -> I_copy (clexp, CV_id (case_return_id, ctyp))),
aval_cleanup
@ [I_comment "end match"]
@@ -1002,16 +1032,16 @@ let rec compile_aexp ctx = function
let if_ctyp = ctyp_of_typ ctx if_typ in
let compile_branch aexp =
let setup, ctyp, call, cleanup = compile_aexp ctx aexp in
- fun id -> setup @ [call id] @ cleanup
+ fun clexp -> setup @ [call clexp] @ cleanup
in
let setup, ctyp, call, cleanup = compile_aexp ctx (AE_val aval) in
let gs = gensym () in
- setup @ [I_decl (ctyp, gs); call gs],
+ setup @ [I_decl (ctyp, gs); call (CL_id gs)],
if_ctyp,
- (fun id -> I_if (CV_id (gs, ctyp),
- compile_branch then_aexp id,
- compile_branch else_aexp id,
- if_ctyp)),
+ (fun clexp -> I_if (CV_id (gs, ctyp),
+ compile_branch then_aexp clexp,
+ compile_branch else_aexp clexp,
+ if_ctyp)),
cleanup
| AE_record_update (aval, fields, typ) ->
@@ -1022,9 +1052,9 @@ let rec compile_aexp ctx = function
let setup, calls, cleanup = List.fold_left update_field ([], [], []) (Bindings.bindings fields) in
let ctyp = ctyp_of_typ ctx typ in
let gs = gensym () in
- [I_alloc (ctyp, gs)] @ setup @ List.map (fun call -> call gs) calls,
+ [I_alloc (ctyp, gs)] @ setup @ List.map (fun call -> call (CL_id gs)) calls,
ctyp,
- (fun id -> I_copy (CL_id id, CV_id (gs, ctyp))),
+ (fun clexp -> I_copy (clexp, CV_id (gs, ctyp))),
cleanup @ [I_clear (ctyp, gs)]
| AE_assign (id, assign_typ, aexp) ->
@@ -1036,16 +1066,16 @@ let rec compile_aexp ctx = function
let unit_fragment = CV_C_fragment ("UNIT", CT_unit) in
let comment = "assign " ^ string_of_ctyp assign_ctyp ^ " := " ^ string_of_ctyp ctyp in
if ctyp_equal assign_ctyp ctyp then
- setup @ [call id], CT_unit, (fun id -> I_copy (CL_id id, unit_fragment)), cleanup
+ setup @ [call (CL_id id)], CT_unit, (fun clexp -> I_copy (clexp, unit_fragment)), cleanup
else if not (is_stack_ctyp assign_ctyp) && is_stack_ctyp ctyp then
let gs = gensym () in
setup @ [ I_comment comment;
I_decl (ctyp, gs);
- call gs;
- I_convert (id, assign_ctyp, gs, ctyp)
+ call (CL_id gs);
+ I_convert (CL_id id, assign_ctyp, gs, ctyp)
],
CT_unit,
- (fun id -> I_copy (CL_id id, unit_fragment)),
+ (fun clexp -> I_copy (clexp, unit_fragment)),
cleanup
else
failwith comment
@@ -1055,6 +1085,27 @@ let rec compile_aexp ctx = function
let setup, ctyp, call, cleanup = compile_aexp ctx aexp in
block @ setup, ctyp, call, cleanup
+ | AE_loop (While, cond, body) ->
+ let unit_fragment = CV_C_fragment ("UNIT", CT_unit) in
+ 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 gs = gensym () in
+ let unit_gs = gensym () in
+ let loop_test = CV_C_fragment (Printf.sprintf "!%s" (Util.zencode_string (string_of_id gs)), CT_bool) in
+ cond_setup @ [I_decl (CT_bool, gs); I_decl (CT_unit, unit_gs)]
+ @ [I_label loop_start_label]
+ @ [I_block ([cond_call (CL_id gs); I_if (loop_test, [I_goto loop_end_label], [], CT_unit)]
+ @ body_setup
+ @ [body_call (CL_id unit_gs)]
+ @ body_cleanup
+ @ [I_goto loop_start_label])]
+ @ [I_label loop_end_label],
+ CT_unit,
+ (fun clexp -> I_copy (clexp, unit_fragment)),
+ cond_cleanup
+
| AE_cast (aexp, typ) -> compile_aexp ctx aexp
and compile_block ctx = function
@@ -1063,13 +1114,14 @@ and compile_block ctx = function
let setup, _, call, cleanup = compile_aexp ctx exp in
let rest = compile_block ctx exps in
let gs = gensym () in
- setup @ [I_decl (CT_unit, gs); call gs] @ cleanup @ rest
+ setup @ [I_decl (CT_unit, gs); call (CL_id gs)] @ cleanup @ rest
-let rec pat_ids (P_aux (p_aux, _)) =
+let rec pat_ids (P_aux (p_aux, _) as pat) =
match p_aux with
| P_id id -> [id]
| P_tup pats -> List.concat (List.map pat_ids pats)
- | _ -> failwith "Bad pattern"
+ | P_lit (L_aux (L_unit, _)) -> let gs = gensym () in [gs]
+ | _ -> failwith ("Bad pattern " ^ string_of_pat pat)
let compile_type_def ctx (TD_aux (type_def, _)) =
match type_def with
@@ -1113,10 +1165,10 @@ let compile_def ctx = function
let setup, ctyp, call, cleanup = compile_aexp ctx aexp in
let gs = gensym () in
if is_stack_ctyp ctyp then
- let instrs = [I_decl (ctyp, gs)] @ setup @ [call gs] @ cleanup @ [I_return gs] in
+ let instrs = [I_decl (ctyp, gs)] @ setup @ [call (CL_id gs)] @ cleanup @ [I_return gs] in
[CDEF_fundef (id, None, pat_ids pat, instrs)], ctx
else
- let instrs = setup @ [call gs] @ cleanup in
+ let instrs = setup @ [call (CL_addr (CL_id gs))] @ cleanup in
[CDEF_fundef (id, Some gs, pat_ids pat, instrs)], ctx
| _ -> assert false
end
@@ -1154,6 +1206,7 @@ let sgen_ctyp = function
| CT_struct (id, _) -> "struct " ^ sgen_id id
| CT_enum (id, _) -> "enum " ^ sgen_id id
| CT_variant (id, _) -> "struct " ^ sgen_id id
+ | CT_string -> "sail_string"
let sgen_ctyp_name = function
| CT_unit -> "unit"
@@ -1167,6 +1220,7 @@ let sgen_ctyp_name = function
| CT_struct (id, _) -> sgen_id id
| CT_enum (id, _) -> sgen_id id
| CT_variant (id, _) -> sgen_id id
+ | CT_string -> "sail_string"
let sgen_cval = function
| CV_C_fragment (c, _) -> c
@@ -1174,8 +1228,15 @@ let sgen_cval = function
| _ -> "CVAL??"
let sgen_clexp = function
+ | CL_id id -> "&" ^ sgen_id id
+ | CL_field (id, field) -> "&(" ^ sgen_id id ^ "." ^ sgen_id field ^ ")"
+ | CL_addr (CL_id id) -> sgen_id id
+ | _ -> assert false
+
+let sgen_clexp_pure = function
| CL_id id -> sgen_id id
| CL_field (id, field) -> sgen_id id ^ "." ^ sgen_id field
+ | _ -> assert false
let rec codegen_instr ctx = function
| I_decl (ctyp, id) ->
@@ -1183,7 +1244,7 @@ let rec codegen_instr ctx = function
| I_copy (clexp, cval) ->
let ctyp = cval_ctyp cval in
if is_stack_ctyp ctyp then
- string (Printf.sprintf " %s = %s;" (sgen_clexp clexp) (sgen_cval cval))
+ string (Printf.sprintf " %s = %s;" (sgen_clexp_pure clexp) (sgen_cval cval))
else
string (Printf.sprintf " set_%s(%s, %s);" (sgen_ctyp_name ctyp) (sgen_clexp clexp) (sgen_cval cval))
| I_if (cval, [then_instr], [], ctyp) ->
@@ -1202,13 +1263,13 @@ let rec codegen_instr ctx = function
let args = Util.string_of_list ", " sgen_cval args in
let fname = if Env.is_extern f ctx.tc_env "c" then Env.get_extern f ctx.tc_env "c" else sgen_id f in
if is_stack_ctyp ctyp then
- string (Printf.sprintf " %s = %s(%s);" (sgen_id x) fname args)
+ string (Printf.sprintf " %s = %s(%s);" (sgen_clexp_pure x) fname args)
else
- string (Printf.sprintf " %s(%s, %s);" fname (sgen_id x) args)
+ string (Printf.sprintf " %s(%s, %s);" fname (sgen_clexp x) args)
| I_clear (ctyp, id) ->
- string (Printf.sprintf " clear_%s(%s);" (sgen_ctyp_name ctyp) (sgen_id id))
+ string (Printf.sprintf " clear_%s(&%s);" (sgen_ctyp_name ctyp) (sgen_id id))
| I_init (ctyp, id, cval) ->
- string (Printf.sprintf " init_%s_of_%s(%s, %s);"
+ string (Printf.sprintf " init_%s_of_%s(&%s, %s);"
(sgen_ctyp_name ctyp)
(sgen_ctyp_name (cval_ctyp cval))
(sgen_id id)
@@ -1216,11 +1277,11 @@ let rec codegen_instr ctx = function
| I_alloc (ctyp, id) ->
string (Printf.sprintf " %s %s;" (sgen_ctyp ctyp) (sgen_id id))
^^ hardline
- ^^ string (Printf.sprintf " init_%s(%s);" (sgen_ctyp_name ctyp) (sgen_id id))
+ ^^ string (Printf.sprintf " init_%s(&%s);" (sgen_ctyp_name ctyp) (sgen_id id))
| I_convert (x, ctyp1, y, ctyp2) ->
if is_stack_ctyp ctyp1 then
string (Printf.sprintf " %s = convert_%s_of_%s(%s);"
- (sgen_id x)
+ (sgen_clexp_pure x)
(sgen_ctyp_name ctyp1)
(sgen_ctyp_name ctyp2)
(sgen_id y))
@@ -1228,7 +1289,7 @@ let rec codegen_instr ctx = function
string (Printf.sprintf " convert_%s_of_%s(%s, %s);"
(sgen_ctyp_name ctyp1)
(sgen_ctyp_name ctyp2)
- (sgen_id x)
+ (sgen_clexp x)
(sgen_id y))
| I_return id ->
string (Printf.sprintf " return %s;" (sgen_id id))
@@ -1250,12 +1311,12 @@ let codegen_type_def ctx = function
(* Generate a set_T function for every struct T *)
let codegen_set (id, ctyp) =
if is_stack_ctyp ctyp then
- string (Printf.sprintf "rop.%s = op.%s;" (sgen_id id) (sgen_id id))
+ string (Printf.sprintf "rop->%s = op.%s;" (sgen_id id) (sgen_id id))
else
- string (Printf.sprintf "set_%s(rop.%s, op.%s);" (sgen_ctyp_name ctyp) (sgen_id id) (sgen_id id))
+ string (Printf.sprintf "set_%s(&rop->%s, op.%s);" (sgen_ctyp_name ctyp) (sgen_id id) (sgen_id id))
in
let codegen_setter id ctors =
- string (let n = sgen_id id in Printf.sprintf "void set_%s(struct %s rop, const struct %s op)" n n n) ^^ space
+ string (let n = sgen_id id in Printf.sprintf "void set_%s(struct %s *rop, const struct %s op)" n n n) ^^ space
^^ surround 2 0 lbrace
(separate_map hardline codegen_set (Bindings.bindings ctors))
rbrace
@@ -1263,11 +1324,11 @@ let codegen_type_def ctx = function
(* Generate an init/clear_T function for every struct T *)
let codegen_field_init f (id, ctyp) =
if not (is_stack_ctyp ctyp) then
- [string (Printf.sprintf "%s_%s(op.%s);" f (sgen_ctyp_name ctyp) (sgen_id id))]
+ [string (Printf.sprintf "%s_%s(&op->%s);" f (sgen_ctyp_name ctyp) (sgen_id id))]
else []
in
let codegen_init f id ctors =
- string (let n = sgen_id id in Printf.sprintf "void %s_%s(struct %s op)" f n n) ^^ space
+ string (let n = sgen_id id in Printf.sprintf "void %s_%s(struct %s *op)" f n n) ^^ space
^^ surround 2 0 lbrace
(separate hardline (Bindings.bindings ctors |> List.map (codegen_field_init f) |> List.concat))
rbrace
@@ -1346,7 +1407,7 @@ let codegen_def' ctx = function
| Some gs ->
assert (not (is_stack_ctyp ret_ctyp));
string "void" ^^ space ^^ codegen_id id
- ^^ parens (string (sgen_ctyp ret_ctyp ^ " " ^ sgen_id gs ^ ", ") ^^ string args)
+ ^^ parens (string (sgen_ctyp ret_ctyp ^ " *" ^ sgen_id gs ^ ", ") ^^ string args)
^^ hardline
in
function_header
@@ -1376,14 +1437,21 @@ let compile_ast ctx (Defs defs) =
[ string "#include \"sail.h\"" ]
in
+ let postamble = separate hardline
+ [ string "int main(void)";
+ string "{";
+ string " zmain(UNIT);";
+ string "}" ]
+ in
+
let hlhl = hardline ^^ hardline in
- Pretty_print_sail.to_string (preamble ^^ hlhl ^^ separate hlhl docs)
+ Pretty_print_sail.to_string (preamble ^^ hlhl ^^ separate hlhl docs ^^ hlhl ^^ postamble)
|> print_endline
let print_compiled (setup, ctyp, call, cleanup) =
List.iter (fun instr -> print_endline (Pretty_print_sail.to_string (pp_instr instr))) setup;
- print_endline (Pretty_print_sail.to_string (pp_instr (call (mk_id ("?" ^ string_of_ctyp ctyp)))));
+ print_endline (Pretty_print_sail.to_string (pp_instr (call (CL_id (mk_id ("?" ^ string_of_ctyp ctyp))))));
List.iter (fun instr -> print_endline (Pretty_print_sail.to_string (pp_instr instr))) cleanup
let compile_exp ctx exp =