open Datastructures (* dataflow analysis graph signature ---------------------------------------- *) (* Interface for dataflow graphs structured in a way to facilitate the general iterative dataflow analysis algorithm. The AsGraph functor in cfg.ml provides an implementation of this DFA_GRAPH signature that converts an LL IR control-flow graph to this representation. NOTE: The direction of the analysis is goverened by how preds and succs are instantiated and how the corresponding flow function is defined. This module pretends that all information is flowing "forward", but e.g. liveness instantiates the graph so that "forward" here is "backward" in the control-flow graph. This means that for a node n, the output information is *explicitly* represented by the "Graph.out" function: out[n] = Graph.out g n The input information for [n] is *implicitly* represented by: in[n] = combine preds[n] (out[n]) *) module type DFA_GRAPH = sig module NodeS : SetS (* type of nodes in this graph *) type node = NodeS.elt (* dataflow facts associated with the out-edges of the nodes in the graph *) type fact (* the abstract type of dataflow graphs *) type t val preds : t -> node -> NodeS.t val succs : t -> node -> NodeS.t val nodes : t -> NodeS.t (* the flow function: given a graph node and input fact, compute the resulting fact on the output edge of the node *) val flow : t -> node -> fact -> fact (* lookup / modify the dataflow annotations associated with a node *) val out : t -> node -> fact val add_fact : node -> fact -> t -> t end (* abstract dataflow lattice signature -------------------------------------- *) (* The general algorithm works over a generic lattice of abstract "facts". - facts can be combined (this is the 'meet' operation) - facts can be compared: for `compare x y` the result indicates: < 0 : x is less than y = 0 : x equals y > 0 : x is greater than y *) module type FACT = sig type t val combine : t list -> t val compare : t -> t -> int val to_string : t -> string end (* generic iterative dataflow solver ---------------------------------------- *) (* This functor takes two modules: Fact - the implementation of the lattice Graph - the dataflow anlaysis graph It produces a module that has a single function 'solve', which implements the iterative dataflow analysis described in lecture. - using a worklist (or workset) nodes [initialized with the set of all nodes] - process the worklist until empty: . choose a node from the worklist . find the node's predecessors and combine their flow facts . apply the flow function to the combined input to find the new output . if the output has changed, update the graph and add the node's successors to the worklist TASK: complete the [solve] function, which implements the above algorithm. *) module Make (Fact : FACT) (Graph : DFA_GRAPH with type fact := Fact.t) = struct let solve (g:Graph.t) : Graph.t = failwith "TODO HW6: Solver.solve unimplemented" end