From 6eef135e8dd834ee1eddfc8a18f5936afda6f12d Mon Sep 17 00:00:00 2001 From: Allan Blanchard <allan.blanchard@cea.fr> Date: Tue, 15 Oct 2019 15:17:47 +0200 Subject: [PATCH] [Builtin] Simplifies function body generation --- src/plugins/builtin/Makefile.in | 2 +- src/plugins/builtin/basic_blocks.ml | 10 ++----- src/plugins/builtin/basic_blocks.mli | 3 +- src/plugins/builtin/memcmp.ml | 24 ++++++---------- src/plugins/builtin/memcpy.ml | 24 ++++++---------- src/plugins/builtin/memmove.ml | 24 ++++++---------- src/plugins/builtin/transform.ml | 43 +++++++++++++++++++++------- src/plugins/builtin/transform.mli | 3 +- 8 files changed, 63 insertions(+), 70 deletions(-) diff --git a/src/plugins/builtin/Makefile.in b/src/plugins/builtin/Makefile.in index a7203c74139..702ddb08ba8 100644 --- a/src/plugins/builtin/Makefile.in +++ b/src/plugins/builtin/Makefile.in @@ -37,7 +37,7 @@ PLUGIN_DIR ?= . PLUGIN_ENABLE := @ENABLE_BUILTIN@ PLUGIN_NAME := Builtin PLUGIN_CMI := -PLUGIN_CMO := options transform basic_blocks memcpy memcmp memmove register +PLUGIN_CMO := basic_blocks options transform memcpy memcmp memmove register PLUGIN_DISTRIBUTED := $(PLUGIN_ENABLE) PLUGIN_DISTRIB_EXTERNAL:= Makefile.in configure.ac configure #PLUGIN_NO_DEFAULT_TEST := no diff --git a/src/plugins/builtin/basic_blocks.ml b/src/plugins/builtin/basic_blocks.ml index 65ae46edd4e..d962ae3b70e 100644 --- a/src/plugins/builtin/basic_blocks.ml +++ b/src/plugins/builtin/basic_blocks.ml @@ -33,20 +33,14 @@ let size_t () = let prepare_definition name fun_type = let vi = Cil.makeGlobalVar ~referenced:true name fun_type in + vi.vdefined <- true ; let fd = Cil.emptyFunctionFromVI vi in Cil.setFormalsDecl vi fun_type ; fd.sformals <- Cil.getFormalsDecl vi ; fd -let set_function_body fd body = - fd.sbody <- body ; - fd.svar.vdefined <- true ; - File.must_recompute_cfg fd - -let call_function lval name args = - let open Globals.Functions in +let call_function lval vi args = let loc = Cil_datatype.Location.unknown in - let vi = get_vi (find_by_name name) in let _, typs, _, _ = Cil.splitFunctionTypeVI vi in let typs = Cil.argsToList typs in let gen_arg exp (_, typ, _) = diff --git a/src/plugins/builtin/basic_blocks.mli b/src/plugins/builtin/basic_blocks.mli index 642e8c1b69f..13a746b4571 100644 --- a/src/plugins/builtin/basic_blocks.mli +++ b/src/plugins/builtin/basic_blocks.mli @@ -28,8 +28,7 @@ val const_of: typ -> typ val size_t: unit -> typ val prepare_definition: string -> typ -> fundec -val set_function_body: fundec -> block -> unit -val call_function: lval option -> string -> exp list -> instr +val call_function: lval option -> varinfo -> exp list -> instr val string_of_typ: typ -> string diff --git a/src/plugins/builtin/memcmp.ml b/src/plugins/builtin/memcmp.ml index 17ac40ba510..a5b8bea2647 100644 --- a/src/plugins/builtin/memcmp.ml +++ b/src/plugins/builtin/memcmp.ml @@ -79,22 +79,13 @@ let generate_function_type t = ] in TFun(Cil.intType, Some params, false, []) -let generate_body fd = - let loc = Cil_datatype.Location.unknown in - let rv = Cil.makeLocalVar fd "__retres" Cil.intType in - let args = List.map Cil.evar fd.sformals in - let call = Instr(call_function (Some (Var rv, NoOffset)) function_name args) in - let ret = Return (Some (Cil.evar rv), loc) in - let block = Cil.mkBlock (List.map Cil.mkStmt [ call ; ret]) in - block.blocals <- [ rv ] ; - block - -let generate_function t = +let generate_prototype t = + let fun_type = generate_function_type t in let name = function_name ^ "_" ^ (string_of_typ t) in - let fun_t = generate_function_type t in - let fd = prepare_definition name fun_t in - set_function_body fd (generate_body fd) ; - fd + name, fun_type + +let args_for_original _t fd = + List.map Cil.evar fd.sformals let type_from_arg x = let x = Cil.stripCasts x in @@ -131,6 +122,7 @@ let () = Transform.register (module struct let well_typed_call = well_typed_call let key_from_call = key_from_call let retype_args = retype_args - let generate_function = generate_function + let generate_prototype = generate_prototype let generate_spec = generate_spec + let args_for_original = args_for_original end) \ No newline at end of file diff --git a/src/plugins/builtin/memcpy.ml b/src/plugins/builtin/memcpy.ml index 7140704da34..717c7009ae1 100644 --- a/src/plugins/builtin/memcpy.ml +++ b/src/plugins/builtin/memcpy.ml @@ -83,22 +83,13 @@ let generate_function_type t = ] in TFun(dt, Some params, false, []) -let generate_body t fd = - let loc = Cil_datatype.Location.unknown in - let rv = Cil.makeLocalVar fd "__retres" (TPtr(t, [])) in - let args = List.map Cil.evar fd.sformals in - let call = Instr(call_function (Some (Var rv, NoOffset)) function_name args) in - let ret = Return (Some (Cil.evar rv), loc) in - let block = Cil.mkBlock (List.map Cil.mkStmt [ call ; ret]) in - block.blocals <- [ rv ] ; - block - -let generate_function t = +let generate_prototype t = + let fun_type = generate_function_type t in let name = function_name ^ "_" ^ (string_of_typ t) in - let fun_t = generate_function_type t in - let fd = prepare_definition name fun_t in - set_function_body fd (generate_body t fd) ; - fd + name, fun_type + +let args_for_original _t fd = + List.map Cil.evar fd.sformals let type_from_arg x = let x = Cil.stripCasts x in @@ -135,6 +126,7 @@ let () = Transform.register (module struct let well_typed_call = well_typed_call let key_from_call = key_from_call let retype_args = retype_args - let generate_function = generate_function + let generate_prototype = generate_prototype let generate_spec = generate_spec + let args_for_original = args_for_original end) \ No newline at end of file diff --git a/src/plugins/builtin/memmove.ml b/src/plugins/builtin/memmove.ml index ec50e9b6253..e5b7b6f7ff2 100644 --- a/src/plugins/builtin/memmove.ml +++ b/src/plugins/builtin/memmove.ml @@ -78,22 +78,13 @@ let generate_function_type t = ] in TFun(dt, Some params, false, []) -let generate_body t fd = - let loc = Cil_datatype.Location.unknown in - let rv = Cil.makeLocalVar fd "__retres" (TPtr(t, [])) in - let args = List.map Cil.evar fd.sformals in - let call = Instr(call_function (Some (Var rv, NoOffset)) function_name args) in - let ret = Return (Some (Cil.evar rv), loc) in - let block = Cil.mkBlock (List.map Cil.mkStmt [ call ; ret]) in - block.blocals <- [ rv ] ; - block - -let generate_function t = +let generate_prototype t = + let fun_type = generate_function_type t in let name = function_name ^ "_" ^ (string_of_typ t) in - let fun_t = generate_function_type t in - let fd = prepare_definition name fun_t in - set_function_body fd (generate_body t fd) ; - fd + name, fun_type + +let args_for_original _t fd = + List.map Cil.evar fd.sformals let type_from_arg x = let x = Cil.stripCasts x in @@ -130,6 +121,7 @@ let () = Transform.register (module struct let well_typed_call = well_typed_call let key_from_call = key_from_call let retype_args = retype_args - let generate_function = generate_function + let generate_prototype = generate_prototype let generate_spec = generate_spec + let args_for_original = args_for_original end) \ No newline at end of file diff --git a/src/plugins/builtin/transform.ml b/src/plugins/builtin/transform.ml index 0e1db9267c7..a14e9360266 100644 --- a/src/plugins/builtin/transform.ml +++ b/src/plugins/builtin/transform.ml @@ -21,6 +21,7 @@ (**************************************************************************) open Cil_types +open Basic_blocks module type Builtin = sig module Hashtbl: Datatype.Hashtbl @@ -30,8 +31,9 @@ module type Builtin = sig val well_typed_call: exp list -> bool val key_from_call: exp list -> override_key val retype_args: override_key -> exp list -> exp list - val generate_function: override_key -> fundec + val generate_prototype: override_key -> (string * typ) val generate_spec: override_key -> fundec -> location -> funspec + val args_for_original: override_key -> fundec -> exp list end module type Internal_builtin = sig @@ -52,13 +54,34 @@ module Make_internal_builtin (B: Builtin) = struct let name = "Builtins." ^ B.function_name end) + let create_and_add key = + let (name, typ) = B.generate_prototype key in + let fd = Basic_blocks.prepare_definition name typ in + let loc = Cil_datatype.Location.unknown in + let open Globals.Functions in + let open Extlib in + let ret_var = match Cil.getReturnType fd.svar.vtype with + | t when Cil.isVoidType t -> None + | t -> Some (Cil.makeLocalVar fd "__retres" t) + in + let call = + let orig = get_vi (find_by_name function_name) in + let args = B.args_for_original key fd in + Instr(call_function (opt_map Cil.var ret_var) orig args) + in + let ret = Return ( (opt_map Cil.evar ret_var), loc) in + fd.sbody <- + { (Cil.mkBlock (List.map Cil.mkStmt [ call ; ret ])) + with blocals = list_of_opt ret_var } ; + File.must_recompute_cfg fd ; + Cache.add key fd + let get_override key = try Cache.find key with Not_found -> - let fct = B.generate_function key in - Cache.add key fct ; - fct + create_and_add key ; + Cache.find key let get_globals location = let finalize key fd = @@ -135,12 +158,12 @@ class visitor = object(_) method! vinst = function | Call(_) | Local_init(_, ConsInit(_, _, Plain_func), _) -> let change = function - | [ Call(r, ({ enode = Lval((Var fct), NoOffset) } as e), args, loc) ] -> - let fct, args = replace_call (fct, args) in - [ Call(r, { e with enode = Lval((Var fct), NoOffset) }, args, loc) ] - | [ Local_init(r, ConsInit(fct, args, Plain_func), loc) ] -> - let fct, args = replace_call (fct, args) in - [ Local_init(r, ConsInit(fct, args, Plain_func), loc) ] + | [ Call(r, ({ enode = Lval((Var f), NoOffset) } as e), args, loc) ] -> + let f, args = replace_call (f, args) in + [ Call(r, { e with enode = Lval((Var f), NoOffset) }, args, loc) ] + | [ Local_init(r, ConsInit(f, args, Plain_func), loc) ] -> + let f, args = replace_call (f, args) in + [ Local_init(r, ConsInit(f, args, Plain_func), loc) ] | _ -> assert false in Cil.DoChildrenPost change diff --git a/src/plugins/builtin/transform.mli b/src/plugins/builtin/transform.mli index 9d081643eeb..e5876ab7a52 100644 --- a/src/plugins/builtin/transform.mli +++ b/src/plugins/builtin/transform.mli @@ -30,8 +30,9 @@ module type Builtin = sig val well_typed_call: exp list -> bool val key_from_call: exp list -> override_key val retype_args: override_key -> exp list -> exp list - val generate_function: override_key -> fundec + val generate_prototype: override_key -> (string * typ) val generate_spec: override_key -> fundec -> location -> funspec + val args_for_original: override_key -> fundec -> exp list end val register: (module Builtin) -> unit -- GitLab