diff options
| author | Alasdair Armstrong | 2020-08-06 15:33:25 +0100 |
|---|---|---|
| committer | GitHub | 2020-08-06 15:33:25 +0100 |
| commit | 2c12d9d7f7943cc926089ecc25973ed41e7a19a5 (patch) | |
| tree | d96d3e8cbf4a1ed4fb37d1b25b9d2245ea7ee5a6 | |
| parent | be1bc6fc7090f6fc44cc151df4a3e81ab5f5954d (diff) | |
| parent | ed55c0c8f4d34df9a16e014629e206b957cc544f (diff) | |
Merge pull request #81 from julienfreche/get_set_final
Generate accessors for scalar types, array of scalars and scalars in struct in the sail state
| -rw-r--r-- | src/jib/c_codegen.ml | 179 |
1 files changed, 145 insertions, 34 deletions
diff --git a/src/jib/c_codegen.ml b/src/jib/c_codegen.ml index d5015318..d760e6ec 100644 --- a/src/jib/c_codegen.ml +++ b/src/jib/c_codegen.ml @@ -96,6 +96,10 @@ let rec is_stack_ctyp ctyp = match ctyp with | CT_poly -> true | CT_constant n -> Big_int.less_equal (min_int 64) n && Big_int.greater_equal n (max_int 64) +(** For now, the types that can be used in the state API are the types that fits on the stack. + In the future, this can be expanded to support more complex types if needed. *) +let is_api_ctyp = is_stack_ctyp + let v_mask_lower i = V_lit (VL_bits (Util.list_init i (fun _ -> Sail2_values.B1), true), CT_fbits (i, true)) type codegen_options = { @@ -230,12 +234,15 @@ let sgen_id id = | Some export -> export | None -> mangle (string_of_id id) -let sgen_name = - function +let sgen_name ctyp id = + match id with | Name (id, _) -> sgen_id id | Global (id, _) -> - sprintf "(state->%s)" (sgen_id id) + if is_api_ctyp ctyp then + sprintf "(state_get_%s(state))" (sgen_id id) + else + sprintf "(state->%s)" (sgen_id id) | Have_exception _ -> "(state->have_exception)" | Return _ -> @@ -343,11 +350,14 @@ let rec sgen_value = function let rec sgen_cval ctx = function | V_id (id, ctyp) -> - sgen_name id + sgen_name ctyp id | V_lit (vl, ctyp) -> sgen_value vl | V_call (op, cvals) -> sgen_call ctx op cvals - | V_field (f, field) -> - sprintf "%s.%s" (sgen_cval ctx f) (sgen_uid field) + | V_field (f, field) -> + begin match f with + | V_id (Global (id, _), ctyp) -> sprintf "state_get_%s_in_%s(state)" (sgen_uid field) (sgen_id id) + | _ -> sprintf "%s.%s" (sgen_cval ctx f) (sgen_uid field) + end | V_tuple_member (f, _, n) -> sprintf "%s.%s" (sgen_cval ctx f) (mangle ("tup" ^ string_of_int n)) | V_ctor_kind (f, ctor, unifiers, _) -> @@ -532,25 +542,70 @@ let sgen_cval_param ctx cval = | _ -> sgen_cval ctx cval -let rec sgen_clexp ctx = function +let rec sgen_clexp_state_api = function + | CL_id (Global (id, _), _) -> sgen_id id + | CL_field (clexp, field) -> sgen_uid field ^ "_in_" ^ sgen_clexp_state_api clexp + | _ -> assert false + +let sgen_cval_state_api = function + | V_id (Global (id, _), ctyp) -> sgen_id id + | _ -> assert false + +let rec is_state_api_cval = function + | V_id (Global (id, _), ctyp) -> + begin match ctyp with + | CT_vector (_, vctyp) -> is_api_ctyp vctyp + | CT_fvector (_, _, vctyp) -> is_api_ctyp vctyp + | _ when is_api_ctyp ctyp -> true + | _ -> false + end + | V_field (clexp, field) -> is_state_api_cval clexp + | _ -> false + +let rec is_state_api_clexp = function + | CL_id (Global (id, _), ctyp) -> + begin match ctyp with + | CT_vector (_, vctyp) -> is_api_ctyp vctyp + | CT_fvector (_, _, vctyp) -> is_api_ctyp vctyp + | _ when is_api_ctyp ctyp -> true + | _ -> false + end + | CL_field (clexp, field) -> is_state_api_clexp clexp + | _ -> false + +let rec sgen_clexp ctx clexp = + match clexp with | CL_id (Have_exception _, _) -> "(state->have_exception)" | CL_id (Current_exception _, _) -> "(state->current_exception)" | CL_id (Throw_location _, _) -> "(state->throw_location)" | CL_id (Return _, _) -> assert false - | CL_id (Global (id, _), _) -> "&(state->" ^ sgen_id id ^ ")" + | CL_id (Global (id, _), _) -> + let ctyp = clexp_ctyp clexp in + if is_api_ctyp ctyp then + "(state_get_" ^ sgen_id id ^ "(state))" + else + "&(state->" ^ sgen_id id ^ ")" | CL_id (Name (id, _), _) -> "&" ^ sgen_id id - | CL_field (clexp, field) -> "&((" ^ sgen_clexp ctx clexp ^ ")->" ^ sgen_uid field ^ ")" + | CL_field (clexp, field) -> + begin match clexp with + | CL_id (Global (id, _), ctyp) when is_api_ctyp ctyp -> "(state_get_ " ^ sgen_uid field ^ "_in_" ^ sgen_clexp_state_api clexp ^ "(state))" + | _ -> "&((" ^ sgen_clexp ctx clexp ^ ")->" ^ sgen_uid field ^ ")" + end | CL_tuple (clexp, n) -> "&((" ^ sgen_clexp ctx clexp ^ ")->" ^ mangle ("tup" ^ string_of_int n) ^ ")" | CL_addr clexp -> "(*(" ^ sgen_clexp ctx clexp ^ "))" | CL_void -> assert false | CL_rmw _ -> assert false -let rec sgen_clexp_pure ctx = function +let rec sgen_clexp_pure ctx clexp = + match clexp with | CL_id (Have_exception _, _) -> "(state->have_exception)" | CL_id (Current_exception _, _) -> "(state->current_exception)" | CL_id (Throw_location _, _) -> "(state->throw_location)" | CL_id (Return _, _) -> assert false - | CL_id (Global (id, _), _) -> "state->" ^ sgen_id id + | CL_id (Global (id, _), _) -> + let ctyp = clexp_ctyp clexp in + assert (not (is_api_ctyp ctyp)); + "state->" ^ sgen_id id | CL_id (Name (id, _), _) -> sgen_id id | CL_field (clexp, field) -> sgen_clexp_pure ctx clexp ^ "." ^ sgen_uid field | CL_tuple (clexp, n) -> sgen_clexp_pure ctx clexp ^ "." ^ mangle ("tup" ^ string_of_int n) @@ -569,7 +624,10 @@ let rec codegen_conversion l ctx clexp cval = (* When both types are equal, we don't need any conversion. *) | _, _ when ctyp_equal ctyp_to ctyp_from -> if is_stack_ctyp ctyp_to then - ksprintf string " %s = %s;" (sgen_clexp_pure ctx clexp) (sgen_cval ctx cval) + if is_state_api_clexp clexp then + ksprintf string " state_set_%s(state, %s);" (sgen_clexp_state_api clexp) (sgen_cval ctx cval) + else + ksprintf string " %s = %s;" (sgen_clexp_pure ctx clexp) (sgen_cval ctx cval) else ksprintf string " COPY(%s)(%s, %s);" (sgen_ctyp_name ctyp_to) (sgen_clexp ctx clexp) (sgen_cval ctx cval) @@ -590,6 +648,10 @@ let rec codegen_conversion l ctx clexp cval = (* For anything not special cased, just try to call a appropriate CONVERT_OF function. *) | _, _ when is_stack_ctyp (clexp_ctyp clexp) -> + if is_state_api_clexp clexp then + ksprintf string " state_set_%s(state, CONVERT_OF(%s, %s)(%s));" + (sgen_clexp_state_api clexp) (sgen_ctyp_name ctyp_to) (sgen_ctyp_name ctyp_from) (sgen_cval_param ctx cval) + else ksprintf string " %s = CONVERT_OF(%s, %s)(%s);" (sgen_clexp_pure ctx clexp) (sgen_ctyp_name ctyp_to) (sgen_ctyp_name ctyp_from) (sgen_cval_param ctx cval) | _, _ -> @@ -607,10 +669,10 @@ let extra_arguments is_extern = let rec codegen_instr fid ctx (I_aux (instr, (_, l))) = match instr with | I_decl (ctyp, id) when is_stack_ctyp ctyp -> - ksprintf string " %s %s;" (sgen_ctyp ctyp) (sgen_name id) + ksprintf string " %s %s;" (sgen_ctyp ctyp) (sgen_name ctyp id) | I_decl (ctyp, id) -> - ksprintf string " %s %s;" (sgen_ctyp ctyp) (sgen_name id) ^^ hardline - ^^ ksprintf string " CREATE(%s)(&%s);" (sgen_ctyp_name ctyp) (sgen_name id) + ksprintf string " %s %s;" (sgen_ctyp ctyp) (sgen_name ctyp id) ^^ hardline + ^^ ksprintf string " CREATE(%s)(&%s);" (sgen_ctyp_name ctyp) (sgen_name ctyp id) | I_copy (clexp, cval) -> codegen_conversion l ctx clexp cval @@ -650,11 +712,11 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) = else (sgen_function_uid f, false) in - let sail_state_arg = - if is_extern && StringSet.mem fname O.opts.state_primops then + let sail_state_arg : string ref = ref + (if is_extern && StringSet.mem fname O.opts.state_primops then "sail_state *state, " else - "" + "") in let fname = match fname, ctyp with @@ -677,6 +739,7 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) = | "vector_access", CT_bit -> "bitvector_access" | "vector_access", _ -> begin match args with + | cval :: _ when is_state_api_cval cval -> sail_state_arg := "state, "; sprintf "state_vector_access_%s" (sgen_cval_state_api cval) | cval :: _ -> sprintf "vector_access_%s" (sgen_ctyp_name (cval_ctyp cval)) | _ -> Reporting.unreachable l __POS__ "vector access function with bad arity." end @@ -684,7 +747,11 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) = | "vector_subrange", _ -> sprintf "vector_subrange_%s" (sgen_ctyp_name ctyp) | "vector_update", CT_fbits _ -> "update_fbits" | "vector_update", CT_lbits _ -> "update_lbits" - | "vector_update", _ -> sprintf "vector_update_%s" (sgen_ctyp_name ctyp) + | "vector_update", _ -> if is_state_api_clexp x then ( + sail_state_arg := "state, "; + sprintf "state_vector_update_%s" (sgen_clexp_state_api x)) + else + sprintf "vector_update_%s" (sgen_ctyp_name ctyp) | "string_of_bits", _ -> begin match cval_ctyp (List.nth args 0) with | CT_fbits _ -> "string_of_fbits" @@ -713,14 +780,17 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) = ksprintf string " COPY(%s)(&%s, *(%s));" (sgen_ctyp_name ctyp) (sgen_clexp_pure ctx x) c_args else if is_stack_ctyp ctyp then - ksprintf string " %s = %s(%s%s%s);" (sgen_clexp_pure ctx x) fname sail_state_arg (extra_arguments is_extern) c_args + if is_state_api_clexp x then + ksprintf string " state_set_%s(state, %s(%s%s%s));" (sgen_clexp_state_api x) fname !sail_state_arg (extra_arguments is_extern) c_args + else + ksprintf string " %s = %s(%s%s%s);" (sgen_clexp_pure ctx x) fname !sail_state_arg (extra_arguments is_extern) c_args else - ksprintf string " %s(%s%s%s, %s);" fname sail_state_arg (extra_arguments is_extern) (sgen_clexp ctx x) c_args + ksprintf string " %s(%s%s%s, %s);" fname !sail_state_arg (extra_arguments is_extern) (sgen_clexp ctx x) c_args | I_clear (ctyp, id) when is_stack_ctyp ctyp -> empty | I_clear (ctyp, id) -> - ksprintf string " KILL(%s)(&%s);" (sgen_ctyp_name ctyp) (sgen_name id) + ksprintf string " KILL(%s)(&%s);" (sgen_ctyp_name ctyp) (sgen_name ctyp id) | I_init (ctyp, id, cval) -> codegen_instr fid ctx (idecl ctyp id) ^^ hardline @@ -731,9 +801,9 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) = ^^ codegen_conversion Parse_ast.Unknown ctx (CL_id (id, ctyp)) cval | I_reset (ctyp, id) when is_stack_ctyp ctyp -> - ksprintf string " %s %s;" (sgen_ctyp ctyp) (sgen_name id) + ksprintf string " %s %s;" (sgen_ctyp ctyp) (sgen_name ctyp id) | I_reset (ctyp, id) -> - ksprintf string " RECREATE(%s)(&%s);" (sgen_ctyp_name ctyp) (sgen_name id) + ksprintf string " RECREATE(%s)(&%s);" (sgen_ctyp_name ctyp) (sgen_name ctyp id) | I_return cval -> ksprintf string " return %s;" (sgen_cval ctx cval) @@ -760,8 +830,8 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) = sprintf ".%s = %s" (mangle ("tup" ^ string_of_int n)) init :: inits, prev @ prev' in let inits, prev = List.fold_left fold ([], []) (List.mapi (fun i x -> (i, x)) ctyps) in - sgen_name gs, - [sprintf "struct %s %s = { " (sgen_ctyp_name ctyp) (sgen_name gs) + sgen_name ctyp gs, + [sprintf "struct %s %s = { " (sgen_ctyp_name ctyp) (sgen_name ctyp gs) ^ Util.string_of_list ", " (fun x -> x) inits ^ " };"] @ prev | CT_struct (id, ctors) when is_stack_ctyp ctyp -> let gs = ngensym () in @@ -770,8 +840,8 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) = sprintf ".%s = %s" (sgen_uid uid) init :: inits, prev @ prev' in let inits, prev = List.fold_left fold ([], []) ctors in - sgen_name gs, - [sprintf "struct %s %s = { " (sgen_ctyp_name ctyp) (sgen_name gs) + sgen_name ctyp gs, + [sprintf "struct %s %s = { " (sgen_ctyp_name ctyp) (sgen_name ctyp gs) ^ Util.string_of_list ", " (fun x -> x) inits ^ " };"] @ prev | ctyp -> Reporting.unreachable l __POS__ ("Cannot create undefined value for type: " ^ string_of_ctyp ctyp) in @@ -1154,7 +1224,13 @@ let codegen_vector_header ctx id (direction, ctyp) = string (Printf.sprintf "struct %s {\n size_t len;\n %s *data;\n};\n" (sgen_id id) (sgen_ctyp ctyp)) ^^ string (Printf.sprintf "typedef struct %s %s;" (sgen_id id) (sgen_id id)) in - vector_typedef ^^ twice hardline + vector_typedef ^^ hardline ^^ + string (Printf.sprintf "void vector_update_%s(%s *rop, %s op, sail_int n, %s elem);" (sgen_id id) (sgen_id id) (sgen_id id) (sgen_ctyp ctyp)) ^^ hardline ^^ + if is_stack_ctyp ctyp then + string (Printf.sprintf "%s vector_access_%s(%s op, sail_int n);" (sgen_ctyp ctyp) (sgen_id id) (sgen_id id)) + else + string (Printf.sprintf "static void vector_access_%s(%s *rop, %s op, sail_int n);" (sgen_id id) (sgen_ctyp ctyp) (sgen_id id)) + ^^ twice hardline let codegen_vector_body ctx id (direction, ctyp) = let vector_init = @@ -1184,7 +1260,7 @@ let codegen_vector_body ctx id (direction, ctyp) = ^^ string "}" in let vector_update = - string (Printf.sprintf "static void vector_update_%s(%s *rop, %s op, sail_int n, %s elem) {\n" (sgen_id id) (sgen_id id) (sgen_id id) (sgen_ctyp ctyp)) + string (Printf.sprintf "void vector_update_%s(%s *rop, %s op, sail_int n, %s elem) {\n" (sgen_id id) (sgen_id id) (sgen_id id) (sgen_ctyp ctyp)) ^^ string " int m = sail_int_get_ui(n);\n" ^^ string " if (rop->data == op.data) {\n" ^^ string (if is_stack_ctyp ctyp then @@ -1210,7 +1286,7 @@ let codegen_vector_body ctx id (direction, ctyp) = in let vector_access = if is_stack_ctyp ctyp then - string (Printf.sprintf "static %s vector_access_%s(%s op, sail_int n) {\n" (sgen_ctyp ctyp) (sgen_id id) (sgen_id id)) + string (Printf.sprintf "%s vector_access_%s(%s op, sail_int n) {\n" (sgen_ctyp ctyp) (sgen_id id) (sgen_id id)) ^^ string " int m = sail_int_get_ui(n);\n" ^^ string " return op.data[m];\n" ^^ string "}" @@ -1291,13 +1367,13 @@ let is_decl = function let codegen_decl = function | I_aux (I_decl (ctyp, id), _) -> - string (Printf.sprintf "%s %s;" (sgen_ctyp ctyp) (sgen_name id)) + string (Printf.sprintf "%s %s;" (sgen_ctyp ctyp) (sgen_name ctyp id)) | _ -> assert false let codegen_alloc = function | I_aux (I_decl (ctyp, id), _) when is_stack_ctyp ctyp -> empty | I_aux (I_decl (ctyp, id), _) -> - string (Printf.sprintf " CREATE(%s)(&%s);" (sgen_ctyp_name ctyp) (sgen_name id)) + string (Printf.sprintf " CREATE(%s)(&%s);" (sgen_ctyp_name ctyp) (sgen_name ctyp id)) | _ -> assert false let add_local_labels instrs = @@ -1465,6 +1541,40 @@ let codegen_state_struct_def ctx = function | _ -> empty +let codegen_state_api_struct id ctyp = + match ctyp with + | CT_struct (_, fields) -> separate_map hardline (fun ((fid, _), ctyp) -> if is_api_ctyp ctyp then + string (Printf.sprintf "static inline void state_set_%s_in_%s(sail_state* st, %s u) { st->%s.%s = u; }" (sgen_id fid) (sgen_id id) (sgen_ctyp ctyp) (sgen_id id) (sgen_id fid)) + ^^ hardline ^^ + string (Printf.sprintf "static inline %s state_get_%s_in_%s(sail_state* st) { return st->%s.%s; }" (sgen_ctyp ctyp) (sgen_id fid) (sgen_id id) (sgen_id id) (sgen_id fid)) + else empty) fields ^^ hardline + | _ -> empty + +let codegen_state_api_vector id ctyp vctyp = + string (Printf.sprintf "static inline void state_vector_update_%s(sail_state* st, %s *rop, %s op, sail_int n, %s elem) { vector_update_%s(rop, op, n, elem); }" + (sgen_id id) (sgen_ctyp ctyp) (sgen_ctyp ctyp) (sgen_ctyp vctyp) (sgen_ctyp ctyp)) ^^ hardline ^^ + string (Printf.sprintf "static inline %s state_vector_access_%s(sail_state* st, %s op, sail_int n) { return vector_access_%s(op, n); }" + (sgen_ctyp vctyp) (sgen_id id) (sgen_ctyp ctyp) (sgen_ctyp ctyp)) ^^ hardline + +let codegen_state_api_reg_dec id ctyp = + begin match ctyp with + | _ when is_api_ctyp ctyp -> + ksprintf string "static inline %s state_get_%s(sail_state* st) { return st->%s; }" (sgen_ctyp ctyp) (sgen_id id) (sgen_id id) ^^ hardline ^^ + ksprintf string "static inline void state_set_%s(sail_state* st, %s n) { st->%s = n; }" (sgen_id id) (sgen_ctyp ctyp) (sgen_id id) ^^ hardline ^^ + codegen_state_api_struct id ctyp + | CT_vector (_, vctyp) when is_api_ctyp vctyp -> codegen_state_api_vector id ctyp vctyp + | CT_fvector (_, _, vctyp) when is_api_ctyp vctyp -> codegen_state_api_vector id ctyp vctyp + | _ -> empty + end + +let codegen_state_api ctx = function +| CDEF_reg_dec (id, ctyp, _) -> codegen_state_api_reg_dec id ctyp +| CDEF_let (_, [], _) -> empty +| CDEF_let (_, bindings, _) -> + separate_map hardline (fun (id, ctyp) -> codegen_state_api_reg_dec id ctyp) bindings + ^^ hardline +| _ -> empty + let codegen_state_struct ctx cdefs = string "struct sail_state {" ^^ hardline ^^ concat_map (codegen_state_struct_def ctx) cdefs @@ -1477,7 +1587,8 @@ let codegen_state_struct ctx cdefs = ^^ string " sail_string *throw_location;" ^^ hardline )) ^^ concat_map (fun str -> string (" " ^ str) ^^ hardline) O.opts.extra_state - ^^ string "};" + ^^ string "};" ^^ hardline ^^ hardline + ^^ concat_map (codegen_state_api ctx) cdefs let is_cdef_startup = function | CDEF_startup _ -> true |
