Skip to content
Snippets Groups Projects
Commit 59646439 authored by xleroy's avatar xleroy
Browse files

Support __builtin_memcpy; use it for struct assignment

git-svn-id: https://yquem.inria.fr/compcert/svn/compcert/trunk@1319 fca1b0fc-160b-0410-b1d3-a4f43f01ea2e
parent 9e9853b7
No related branches found
No related tags found
No related merge requests found
......@@ -232,6 +232,35 @@ let print_builtin_function oc s =
fprintf oc " stfs %a, [%a, #0]\n" freg FR0 ireg IR0; 2
| "__builtin_volatile_write_float64" ->
fprintf oc " stfd %a, [%a, #0]\n" freg FR0 ireg IR0; 1
(* Block copy *)
| "__builtin_memcpy" ->
let lbl1 = new_label() in
let lbl2 = new_label() in
fprintf oc " cmp %a, #0\n" ireg IR2;
fprintf oc " beq %a\n" label lbl1;
fprintf oc "%a: ldrb %a, [%a], #1\n" label lbl2 ireg IR3 ireg IR1;
fprintf oc " subs %a, %a, #1\n" ireg IR2 ireg IR2;
fprintf oc " strb %a, [%a], #1\n" ireg IR3 ireg IR0;
fprintf oc " bne %a\n" label lbl2;
fprintf oc "%a:\n" label lbl1
(*
let lbl = new_label() in
fprintf oc " cmp %a, #0\n" ireg IR2;
fprintf oc "%a: ldrbne %a, [%a], #1\n" label lbl ireg IR3 ireg IR1;
fprintf oc " strbne %a, [%a], #1\n" ireg IR3 ireg IR0;
fprintf oc " subnes %a, %a, #1\n" ireg IR2 ireg IR2;
fprintf oc " bne %a\n" label lbl
*)
| "__builtin_memcpy_word" ->
let lbl1 = new_label() in
let lbl2 = new_label() in
fprintf oc " movs %a, %a, lsr #2\n" ireg IR2 ireg IR2;
fprintf oc " beq %a\n" label lbl1;
fprintf oc "%a: ldr %a, [%a], #4\n" label lbl2 ireg IR3 ireg IR1;
fprintf oc " subs %a, %a, #1\n" ireg IR2 ireg IR2;
fprintf oc " str %a, [%a], #4\n" ireg IR3 ireg IR0;
fprintf oc " bne %a\n" label lbl2;
fprintf oc "%a:\n" label lbl1
(* Catch-all *)
| s ->
invalid_arg ("unrecognized builtin function " ^ s)
......
......@@ -841,6 +841,19 @@ let builtins_generic = {
(TVoid [], [TPtr(TVoid [], []); TFloat(FDouble, [])], false);
"__builtin_volatile_write_pointer",
(TVoid [], [TPtr(TVoid [], []); TPtr(TVoid [], [])], false)
(* Block copy *)
"__builtin_memcpy",
(TPtr(TVoid [], []),
[TPtr(TVoid [], []);
TPtr(TVoid [AConst], []);
TInt(Cutil.size_t_ikind, [])],
false);
"__builtin_memcpy_words",
(TPtr(TVoid [], []),
[TPtr(TVoid [], []);
TPtr(TVoid [AConst], []);
TInt(Cutil.size_t_ikind, [])],
false)
]
}
......
......@@ -124,7 +124,7 @@ let builtins = {
"__builtin_inf", (doubleType, [], false);
"__builtin_inff", (floatType, [], false);
"__builtin_infl", (longDoubleType, [], false);
"__builtin_memcpy", (voidPtrType, [ voidPtrType; voidConstPtrType; uintType ], false);
"__builtin_memcpy", (voidPtrType, [ voidPtrType; voidConstPtrType; sizeType ], false);
"__builtin_mempcpy", (voidPtrType, [ voidPtrType; voidConstPtrType; sizeType ], false);
"__builtin_fmod", (doubleType, [ doubleType ], false);
......
......@@ -19,13 +19,14 @@
Preserves: simplified code, unblocked code *)
open C
open Machine
open Cutil
open Env
open Errors
let maxsize = ref 8
let need_memcpy = ref (None: ident option)
let memcpy_decl = ref (None : ident option)
let memcpy_type =
TFun(TPtr(TVoid [], []),
......@@ -34,14 +35,18 @@ let memcpy_type =
(Env.fresh_ident "", TInt(size_t_ikind, []))],
false, [])
let memcpy_ident () =
match !need_memcpy with
| None ->
let id = Env.fresh_ident "memcpy" in
need_memcpy := Some id;
id
| Some id ->
id
let memcpy_ident env =
try fst (Env.lookup_ident env "__builtin_memcpy")
with Env.Error _ ->
try fst (Env.lookup_ident env "memcpy")
with Env.Error _ ->
match !memcpy_decl with
| Some id -> id
| None -> let id = Env.fresh_ident "memcpy" in memcpy_decl := Some id; id
let memcpy_words_ident env =
try fst (Env.lookup_ident env "__builtin_memcpy_words")
with Env.Error _ -> memcpy_ident env
let transf_assign env loc lhs rhs =
......@@ -89,7 +94,15 @@ let transf_assign env loc lhs rhs =
try
transf lhs rhs
with Exit ->
let memcpy = {edesc = EVar(memcpy_ident()); etyp = memcpy_type} in
let by_words =
match Cutil.sizeof env lhs.etyp with
| Some n -> n mod !config.sizeof_ptr = 0
| None -> false in
let ident =
if by_words
then memcpy_word_ident()
else memcpy_ident() in
let memcpy = {edesc = EVar(ident); etyp = memcpy_type} in
let e_lhs = {edesc = EUnop(Oaddrof, lhs); etyp = TPtr(lhs.etyp, [])} in
let e_rhs = {edesc = EUnop(Oaddrof, rhs); etyp = TPtr(rhs.etyp, [])} in
let e_size = {edesc = ESizeof(lhs.etyp); etyp = TInt(size_t_ikind, [])} in
......@@ -131,27 +144,10 @@ let transf_fundef env fd =
{fd with fd_body = transf_stmt env fd.fd_body}
let program p =
need_memcpy := None;
memcpy_decl := None;
let p' = Transform.program ~fundef:transf_fundef p in
match !need_memcpy with
match !memcpy_decl with
| None -> p'
| Some id ->
{gdesc = Gdecl(Storage_extern, id, memcpy_type, None); gloc = no_loc}
:: p'
(* Horrible hack *)
(***
let has_memcpy = ref false in
need_memcpy := None;
List.iter
(function {gdesc = Gdecl(_, ({name = "memcpy"} as id), _, _)} ->
need_memcpy := Some id; has_memcpy := true
| _ -> ())
p;
let p' = Transform.program ~fundef:transf_fundef p in
match !need_memcpy with
| Some id when not !has_memcpy ->
{gdesc = Gdecl(Storage_extern, id, memcpy_type, None); gloc = no_loc}
:: p'
| _ -> p'
***)
......@@ -271,6 +271,31 @@ let print_builtin_function oc s =
fprintf oc " stfs %a, 0(%a)\n" freg FPR1 ireg GPR3
| "__builtin_volatile_write_float64" ->
fprintf oc " stfd %a, 0(%a)\n" freg FPR1 ireg GPR3
(* Block copy *)
| "__builtin_memcpy" ->
let lbl1 = new_label() in
let lbl2 = new_label() in
fprintf oc " cmplwi %a, %a, 0\n" creg CR0 ireg GPR5;
fprintf oc " beq %a, %a\n" creg CR0 label lbl1;
fprintf oc " mtctr %a\n" ireg GPR5;
fprintf oc " addi %a, %a, -1\n" ireg GPR6 ireg GPR3;
fprintf oc " addi %a, %a, -1\n" ireg GPR4 ireg GPR4;
fprintf oc "%a: lbzu %a, 1(%a)\n" label lbl2 ireg GPR0 ireg GPR4;
fprintf oc " stbu %a, 1(%a)\n" ireg GPR0 ireg GPR6;
fprintf oc " bdnz %a\n" label lbl2;
fprintf oc "%a:\n" label lbl1
| "__builtin_memcpy_word" ->
let lbl1 = new_label() in
let lbl2 = new_label() in
fprintf oc " rlwinm. %a, %a, 30, 2, 31\n" ireg GPR5 ireg GPR5;
fprintf oc " beq %a, %a\n" creg CR0 label lbl1;
fprintf oc " mtctr %a\n" ireg GPR5;
fprintf oc " addi %a, %a, -4\n" ireg GPR6 ireg GPR3;
fprintf oc " addi %a, %a, -4\n" ireg GPR4 ireg GPR4;
fprintf oc "%a: lwzu %a, 4(%a)\n" label lbl2 ireg GPR0 ireg GPR4;
fprintf oc " stwu %a, 4(%a)\n" ireg GPR0 ireg GPR6;
fprintf oc " bdnz %a\n" label lbl2;
fprintf oc "%a:\n" label lbl1
(* Integer arithmetic *)
| "__builtin_mulhw" ->
fprintf oc " mulhw %a, %a, %a\n" ireg GPR3 ireg GPR3 ireg GPR4
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment