From 59646439baa1b9cc6209b684e4ccf9aac908fdbc Mon Sep 17 00:00:00 2001 From: xleroy Date: Sat, 17 Apr 2010 07:01:18 +0000 Subject: 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 --- arm/PrintAsm.ml | 29 ++++++++++++++++++++++++++ cfrontend/C2Clight.ml | 13 ++++++++++++ cparser/GCC.ml | 2 +- cparser/StructAssign.ml | 54 +++++++++++++++++++++++-------------------------- powerpc/PrintAsm.ml | 25 +++++++++++++++++++++++ 5 files changed, 93 insertions(+), 30 deletions(-) diff --git a/arm/PrintAsm.ml b/arm/PrintAsm.ml index 77bacc3c..bb99bb5c 100644 --- a/arm/PrintAsm.ml +++ b/arm/PrintAsm.ml @@ -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) diff --git a/cfrontend/C2Clight.ml b/cfrontend/C2Clight.ml index 100c72b1..614ad770 100644 --- a/cfrontend/C2Clight.ml +++ b/cfrontend/C2Clight.ml @@ -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) ] } diff --git a/cparser/GCC.ml b/cparser/GCC.ml index 9f864dcd..17b718b4 100644 --- a/cparser/GCC.ml +++ b/cparser/GCC.ml @@ -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); diff --git a/cparser/StructAssign.ml b/cparser/StructAssign.ml index f5cecfc5..3be917e8 100644 --- a/cparser/StructAssign.ml +++ b/cparser/StructAssign.ml @@ -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' -***) diff --git a/powerpc/PrintAsm.ml b/powerpc/PrintAsm.ml index f528335a..4c898790 100644 --- a/powerpc/PrintAsm.ml +++ b/powerpc/PrintAsm.ml @@ -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 -- cgit