38 lines
1.6 KiB
OCaml
38 lines
1.6 KiB
OCaml
|
|
open Ll
|
||
|
|
open Datastructures
|
||
|
|
|
||
|
|
|
||
|
|
|
||
|
|
(* Because the cfg instance of the dataflow graph uses _basic blocks_ as nodes,
|
||
|
|
we need a way to recover the dataflow facts at individual instructions
|
||
|
|
within the block. Depending on the direction of the analysis, this amounts to
|
||
|
|
propagating information either forward or backwards through the block.
|
||
|
|
|
||
|
|
The following helper functions construct maps from each instruction or terminator
|
||
|
|
to the corresponding dataflow fact. *)
|
||
|
|
|
||
|
|
(* Compute IN for each instruction in a block, given IN of the first instruction *)
|
||
|
|
let block_flow_forwards_map (fi:uid * insn -> 'd -> 'd)
|
||
|
|
(ft:terminator -> 'd -> 'd)
|
||
|
|
({insns; term}:block) (d_in:'d) : uid -> 'd =
|
||
|
|
let t_id, t = term in
|
||
|
|
let m, d_tmn = List.fold_left (fun (m, d) (u,i) ->
|
||
|
|
let d' = fi (u,i) d in
|
||
|
|
UidM.add u d m, d')
|
||
|
|
(UidM.empty, d_in) insns in
|
||
|
|
let m' = UidM.add t_id d_tmn m in
|
||
|
|
fun u -> UidM.find u m'
|
||
|
|
|
||
|
|
(* Compute OUT for each instruction in a block, given OUT of the terminator*)
|
||
|
|
let block_flow_backwards_map (fi:uid * insn -> 'd -> 'd)
|
||
|
|
(ft:terminator -> 'd -> 'd)
|
||
|
|
({insns; term}:block) (d_out:'d) : uid -> 'd =
|
||
|
|
let t_id, t = term in
|
||
|
|
let d_ins = ft t d_out in
|
||
|
|
let m, _ = List.fold_right (fun (u,i) (m, d) ->
|
||
|
|
let d' = fi (u,i) d in
|
||
|
|
UidM.add u d m, d')
|
||
|
|
insns (UidM.empty, d_ins) in
|
||
|
|
let m' = UidM.add t_id d_out m in
|
||
|
|
fun u -> UidM.find u m'
|