You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

121 lines
4.1 KiB

(*
* Copyright (c) 2009-2013, Monoidics ltd.
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
open! IStd
(** Execution environments: basically a cache of where procedures are and what is their CFG and type
environment *)
module L = Logging
(** per-file data: type environment and cfg *)
type file_data =
{ source: SourceFile.t
; mutable tenv: Tenv.t option
; mutable integer_type_widths: Typ.IntegerWidths.t option }
(** create a new file_data *)
let new_file_data source =
(* Do not fill in tenv and cfg as they can be quite large. This makes calls to fork() cheaper
until we start filling out these fields. *)
{source; tenv= None (* Sil.load_tenv_from_file tenv_file *); integer_type_widths= None}
let create_file_data table source =
match SourceFile.Hash.find table source with
| file_data ->
file_data
| exception Caml.Not_found ->
let file_data = new_file_data source in
SourceFile.Hash.add table source file_data ;
file_data
type t =
{ proc_map: file_data Typ.Procname.Hash.t (** map from procedure name to file data *)
; file_map: file_data SourceFile.Hash.t (** map from source files to file data *) }
let get_file_data exe_env pname =
try Some (Typ.Procname.Hash.find exe_env.proc_map pname) with Caml.Not_found ->
let source_file_opt =
match Attributes.load pname with
| None ->
L.(debug Analysis Medium) "can't find tenv_cfg_object for %a@." Typ.Procname.pp pname ;
None
| Some proc_attributes when Config.reactive_capture ->
let get_captured_file {ProcAttributes.translation_unit} = translation_unit in
OndemandCapture.try_capture proc_attributes |> Option.map ~f:get_captured_file
| Some proc_attributes ->
Some proc_attributes.ProcAttributes.translation_unit
in
let get_file_data_for_source source_file =
let file_data = create_file_data exe_env.file_map source_file in
Typ.Procname.Hash.replace exe_env.proc_map pname file_data ;
file_data
in
Option.map ~f:get_file_data_for_source source_file_opt
let file_data_to_tenv file_data =
if is_none file_data.tenv then file_data.tenv <- Tenv.load file_data.source ;
file_data.tenv
let file_data_to_integer_type_widths file_data =
if is_none file_data.integer_type_widths then
file_data.integer_type_widths
<- Option.first_some (Typ.IntegerWidths.load file_data.source) (Some Typ.IntegerWidths.java) ;
file_data.integer_type_widths
let java_global_tenv =
lazy
( match Tenv.load_global () with
| None ->
L.(die InternalError) "Could not load the global tenv"
| Some tenv ->
tenv )
let get_column_value ~value_on_java ~file_data_to_value ~column_name exe_env proc_name =
match proc_name with
| Typ.Procname.Java _ ->
Lazy.force value_on_java
| _ -> (
match get_file_data exe_env proc_name with
| Some file_data -> (
match file_data_to_value file_data with
| Some v ->
v
| None ->
let loc = State.get_loc_exn () in
L.(die InternalError)
"get_column_value: %s not found for %a in file '%a' at %a" column_name Typ.Procname.pp
proc_name SourceFile.pp loc.Location.file Location.pp loc )
| None ->
let loc = State.get_loc_exn () in
L.(die InternalError)
"get_column_value: file_data not found for %a in file '%a' at %a" Typ.Procname.pp
proc_name SourceFile.pp loc.Location.file Location.pp loc )
(** return the type environment associated to the procedure *)
let get_tenv =
get_column_value ~value_on_java:java_global_tenv ~file_data_to_value:file_data_to_tenv
~column_name:"tenv"
(** return the integer type widths associated to the procedure *)
let get_integer_type_widths =
get_column_value
~value_on_java:(lazy Typ.IntegerWidths.java)
~file_data_to_value:file_data_to_integer_type_widths ~column_name:"integer type widths"
let mk () = {proc_map= Typ.Procname.Hash.create 17; file_map= SourceFile.Hash.create 1}