diff options
Diffstat (limited to 'src/c_backend.ml')
| -rw-r--r-- | src/c_backend.ml | 130 |
1 files changed, 67 insertions, 63 deletions
diff --git a/src/c_backend.ml b/src/c_backend.ml index 8354f65a..53015f8a 100644 --- a/src/c_backend.ml +++ b/src/c_backend.ml @@ -590,7 +590,7 @@ let rec chunkify n xs = | xs, [] -> [xs] | xs, ys -> xs :: chunkify n ys -let rec compile_aval ctx = function +let rec compile_aval l ctx = function | AV_C_fragment (frag, typ) -> [], (frag, ctyp_of_typ ctx typ), [] @@ -638,7 +638,7 @@ let rec compile_aval ctx = function c_error ~loc:l ("Encountered unexpected literal " ^ string_of_lit lit) | AV_tuple avals -> - let elements = List.map (compile_aval ctx) avals in + let elements = List.map (compile_aval l ctx) avals in let cvals = List.map (fun (_, cval, _) -> cval) elements in let setup = List.concat (List.map (fun (setup, _, _) -> setup) elements) in let cleanup = List.concat (List.rev (List.map (fun (_, _, cleanup) -> cleanup) elements)) in @@ -646,7 +646,7 @@ let rec compile_aval ctx = function let gs = gensym () in setup @ [idecl tup_ctyp gs] - @ List.mapi (fun n cval -> icopy (CL_field (gs, "tup" ^ string_of_int n, cval_ctyp cval)) cval) cvals, + @ List.mapi (fun n cval -> icopy l (CL_field (gs, "tup" ^ string_of_int n, cval_ctyp cval)) cval) cvals, (F_id gs, CT_tup (List.map cval_ctyp cvals)), [iclear tup_ctyp gs] @ cleanup @@ -655,9 +655,9 @@ let rec compile_aval ctx = function let ctyp = ctyp_of_typ ctx typ in let gs = gensym () in let compile_fields (id, aval) = - let field_setup, cval, field_cleanup = compile_aval ctx aval in + let field_setup, cval, field_cleanup = compile_aval l ctx aval in field_setup - @ [icopy (CL_field (gs, string_of_id id, cval_ctyp cval)) cval] + @ [icopy l (CL_field (gs, string_of_id id, cval_ctyp cval)) cval] @ field_cleanup in [idecl ctyp gs] @@ -712,16 +712,16 @@ let rec compile_aval ctx = function let ctyp = CT_bits64 (len, direction) in let mask i = V_bits (Util.list_init (63 - i) (fun _ -> Sail2_values.B0) @ [Sail2_values.B1] @ Util.list_init i (fun _ -> Sail2_values.B0)) in let aval_mask i aval = - let setup, cval, cleanup = compile_aval ctx aval in + let setup, cval, cleanup = compile_aval l ctx aval in match cval with | (F_lit (V_bit Sail2_values.B0), _) -> [] | (F_lit (V_bit Sail2_values.B1), _) -> - [icopy (CL_id (gs, ctyp)) (F_op (F_id gs, "|", F_lit (mask i)), ctyp)] + [icopy l (CL_id (gs, ctyp)) (F_op (F_id gs, "|", F_lit (mask i)), ctyp)] | _ -> - setup @ [iif cval [icopy (CL_id (gs, ctyp)) (F_op (F_id gs, "|", F_lit (mask i)), ctyp)] [] CT_unit] @ cleanup + setup @ [iif cval [icopy l (CL_id (gs, ctyp)) (F_op (F_id gs, "|", F_lit (mask i)), ctyp)] [] CT_unit] @ cleanup in [idecl ctyp gs; - icopy (CL_id (gs, ctyp)) (F_lit (V_bits (Util.list_init 64 (fun _ -> Sail2_values.B0))), ctyp)] + icopy l (CL_id (gs, ctyp)) (F_lit (V_bits (Util.list_init 64 (fun _ -> Sail2_values.B0))), ctyp)] @ List.concat (List.mapi aval_mask (List.rev avals)), (F_id gs, ctyp), [] @@ -738,7 +738,7 @@ let rec compile_aval ctx = function let vector_ctyp = CT_vector (direction, ctyp_of_typ ctx typ) in let gs = gensym () in let aval_set i aval = - let setup, cval, cleanup = compile_aval ctx aval in + let setup, cval, cleanup = compile_aval l ctx aval in setup @ [iextern (CL_id (gs, vector_ctyp)) (mk_id "internal_vector_update") @@ -761,7 +761,7 @@ let rec compile_aval ctx = function in let gs = gensym () in let mk_cons aval = - let setup, cval, cleanup = compile_aval ctx aval in + let setup, cval, cleanup = compile_aval l 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)]] @ cleanup in [idecl (CT_list ctyp) gs] @@ -788,7 +788,7 @@ let compile_funcall l ctx id args typ = 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 + let arg_setup, cval, arg_cleanup = compile_aval l ctx aval in setup := List.rev arg_setup @ !setup; cleanup := arg_cleanup @ !cleanup; let have_ctyp = cval_ctyp cval in @@ -815,7 +815,7 @@ let compile_funcall l ctx id args typ = 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); + icopy l clexp (F_id gs, ret_ctyp); iclear ret_ctyp gs] end, !cleanup @@ -838,11 +838,11 @@ let rec compile_match ctx (AP_aux (apat_aux, env, l)) cval case_label = | AP_global (pid, typ), (frag, ctyp) -> let global_ctyp = ctyp_of_typ ctx typ in - [icopy (CL_id (pid, global_ctyp)) cval], [], ctx + [icopy l (CL_id (pid, global_ctyp)) cval], [], ctx | AP_id (pid, _), (frag, ctyp) when is_ct_enum ctyp -> begin match Env.lookup_id pid ctx.tc_env with - | Unbound -> [idecl ctyp pid; icopy (CL_id (pid, ctyp)) (frag, ctyp)], [], ctx + | Unbound -> [idecl ctyp pid; icopy l (CL_id (pid, ctyp)) (frag, ctyp)], [], ctx | _ -> [ijump (F_op (F_id pid, "!=", frag), CT_bool) case_label], [], ctx end @@ -851,7 +851,7 @@ let rec compile_match ctx (AP_aux (apat_aux, env, l)) cval case_label = let id_ctyp = ctyp_of_typ ctx typ in c_debug (lazy ("Adding local " ^ string_of_id pid ^ " : " ^ string_of_ctyp id_ctyp)); let ctx = { ctx with locals = Bindings.add pid (Immutable, id_ctyp) ctx.locals } in - [idecl id_ctyp pid; icopy (CL_id (pid, id_ctyp)) cval], [iclear id_ctyp pid], ctx + [idecl id_ctyp pid; icopy l (CL_id (pid, id_ctyp)) cval], [iclear id_ctyp pid], ctx | AP_tup apats, (frag, ctyp) -> begin @@ -922,11 +922,7 @@ let label str = let pointer_assign ctyp1 ctyp2 = match ctyp1 with - | CT_ref ctyp1 when ctyp_equal ctyp1 ctyp2 -> true - | CT_ref ctyp1 -> - c_error (Printf.sprintf "Incompatible type in pointer assignment between %s and %s" - (string_of_ctyp ctyp1) - (string_of_ctyp ctyp2)) + | CT_ref ctyp1 -> true | _ -> false let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = @@ -946,13 +942,13 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = compile_funcall l ctx id vs typ | AE_val aval -> - let setup, cval, cleanup = compile_aval ctx aval in - setup, (fun clexp -> icopy clexp cval), cleanup + let setup, cval, cleanup = compile_aval l ctx aval in + setup, (fun clexp -> icopy l clexp cval), cleanup (* Compile case statements *) | AE_case (aval, cases, typ) -> let ctyp = ctyp_of_typ ctx typ in - let aval_setup, cval, aval_cleanup = compile_aval ctx aval in + let aval_setup, cval, aval_cleanup = compile_aval l ctx aval in let case_return_id = gensym () in let finish_match_label = label "finish_match_" in let compile_case (apat, guard, body) = @@ -985,7 +981,7 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = @ List.concat (List.map compile_case cases) @ [imatch_failure ()] @ [ilabel finish_match_label], - (fun clexp -> icopy clexp (F_id case_return_id, ctyp)), + (fun clexp -> icopy l clexp (F_id case_return_id, ctyp)), [iclear ctyp case_return_id] @ aval_cleanup @ [icomment "end match"] @@ -1028,8 +1024,8 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = @ List.concat (List.map compile_case cases) @ [imatch_failure (); ilabel handled_exception_label; - icopy CL_have_exception (F_lit (V_bool false), CT_bool)], - (fun clexp -> icopy clexp (F_id try_return_id, ctyp)), + icopy l CL_have_exception (F_lit (V_bool false), CT_bool)], + (fun clexp -> icopy l clexp (F_id try_return_id, ctyp)), [] | AE_if (aval, then_aexp, else_aexp, if_typ) -> @@ -1038,7 +1034,7 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = 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 + let setup, cval, cleanup = compile_aval l ctx aval in setup, (fun clexp -> iif cval (compile_branch then_aexp clexp) @@ -1055,45 +1051,45 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = in let gs = gensym () in let compile_fields (id, aval) = - let field_setup, cval, field_cleanup = compile_aval ctx aval in + let field_setup, cval, field_cleanup = compile_aval l ctx aval in field_setup - @ [icopy (CL_field (gs, string_of_id id, Bindings.find id ctors)) cval] + @ [icopy l (CL_field (gs, string_of_id id, Bindings.find id ctors)) cval] @ field_cleanup in - let setup, cval, cleanup = compile_aval ctx aval in + let setup, cval, cleanup = compile_aval l ctx aval in [idecl ctyp gs] @ setup - @ [icopy (CL_id (gs, ctyp)) cval] + @ [icopy l (CL_id (gs, ctyp)) cval] @ cleanup @ List.concat (List.map compile_fields (Bindings.bindings fields)), - (fun clexp -> icopy clexp (F_id gs, ctyp)), + (fun clexp -> icopy l 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 left_setup, cval, left_cleanup = compile_aval l ctx aval in let right_setup, call, right_cleanup = compile_aexp ctx aexp in let gs = gensym () in left_setup @ [ idecl CT_bool gs; iif cval (right_setup @ [call (CL_id (gs, CT_bool))] @ right_cleanup) - [icopy (CL_id (gs, CT_bool)) (F_lit (V_bool false), CT_bool)] + [icopy l (CL_id (gs, CT_bool)) (F_lit (V_bool false), CT_bool)] CT_bool ] @ left_cleanup, - (fun clexp -> icopy clexp (F_id gs, CT_bool)), + (fun clexp -> icopy l 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 left_setup, cval, left_cleanup = compile_aval l ctx aval in let right_setup, call, right_cleanup = compile_aexp ctx aexp in let gs = gensym () in left_setup @ [ idecl CT_bool gs; iif cval - [icopy (CL_id (gs, CT_bool)) (F_lit (V_bool true), CT_bool)] + [icopy l (CL_id (gs, CT_bool)) (F_lit (V_bool true), CT_bool)] (right_setup @ [call (CL_id (gs, CT_bool))] @ right_cleanup) CT_bool ] @ left_cleanup, - (fun clexp -> icopy clexp (F_id gs, CT_bool)), + (fun clexp -> icopy l clexp (F_id gs, CT_bool)), [] (* This is a faster assignment rule for updating fields of a @@ -1102,19 +1098,19 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = when Id.compare id rid = 0 && !optimize_struct_updates -> c_debug (lazy ("Optimizing struct update")); let compile_fields (field_id, aval) = - let field_setup, cval, field_cleanup = compile_aval ctx aval in + let field_setup, cval, field_cleanup = compile_aval l ctx aval in field_setup - @ [icopy (CL_field (id, string_of_id field_id, cval_ctyp cval)) cval] + @ [icopy l (CL_field (id, string_of_id field_id, cval_ctyp cval)) cval] @ field_cleanup in List.concat (List.map compile_fields (Bindings.bindings fields)), - (fun clexp -> icopy clexp unit_fragment), + (fun clexp -> icopy l clexp unit_fragment), [] | AE_assign (id, assign_typ, aexp) -> let assign_ctyp = ctyp_of_typ ctx assign_typ in let setup, call, cleanup = compile_aexp ctx aexp in - setup @ [call (CL_id (id, assign_ctyp))], (fun clexp -> icopy clexp unit_fragment), cleanup + setup @ [call (CL_id (id, assign_ctyp))], (fun clexp -> icopy l clexp unit_fragment), cleanup | AE_block (aexps, aexp, _) -> let block = compile_block ctx aexps in @@ -1140,7 +1136,7 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = @ body_cleanup @ [igoto loop_start_label])] @ [ilabel loop_end_label], - (fun clexp -> icopy clexp unit_fragment), + (fun clexp -> icopy l clexp unit_fragment), [] | AE_loop (Until, cond, body) -> @@ -1162,7 +1158,7 @@ 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], - (fun clexp -> icopy clexp unit_fragment), + (fun clexp -> icopy l clexp unit_fragment), [] | AE_cast (aexp, typ) -> compile_aexp ctx aexp @@ -1173,14 +1169,14 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = | None -> c_error ~loc:l "No function return type found when compiling return statement" in (* Cleanup info will be re-added by fix_early_return *) - let return_setup, cval, _ = compile_aval ctx aval in + let return_setup, cval, _ = compile_aval l ctx aval in let creturn = if ctyp_equal fn_return_ctyp (cval_ctyp cval) then [ireturn cval] else let gs = gensym () in [idecl fn_return_ctyp gs; - icopy (CL_id (gs, fn_return_ctyp)) cval; + icopy l (CL_id (gs, fn_return_ctyp)) cval; ireturn (F_id gs, fn_return_ctyp)] in return_setup @ creturn, @@ -1189,16 +1185,16 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = | AE_throw (aval, typ) -> (* Cleanup info will be handled by fix_exceptions *) - let throw_setup, cval, _ = compile_aval ctx aval in + let throw_setup, cval, _ = compile_aval l ctx aval in throw_setup @ [ithrow cval], (fun clexp -> icomment "unreachable after throw"), [] | AE_field (aval, id, typ) -> let ctyp = ctyp_of_typ ctx typ in - let setup, cval, cleanup = compile_aval ctx aval in + let setup, cval, cleanup = compile_aval l ctx aval in setup, - (fun clexp -> icopy clexp (F_field (fst cval, Util.zencode_string (string_of_id id)), ctyp)), + (fun clexp -> icopy l clexp (F_field (fst cval, Util.zencode_string (string_of_id id)), ctyp)), cleanup | AE_for (loop_var, loop_from, loop_to, loop_step, Ord_aux (ord, _), body) -> @@ -1238,18 +1234,18 @@ let rec compile_aexp ctx (AE_aux (aexp_aux, env, l)) = @ 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); + icopy l (CL_id (loop_var, CT_int64)) (F_id from_gs, CT_int64); idecl CT_unit body_gs; iblock ([ilabel loop_start_label] @ [ijump (F_op (F_id loop_var, (if is_inc then ">" else "<"), F_id to_gs), CT_bool) loop_end_label] @ body_setup @ [body_call (CL_id (body_gs, CT_unit))] @ body_cleanup - @ [icopy (CL_id (loop_var, CT_int64)) + @ [icopy l (CL_id (loop_var, CT_int64)) (F_op (F_id loop_var, (if is_inc then "+" else "-"), F_id step_gs), CT_int64)] @ [igoto loop_start_label]); ilabel loop_end_label])], - (fun clexp -> icopy clexp unit_fragment), + (fun clexp -> icopy l clexp unit_fragment), [] (* @@ -1350,11 +1346,11 @@ let fix_early_return ret ctx instrs = before @ [iif cval (rewrite_return historic then_instrs) (rewrite_return historic else_instrs) ctyp] @ rewrite_return historic after - | before, I_aux (I_return cval, _) :: after -> + | before, I_aux (I_return cval, (_, l)) :: after -> let cleanup_label = label "cleanup_" in let end_cleanup_label = label "end_cleanup_" in before - @ [icopy ret cval; + @ [icopy l ret cval; igoto cleanup_label] (* This is probably dead code until cleanup_label, but how can we be sure there are no jumps into it? *) @ rewrite_return (historic @ before) after @@ -1421,10 +1417,10 @@ let fix_exception_block ?return:(return=None) ctx instrs = before @ [iif cval (rewrite_exception historic then_instrs) (rewrite_exception historic else_instrs) ctyp] @ rewrite_exception historic after - | before, I_aux (I_throw cval, _) :: after -> + | before, I_aux (I_throw cval, (_, l)) :: after -> before - @ [icopy (CL_current_exception (cval_ctyp cval)) cval; - icopy CL_have_exception (F_lit (V_bool true), CT_bool)] + @ [icopy l (CL_current_exception (cval_ctyp cval)) cval; + icopy l CL_have_exception (F_lit (V_bool true), CT_bool)] @ generate_cleanup (historic @ before) @ [igoto end_block_label] @ rewrite_exception (historic @ before) after @@ -1809,7 +1805,7 @@ let rec specialize_variants ctx = | ctyps -> CT_tup ctyps in function - | I_aux (I_funcall (clexp, extern, id, cvals), aux) as instr when Id.compare id ctor_id = 0 -> + | I_aux (I_funcall (clexp, extern, id, cvals), ((_, l) as aux)) as instr when Id.compare id ctor_id = 0 -> assert (List.length ctyps = List.length cvals); (* Work out how each call to a constructor in instantiated and add that to unifications *) @@ -1826,7 +1822,7 @@ let rec specialize_variants ctx = else let gs = gensym () in [idecl suprema gs; - icopy (CL_id (gs, suprema)) (unpoly frag, ctyp)], + icopy l (CL_id (gs, suprema)) (unpoly frag, ctyp)], (F_id gs, suprema), [iclear suprema gs] in @@ -2090,10 +2086,18 @@ let rec codegen_instr fid ctx (I_aux (instr, (_, l))) = | CT_ref lctyp -> lctyp | _ -> assert false in - if is_stack_ctyp lctyp then - string (Printf.sprintf " *(%s) = %s;" (sgen_clexp_pure clexp) (sgen_cval cval)) + if ctyp_equal lctyp rctyp then + if is_stack_ctyp lctyp then + string (Printf.sprintf " *(%s) = %s;" (sgen_clexp_pure clexp) (sgen_cval cval)) + else + string (Printf.sprintf " COPY(%s)(*(%s), %s);" (sgen_ctyp_name lctyp) (sgen_clexp clexp) (sgen_cval cval)) else - string (Printf.sprintf " COPY(%s)(*(%s), %s);" (sgen_ctyp_name lctyp) (sgen_clexp clexp) (sgen_cval cval)) + 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_param cval)) + else + string (Printf.sprintf " CONVERT_OF(%s, %s)(*(%s), %s);" + (sgen_ctyp_name lctyp) (sgen_ctyp_name rctyp) (sgen_clexp clexp) (sgen_cval_param cval)) else if is_stack_ctyp lctyp then string (Printf.sprintf " %s = CONVERT_OF(%s, %s)(%s);" |
