(* * Copyright (c) 2016-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 (** Control-flow graph for a single procedure (as opposed to cfg.ml, which represents a cfg for a file). Defines useful wrappers that allows us to do tricks like turn a forward cfg to into a backward one, or view a cfg as having a single instruction per block *) module type Node = sig type t type id val kind : t -> Procdesc.Node.nodekind val id : t -> id val hash : t -> int val loc : t -> Location.t val underlying_node : t -> Procdesc.Node.t val of_underlying_node : Procdesc.Node.t -> t val compare_id : id -> id -> int val pp_id : Format.formatter -> id -> unit module IdMap : PrettyPrintable.PPMap with type key = id module IdSet : PrettyPrintable.PPSet with type elt = id end module type S = sig type t type instrs_dir module Node : Node val instrs : Node.t -> instrs_dir Instrs.t (** get the instructions from a node *) val fold_succs : t -> (Node.t, Node.t, 'accum) Container.fold (** fold over all successors (normal and exceptional) *) val fold_preds : t -> (Node.t, Node.t, 'accum) Container.fold (** fold over all predecessors (normal and exceptional) *) val fold_normal_succs : t -> (Node.t, Node.t, 'accum) Container.fold (** fold over non-exceptional successors *) val fold_normal_preds : t -> (Node.t, Node.t, 'accum) Container.fold (** fold over non-exceptional predecessors *) val fold_exceptional_succs : t -> (Node.t, Node.t, 'accum) Container.fold (** fold over exceptional successors *) val fold_exceptional_preds : t -> (Node.t, Node.t, 'accum) Container.fold (** fold over exceptional predescessors *) val start_node : t -> Node.t val exit_node : t -> Node.t val proc_desc : t -> Procdesc.t val fold_nodes : (t, Node.t, 'accum) Container.fold val from_pdesc : Procdesc.t -> t val is_loop_head : Procdesc.t -> Node.t -> bool val wto : t -> Node.t WeakTopologicalOrder.Partition.t end module DefaultNode : Node with type t = Procdesc.Node.t and type id = Procdesc.Node.id module InstrNode : sig type instr_index include Node with type t = Procdesc.Node.t * instr_index and type id = Procdesc.Node.id * instr_index end (** Forward CFG with no exceptional control-flow *) module Normal : S with type t = Procdesc.t and module Node = DefaultNode and type instrs_dir = Instrs.not_reversed (** Forward CFG with exceptional control-flow *) module Exceptional : S with type t = Procdesc.t * DefaultNode.t list Procdesc.IdMap.t and module Node = DefaultNode and type instrs_dir = Instrs.not_reversed (** Wrapper that reverses the direction of the CFG *) module Backward (Base : S with type instrs_dir = Instrs.not_reversed) : S with type t = Base.t and module Node = Base.Node and type instrs_dir = Instrs.reversed module OneInstrPerNode (Base : S with module Node = DefaultNode) : sig include S with type t = Base.t and module Node = InstrNode and type instrs_dir = Instrs.not_reversed val last_of_underlying_node : Procdesc.Node.t -> Node.t end module NormalOneInstrPerNode : module type of OneInstrPerNode (Normal) module MakeOcamlGraph (Base : S) : sig type t = Base.t module V : sig type t = Base.Node.t val equal : t -> t -> bool val compare : t -> t -> int val hash : t -> int end val pred : t -> Base.Node.t -> Base.Node.t list val succ : t -> Base.Node.t -> Base.Node.t list val fold_vertex : (Base.Node.t -> 'a -> 'a) -> t -> 'a -> 'a val iter_vertex : (Base.Node.t -> unit) -> t -> unit val iter_succ : (Base.Node.t -> unit) -> t -> Base.Node.t -> unit val nb_vertex : t -> int end