[frontend] Refactoring for the following diff

Summary:
This diff does refactoring for the following diff.

* Define Mangled.return_param and Mangled.is_return_param and use it instead of
  Ident.name_return_param.
* Share common code from objc_setter and objc_getter
* Move struct_copy to CStructUtils.ml

Reviewed By: da319

Differential Revision: D27940125

fbshipit-source-id: 84eb3109b
master
Sungkeun Cho 4 years ago committed by Facebook GitHub Bot
parent 4e02e58709
commit f43d7aa5fb

@ -156,9 +156,6 @@ end
(** Name used for the return variable *) (** Name used for the return variable *)
let name_return = Mangled.from_string "return" let name_return = Mangled.from_string "return"
(** Name used for the return param variable *)
let name_return_param = Mangled.from_string "__return_param"
(** Return the standard name for the given kind *) (** Return the standard name for the given kind *)
let standard_name kind = let standard_name kind =
if equal_kind kind KNormal || equal_kind kind KNone then Name.Normal if equal_kind kind KNormal || equal_kind kind KNone then Name.Normal

@ -69,9 +69,6 @@ val name_spec : name
val name_return : Mangled.t val name_return : Mangled.t
(** Name used for the return variable *) (** Name used for the return variable *)
val name_return_param : Mangled.t
(** Name used for the return param variable *)
val string_to_name : string -> name val string_to_name : string -> name
(** Convert a string to a name. *) (** Convert a string to a name. *)

