[infer][java] Isolate the call to the JBir transformation to a single place

Summary: Having only place where the code runs the transformation of the Java bytecode into the JBir reporesentation allows to more easily start manipulating the JBir representation and the bytecode together and progressively move the translation based on bytecode instead of JBir.

Reviewed By: sblackshear

Differential Revision: D4137576

fbshipit-source-id: c483528
master
Jeremy Dubreil 8 years ago committed by Facebook Github Bot
parent 1b07f78e32
commit 3b997e4882

@ -77,11 +77,9 @@ let add_edges
(** Add a concrete method. *)
let add_cmethod source_file program linereader icfg cm proc_name =
let cn, _ = JBasics.cms_split cm.Javalib.cm_class_method_signature in
let jmethod = (Javalib.ConcreteMethod cm) in
match JTrans.create_procdesc source_file program linereader icfg jmethod with
match JTrans.create_cm_procdesc source_file program linereader icfg cm proc_name with
| None -> ()
| Some _ when JTrans.is_java_native cm -> ()
| Some procdesc ->
| Some (procdesc, impl) ->
let start_node = Cfg.Procdesc.get_start_node procdesc in
let exit_node = Cfg.Procdesc.get_exit_node procdesc in
let exn_node =
@ -89,7 +87,6 @@ let add_cmethod source_file program linereader icfg cm proc_name =
| Some node -> node
| None ->
failwithf "No exn node found for %s" (Procname.to_string proc_name) in
let impl = JTrans.get_implementation cm in
let instrs = JBir.code impl in
let context =
JContext.create_context icfg procdesc impl cn source_file program in
@ -98,15 +95,6 @@ let add_cmethod source_file program linereader icfg cm proc_name =
Cg.add_defined_node icfg.JContext.cg proc_name
(** Add an abstract method. *)
let add_amethod source_file program linereader icfg am proc_name =
let jmethod = (Javalib.AbstractMethod am) in
match JTrans.create_procdesc source_file program linereader icfg jmethod with
| None -> ()
| Some _ ->
Cg.add_defined_node icfg.JContext.cg proc_name
let path_of_cached_classname cn =
let root_path = Filename.concat Config.results_dir "classnames" in
let package_path = IList.fold_left Filename.concat root_path (JBasics.cn_package cn) in
@ -151,15 +139,22 @@ let create_icfg source_file linereader program icfg cn node =
(* do not translate the method if there is a model for it *)
L.out_debug "Skipping method with a model: %s@." (Procname.to_string proc_name)
else
begin
try
(* each procedure has different scope: start names from id 0 *)
Ident.NameGenerator.reset ();
match m with
| Javalib.AbstractMethod am ->
ignore (JTrans.create_am_procdesc program icfg am proc_name);
(* TODO #4040807: investigate why we need to mark asbtract methods as defined *)
Cg.add_defined_node icfg.JContext.cg proc_name
| Javalib.ConcreteMethod cm when JTrans.is_java_native cm ->
ignore (JTrans.create_native_procdesc program icfg cm proc_name)
| Javalib.ConcreteMethod cm ->
add_cmethod source_file program linereader icfg cm proc_name
| Javalib.AbstractMethod am ->
add_amethod source_file program linereader icfg am proc_name
end in
with JBasics.Class_structure_error _ ->
L.do_err
"create_icfg raised JBasics.Class_structure_error on %a@."
Procname.pp proc_name in
Javalib.m_iter translate node

@ -230,106 +230,115 @@ let update_init_loc cn ms loc_start =
try ignore(JBasics.ClassMap.find cn !init_loc_map)
with Not_found -> init_loc_map := (JBasics.ClassMap.add cn loc_start !init_loc_map)
let trans_access = function
| `Default -> PredSymb.Default
| `Public -> PredSymb.Public
| `Private -> PredSymb.Private
| `Protected -> PredSymb.Protected
let create_am_procdesc program icfg am proc_name : Cfg.Procdesc.t =
let cfg = icfg.JContext.cfg in
let tenv = icfg.JContext.tenv in
let m = Javalib.AbstractMethod am in
let cn, ms = JBasics.cms_split (Javalib.get_class_method_signature m) in
let formals =
formals_from_signature program tenv cn ms (JTransType.get_method_kind m) in
let method_annotation =
JAnnotation.translate_method proc_name am.Javalib.am_annotations in
let procdesc =
let proc_attributes =
{ (ProcAttributes.default proc_name Config.Java) with
ProcAttributes.access = trans_access am.Javalib.am_access;
exceptions = IList.map JBasics.cn_name am.Javalib.am_exceptions;
formals;
is_abstract = true;
is_bridge_method = am.Javalib.am_bridge;
is_defined = true;
is_synthetic_method = am.Javalib.am_synthetic;
method_annotation;
ret_type = JTransType.return_type program tenv ms;
} in
Cfg.create_proc_desc cfg proc_attributes in
let start_kind = Cfg.Node.Start_node proc_name in
let start_node = Cfg.Procdesc.create_node procdesc Location.dummy start_kind [] in
let exit_kind = (Cfg.Node.Exit_node proc_name) in
let exit_node = Cfg.Procdesc.create_node procdesc Location.dummy exit_kind [] in
Cfg.Procdesc.node_set_succs_exn procdesc start_node [exit_node] [exit_node];
Cfg.Procdesc.set_start_node procdesc start_node;
Cfg.Procdesc.set_exit_node procdesc exit_node;
procdesc
let create_native_procdesc program icfg cm proc_name =
let cfg = icfg.JContext.cfg in
let tenv = icfg.JContext.tenv in
let m = Javalib.ConcreteMethod cm in
let cn, ms = JBasics.cms_split (Javalib.get_class_method_signature m) in
let formals =
formals_from_signature program tenv cn ms (JTransType.get_method_kind m) in
let method_annotation =
JAnnotation.translate_method proc_name cm.Javalib.cm_annotations in
let proc_attributes =
{ (ProcAttributes.default proc_name Config.Java) with
ProcAttributes.access = trans_access cm.Javalib.cm_access;
exceptions = IList.map JBasics.cn_name cm.Javalib.cm_exceptions;
formals;
is_bridge_method = cm.Javalib.cm_bridge;
is_synthetic_method = cm.Javalib.cm_synthetic;
method_annotation;
ret_type = JTransType.return_type program tenv ms;
} in
Cfg.create_proc_desc cfg proc_attributes
(** Creates a procedure description. *)
let create_procdesc source_file program linereader icfg m : Cfg.Procdesc.t option =
let create_cm_procdesc source_file program linereader icfg cm proc_name =
let cfg = icfg.JContext.cfg in
let tenv = icfg.JContext.tenv in
let m = Javalib.ConcreteMethod cm in
let cn, ms = JBasics.cms_split (Javalib.get_class_method_signature m) in
let proc_name = JTransType.translate_method_name m in
let trans_access = function
| `Default -> PredSymb.Default
| `Public -> PredSymb.Public
| `Private -> PredSymb.Private
| `Protected -> PredSymb.Protected in
try
let impl = get_implementation cm in
let procdesc =
match m with
| Javalib.AbstractMethod am -> (* create a procdesc with empty body *)
let formals =
formals_from_signature program tenv cn ms (JTransType.get_method_kind m) in
let method_annotation =
JAnnotation.translate_method proc_name am.Javalib.am_annotations in
let procdesc =
let proc_attributes =
{ (ProcAttributes.default proc_name Config.Java) with
ProcAttributes.access = trans_access am.Javalib.am_access;
exceptions = IList.map JBasics.cn_name am.Javalib.am_exceptions;
formals;
is_abstract = true;
is_bridge_method = am.Javalib.am_bridge;
is_defined = true;
is_synthetic_method = am.Javalib.am_synthetic;
method_annotation;
ret_type = JTransType.return_type program tenv ms;
} in
Cfg.create_proc_desc cfg proc_attributes in
let start_kind = Cfg.Node.Start_node proc_name in
let start_node = Cfg.Procdesc.create_node procdesc Location.dummy start_kind [] in
let exit_kind = (Cfg.Node.Exit_node proc_name) in
let exit_node = Cfg.Procdesc.create_node procdesc Location.dummy exit_kind [] in
Cfg.Procdesc.node_set_succs_exn procdesc start_node [exit_node] [exit_node];
Cfg.Procdesc.set_start_node procdesc start_node;
Cfg.Procdesc.set_exit_node procdesc exit_node;
procdesc
| Javalib.ConcreteMethod cm when is_java_native cm ->
let formals =
formals_from_signature program tenv cn ms (JTransType.get_method_kind m) in
let method_annotation =
JAnnotation.translate_method proc_name cm.Javalib.cm_annotations in
let proc_attributes =
{ (ProcAttributes.default proc_name Config.Java) with
ProcAttributes.access = trans_access cm.Javalib.cm_access;
exceptions = IList.map JBasics.cn_name cm.Javalib.cm_exceptions;
formals;
is_bridge_method = cm.Javalib.cm_bridge;
is_synthetic_method = cm.Javalib.cm_synthetic;
method_annotation;
ret_type = JTransType.return_type program tenv ms;
} in
Cfg.create_proc_desc cfg proc_attributes;
| Javalib.ConcreteMethod cm ->
let impl = get_implementation cm in
let locals, formals = locals_formals program tenv cn impl in
let loc_start =
let loc = get_location source_file impl 0 in
fix_method_definition_line linereader proc_name loc in
let loc_exit =
get_location source_file impl (Array.length (JBir.code impl) - 1) in
let method_annotation =
JAnnotation.translate_method proc_name cm.Javalib.cm_annotations in
update_constr_loc cn ms loc_start;
update_init_loc cn ms loc_exit;
let proc_attributes =
{ (ProcAttributes.default proc_name Config.Java) with
ProcAttributes.access = trans_access cm.Javalib.cm_access;
exceptions = IList.map JBasics.cn_name cm.Javalib.cm_exceptions;
formals;
is_bridge_method = cm.Javalib.cm_bridge;
is_defined = true;
is_synthetic_method = cm.Javalib.cm_synthetic;
is_java_synchronized_method = cm.Javalib.cm_synchronized;
loc = loc_start;
locals;
method_annotation;
ret_type = JTransType.return_type program tenv ms;
} in
let procdesc =
Cfg.create_proc_desc cfg proc_attributes in
let start_kind = Cfg.Node.Start_node proc_name in
let start_node = Cfg.Procdesc.create_node procdesc loc_start start_kind [] in
let exit_kind = (Cfg.Node.Exit_node proc_name) in
let exit_node = Cfg.Procdesc.create_node procdesc loc_exit exit_kind [] in
let exn_kind = Cfg.Node.exn_sink_kind in
let exn_node = Cfg.Procdesc.create_node procdesc loc_exit exn_kind [] in
JContext.add_exn_node proc_name exn_node;
Cfg.Procdesc.set_start_node procdesc start_node;
Cfg.Procdesc.set_exit_node procdesc exit_node;
Cfg.Node.add_locals_ret_declaration start_node proc_attributes locals;
procdesc in
Some procdesc
with JBir.Subroutine | JBasics.Class_structure_error _ ->
let locals, formals = locals_formals program tenv cn impl in
let loc_start =
let loc = get_location source_file impl 0 in
fix_method_definition_line linereader proc_name loc in
let loc_exit =
get_location source_file impl (Array.length (JBir.code impl) - 1) in
let method_annotation =
JAnnotation.translate_method proc_name cm.Javalib.cm_annotations in
update_constr_loc cn ms loc_start;
update_init_loc cn ms loc_exit;
let proc_attributes =
{ (ProcAttributes.default proc_name Config.Java) with
ProcAttributes.access = trans_access cm.Javalib.cm_access;
exceptions = IList.map JBasics.cn_name cm.Javalib.cm_exceptions;
formals;
is_bridge_method = cm.Javalib.cm_bridge;
is_defined = true;
is_synthetic_method = cm.Javalib.cm_synthetic;
is_java_synchronized_method = cm.Javalib.cm_synchronized;
loc = loc_start;
locals;
method_annotation;
ret_type = JTransType.return_type program tenv ms;
} in
let procdesc =
Cfg.create_proc_desc cfg proc_attributes in
let start_kind = Cfg.Node.Start_node proc_name in
let start_node = Cfg.Procdesc.create_node procdesc loc_start start_kind [] in
let exit_kind = (Cfg.Node.Exit_node proc_name) in
let exit_node = Cfg.Procdesc.create_node procdesc loc_exit exit_kind [] in
let exn_kind = Cfg.Node.exn_sink_kind in
let exn_node = Cfg.Procdesc.create_node procdesc loc_exit exn_kind [] in
JContext.add_exn_node proc_name exn_node;
Cfg.Procdesc.set_start_node procdesc start_node;
Cfg.Procdesc.set_exit_node procdesc exit_node;
Cfg.Node.add_locals_ret_declaration start_node proc_attributes locals;
procdesc in
Some (procdesc, impl)
with JBir.Subroutine ->
L.do_err
"create_procdesc raised JBir.Subroutine or JBasics.Class_structure_error on %a@."
"create_procdesc raised JBir.Subroutine on %a@."
Procname.pp proc_name;
None

@ -22,18 +22,28 @@ type translation =
val is_java_native : JCode.jcode Javalib.concrete_method -> bool
(** [create_procdesc linereader cfg tenv program m] creates a procedure description
for the method m and adds it to cfg *)
val create_procdesc :
(** Create the procedure description for an abstract method *)
val create_am_procdesc :
JClasspath.program -> JContext.icfg -> Javalib.abstract_method -> Procname.t -> Cfg.Procdesc.t
(** Create the procedure description for a concrete method *)
val create_native_procdesc :
JClasspath.program ->
JContext.icfg ->
JCode.jcode Javalib.concrete_method ->
Procname.t ->
Cfg.Procdesc.t
(** [create_procdesc source_file program linereader icfg cm proc_name] creates
a procedure description for the concrete method cm and adds it to cfg *)
val create_cm_procdesc :
DB.source_file ->
JClasspath.program ->
Printer.LineReader.t ->
JContext.icfg ->
JCode.jcode Javalib.jmethod ->
Cfg.Procdesc.t option
(** returns the implementation of a given method *)
val get_implementation : JCode.jcode Javalib.concrete_method -> JBir.t
JCode.jcode Javalib.concrete_method ->
Procname.t ->
(Cfg.Procdesc.t * JBir.t) option
(** translates an instruction into a statement node or prune nodes in the cfg *)
val instruction : JContext.t -> int -> JBir.instr -> translation

Loading…
Cancel
Save