@ -42,6 +42,10 @@ let self = from_string "self"
let is_self = function {plain= "self"} -> true | _ -> false let is_self = function {plain= "self"} -> true | _ -> false
let return_param = from_string "__return_param"
let is_return_param = function {plain= "__return_param"} -> true | _ -> false
module Set = PrettyPrintable.MakePPSet (struct module Set = PrettyPrintable.MakePPSet (struct
type nonrec t = t [@@deriving compare] type nonrec t = t [@@deriving compare]

@ -39,6 +39,10 @@ val self : t [@@warning "-32"]
val is_self : t -> bool val is_self : t -> bool
val return_param : t
val is_return_param : t -> bool
(** Set of Mangled. *) (** Set of Mangled. *)
module Set : PrettyPrintable.PPSet with type elt = t module Set : PrettyPrintable.PPSet with type elt = t

@ -236,7 +236,7 @@ let mk (name : Mangled.t) (proc_name : Procname.t) : t =
let get_ret_pvar pname = mk Ident.name_return pname let get_ret_pvar pname = mk Ident.name_return pname
let get_ret_param_pvar pname = mk Ident.name_return_param pname let get_ret_param_pvar pname = mk Mangled.return_param pname
(** [mk_callee name proc_name] creates a program var for a callee function with the given function (** [mk_callee name proc_name] creates a program var for a callee function with the given function
name *) name *)

@ -7,39 +7,47 @@
open! IStd open! IStd
let objc_getter proc_desc location (self_var, self_typ) (fieldname, field_typ, _) = let get_load_self_instr location (self, self_typ) fieldname =
let id_pvar = Ident.create_fresh Ident.knormal in let id_self = Ident.create_fresh Ident.knormal in
let load_pvar_instr = let load_self_instr =
Sil.Load {id= id_pvar; e= Lvar self_var; root_typ= self_typ; typ= self_typ; loc= location} Sil.Load {id= id_self; e= Lvar self; root_typ= self_typ; typ= self_typ; loc= location}
in in
let id_field = Ident.create_fresh Ident.knormal in
let class_typ = match self_typ.Typ.desc with Typ.Tptr (t, _) -> t | _ -> self_typ in let class_typ = match self_typ.Typ.desc with Typ.Tptr (t, _) -> t | _ -> self_typ in
let e = Exp.Lfield (Var id_pvar, fieldname, class_typ) in let field_exp = Exp.Lfield (Var id_self, fieldname, class_typ) in
(field_exp, load_self_instr)
let objc_getter proc_desc location self_with_typ (fieldname, field_typ, _) =
let field_exp, load_self_instr = get_load_self_instr location self_with_typ fieldname in
let store_instrs =
let id_field = Ident.create_fresh Ident.knormal in
let load_field_instr = let load_field_instr =
Sil.Load {id= id_field; e; root_typ= field_typ; typ= field_typ; loc= location} Sil.Load {id= id_field; e= field_exp; root_typ= field_typ; typ= field_typ; loc= location}
in in
let exp_var = Exp.Lvar (Procdesc.get_ret_var proc_desc) in let exp_var = Exp.Lvar (Procdesc.get_ret_var proc_desc) in
let return_exp = let return_exp =
Sil.Store {e1= exp_var; root_typ= field_typ; typ= field_typ; e2= Exp.Var id_field; loc= location} Sil.Store
{e1= exp_var; root_typ= field_typ; typ= field_typ; e2= Exp.Var id_field; loc= location}
in
[load_field_instr; return_exp]
in in
[load_pvar_instr; load_field_instr; return_exp] load_self_instr :: store_instrs
let objc_setter location (self, self_typ) (var, var_typ) (fieldname, field_typ, _) = let objc_setter location self_with_typ (var, var_typ) (fieldname, field_typ, _) =
let id_self = Ident.create_fresh Ident.knormal in let field_exp, load_self_instr = get_load_self_instr location self_with_typ fieldname in
let load_self_instr = let store_instrs =
Sil.Load {id= id_self; e= Lvar self; root_typ= self_typ; typ= self_typ; loc= location} let id_field = Ident.create_fresh Ident.knormal in
in
let id_var = Ident.create_fresh Ident.knormal in
let load_var_instr = let load_var_instr =
Sil.Load {id= id_var; e= Lvar var; root_typ= var_typ; typ= var_typ; loc= location} Sil.Load {id= id_field; e= Lvar var; root_typ= var_typ; typ= var_typ; loc= location}
in in
let class_typ = match self_typ.Typ.desc with Typ.Tptr (t, _) -> t | _ -> self_typ in
let field_exp = Exp.Lfield (Var id_self, fieldname, class_typ) in
let store_exp = let store_exp =
Sil.Store {e1= field_exp; root_typ= field_typ; typ= field_typ; e2= Exp.Var id_var; loc= location} Sil.Store
{e1= field_exp; root_typ= field_typ; typ= field_typ; e2= Exp.Var id_field; loc= location}
in
[load_var_instr; store_exp]
in in
[load_self_instr; load_var_instr; store_exp] load_self_instr :: store_instrs
let process_getter_setter proc_name proc_desc = let process_getter_setter proc_name proc_desc =

@ -0,0 +1,26 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
let struct_copy tenv loc e1 e2 ~typ ~struct_name =
let rec struct_copy_helper e1 e2 typ struct_name rev_acc =
let {Struct.fields} = Option.value_exn (Tenv.lookup tenv struct_name) in
List.fold fields ~init:rev_acc ~f:(fun rev_acc (field_name, field_typ, _) ->
let mk_field e = Exp.Lfield (e, field_name, typ) in
let e1 = mk_field e1 in
let e2 = mk_field e2 in
match field_typ.Typ.desc with
| Tstruct (CStruct _ as struct_name) ->
struct_copy_helper e1 e2 field_typ struct_name rev_acc
| _ ->
let id = Ident.create_fresh Ident.knormal in
Sil.Store {e1; root_typ= field_typ; typ= field_typ; e2= Exp.Var id; loc}
:: Sil.Load {id; e= e2; root_typ= field_typ; typ= field_typ; loc}
:: rev_acc )
in
if Exp.equal e1 e2 then [] else struct_copy_helper e1 e2 typ struct_name [] |> List.rev

@ -0,0 +1,11 @@
(*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
val struct_copy :
Tenv.t -> Location.t -> Exp.t -> Exp.t -> typ:Typ.t -> struct_name:Typ.name -> Sil.instr list

@ -986,25 +986,6 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
mk_trans_result (array_exp, typ) control mk_trans_result (array_exp, typ) control
and struct_copy tenv loc e1 e2 typ struct_name =
let rec struct_copy_helper e1 e2 typ struct_name rev_acc =
let {Struct.fields} = Option.value_exn (Tenv.lookup tenv struct_name) in
List.fold fields ~init:rev_acc ~f:(fun rev_acc (field_name, field_typ, _) ->
let mk_field e = Exp.Lfield (e, field_name, typ) in
let e1 = mk_field e1 in
let e2 = mk_field e2 in
match field_typ.Typ.desc with
| Tstruct (CStruct _ as struct_name) ->
struct_copy_helper e1 e2 field_typ struct_name rev_acc
| _ ->
let id = Ident.create_fresh Ident.knormal in
Sil.Store {e1; root_typ= field_typ; typ= field_typ; e2= Exp.Var id; loc}
:: Sil.Load {id; e= e2; root_typ= field_typ; typ= field_typ; loc}
:: rev_acc )
in
if Exp.equal e1 e2 then [] else struct_copy_helper e1 e2 typ struct_name [] |> List.rev
and binaryOperator_trans trans_state binary_operator_info stmt_info expr_info stmt_list = and binaryOperator_trans trans_state binary_operator_info stmt_info expr_info stmt_list =
L.debug Capture Verbose " BinaryOperator '%a' " L.debug Capture Verbose " BinaryOperator '%a' "
(Pp.of_string ~f:Clang_ast_j.string_of_binary_operator_kind) (Pp.of_string ~f:Clang_ast_j.string_of_binary_operator_kind)
@ -1029,8 +1010,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
(instruction trans_state' s1, instruction trans_state' s2) (instruction trans_state' s1, instruction trans_state' s2)
in in
let instrs = let instrs =
struct_copy context.CContext.tenv sil_loc (fst res_trans_e1.return) CStructUtils.struct_copy context.CContext.tenv sil_loc (fst res_trans_e1.return)
(fst res_trans_e2.return) res_typ struct_name (fst res_trans_e2.return) ~typ:res_typ ~struct_name
in in
[res_trans_e1.control; res_trans_e2.control; {empty_control with instrs}] [res_trans_e1.control; res_trans_e2.control; {empty_control with instrs}]
|> PriorityNode.compute_controls_to_parent trans_state_pri sil_loc node_name stmt_info |> PriorityNode.compute_controls_to_parent trans_state_pri sil_loc node_name stmt_info
@ -2643,7 +2624,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
let instrs = let instrs =
match cstruct_name_opt with match cstruct_name_opt with
| Some struct_name -> | Some struct_name ->
struct_copy context.CContext.tenv sil_loc var_exp sil_e1' var_typ struct_name CStructUtils.struct_copy context.CContext.tenv sil_loc var_exp sil_e1' ~typ:var_typ
~struct_name
| None -> | None ->
[Sil.Store {e1= var_exp; root_typ= ie_typ; typ= ie_typ; e2= sil_e1'; loc= sil_loc}] [Sil.Store {e1= var_exp; root_typ= ie_typ; typ= ie_typ; e2= sil_e1'; loc= sil_loc}]
in in
@ -3033,8 +3015,8 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
, Some {desc= Tptr ({desc= Tstruct (CStruct _ as struct_name)}, _)} ) -> , Some {desc= Tptr ({desc= Tstruct (CStruct _ as struct_name)}, _)} ) ->
(* return (exp:struct); *) (* return (exp:struct); *)
return_stmt stmt ~mk_ret_instrs:(fun ret_exp _root_typ ret_typ res_trans_stmt -> return_stmt stmt ~mk_ret_instrs:(fun ret_exp _root_typ ret_typ res_trans_stmt ->
struct_copy context.CContext.tenv sil_loc ret_exp (fst res_trans_stmt.return) ret_typ CStructUtils.struct_copy context.CContext.tenv sil_loc ret_exp
struct_name ) (fst res_trans_stmt.return) ~typ:ret_typ ~struct_name )
| [stmt], _ -> | [stmt], _ ->
(* return exp; *) (* return exp; *)
return_stmt stmt ~mk_ret_instrs:(fun ret_exp root_typ ret_typ res_trans_stmt -> return_stmt stmt ~mk_ret_instrs:(fun ret_exp root_typ ret_typ res_trans_stmt ->

@ -44,8 +44,7 @@ let mk_objc_method_nil_summary_aux tenv proc_desc astate =
let* astate, self_value = PulseOperations.eval_deref location (Lvar self) astate in let* astate, self_value = PulseOperations.eval_deref location (Lvar self) astate in
let* astate = PulseArithmetic.prune_eq_zero (fst self_value) astate in let* astate = PulseArithmetic.prune_eq_zero (fst self_value) astate in
match List.last (Procdesc.get_formals proc_desc) with match List.last (Procdesc.get_formals proc_desc) with
| Some (last_formal, {desc= Tptr (typ, _)}) when Mangled.equal last_formal Ident.name_return_param | Some (last_formal, {desc= Tptr (typ, _)}) when Mangled.is_return_param last_formal ->
->
let ret_param_var = Procdesc.get_ret_param_var proc_desc in let ret_param_var = Procdesc.get_ret_param_var proc_desc in
let* astate, ret_param_var_addr_hist = let* astate, ret_param_var_addr_hist =
PulseOperations.eval_deref location (Lvar ret_param_var) astate PulseOperations.eval_deref location (Lvar ret_param_var) astate

Loading…
Cancel
Save