open Ir
open Ir_utils
open Analysis
module type DOMAIN = sig
type domain
val string_of_domain: domain -> string
end
module type DOMAIN_AND_BLOCK_ANALYSIS = sig
include DOMAIN
val analyse_block: ControlFlowGraph.t -> domain Knowledge.table -> label -> domain BlockKnowledge.t
end
(*
module TableVisualizer = struct
let stringize_table (to_string: 'a -> string) result =
let new_result = Hashtbl.create 513 in
let f k v =
let kw = Knowledge.make (to_string @@ Knowledge.pre v) (to_string @@ Knowledge.post v) in
Hashtbl.replace new_result k kw
in
Hashtbl.iter f result;
new_result
let stringize_full_table (to_string: 'a -> string) result =
let visualize_kw v = Knowledge.make (to_string @@ Knowledge.pre v) (to_string @@ Knowledge.post v) in
let visualize_instr (kw, instr) = (visualize_kw kw, instr) in
let visualize_body = List.map visualize_instr in
let visualize_terminator (kw, terminator) = (visualize_kw kw, terminator) in
let new_result = Hashtbl.create 513 in
let f k v =
let pre = to_string @@ BlockKnowledge.pre v in
let post = to_string @@ BlockKnowledge.post v in
let body = visualize_body @@ BlockKnowledge.body v in
let terminator = visualize_terminator @@ BlockKnowledge.terminator v in
Hashtbl.replace new_result k @@ BlockKnowledge.make ~pre ~post ~body ~terminator
in
Hashtbl.iter f result;
new_result
end
*)
module NgMakeGraphvizVisualizer(D:DOMAIN) = struct
let visualise_instr (pre, post, instr) =
let instr = string_of_instr instr in
String.concat "\n"
[
Format.sprintf "
%s | %s | %s |
" pre instr post
]
let visualise_terminator (pre, post, t) =
let t = string_of_terminator t in
String.concat "\n"
[
Format.sprintf "%s | %s | %s |
" pre t post
]
let block_template_pre pre name =
[ Format.sprintf ""
; Format.sprintf "%s |
" name
; Format.sprintf "%s |
" @@ pre
]
let block_template_post post =
[ Format.sprintf "%s |
" post
; Format.sprintf "
"
]
let block_template name pre post body =
String.concat "" @@ List.flatten
[ block_template_pre pre name
; body
; block_template_post post
]
let stringize_body body =
let f (kw, instr) =
let pre = D.string_of_domain @@ Knowledge.pre kw in
let post = D.string_of_domain @@ Knowledge.post kw in
(pre, post, instr)
in
List.map f body
let artificial_body body =
let f instr =
("", "", instr)
in
List.map f body
let stringize_terminator (kw, terminator) =
let pre = D.string_of_domain @@ Knowledge.pre kw in
let post = D.string_of_domain @@ Knowledge.post kw in
(pre, post, terminator)
let artificial_terminator terminator =
("", "", terminator)
let prepare_block bb_kw body terminator =
if BlockKnowledge.is_complex bb_kw then
let sbody = stringize_body @@ BlockKnowledge.body bb_kw in
let sterm = stringize_terminator @@ BlockKnowledge.terminator bb_kw in
sbody, sterm
else
let sbody = artificial_body body in
let sterm = artificial_terminator terminator in
sbody, sterm
let compute_block_label cfg table v =
let v_str = string_of_label v in
let kw = Hashtbl.find table v in
let pre = D.string_of_domain @@ BlockKnowledge.pre kw in
let post = D.string_of_domain @@ BlockKnowledge.post kw in
if v = ControlFlowGraph.entry_label cfg then
block_template (Format.sprintf "ENTRY %s" v_str) pre post []
else if v = ControlFlowGraph.exit_label cfg then
block_template (Format.sprintf "EXIT %s" v_str) pre post []
else
let body = ControlFlowGraph.block cfg v in
let terminator = ControlFlowGraph.terminator cfg v in
let sbody, sterm = prepare_block kw body terminator in
let body = List.flatten
[ List.map visualise_instr sbody
; [visualise_terminator sterm]
] in
block_template (Format.sprintf "BLOCK %s" v_str) pre post body
let describe_vertex cfg table v =
Format.sprintf "N%s[shape=none, margin=0, label=<%s>];"
(string_of_label v)
(compute_block_label cfg table v)
let describe_outedges cfg v =
let describe_edge w =
Format.sprintf "N%s:x -> N%s:e;" (string_of_label v) (string_of_label w)
in
String.concat "\n" @@ List.map describe_edge @@ ControlFlowGraph.successors cfg v
let visualize cfg table =
let labels = ControlFlowGraph.labels cfg in
let vertices = String.concat "\n" @@ List.map (describe_vertex cfg table) labels in
let edges = String.concat "\n" @@ List.map (describe_outedges cfg) labels in
String.concat "\n"
[ "digraph CFG {"
; "node [shape=none; fontname=\"Courier\" fontsize=\"9\"];"
; "ordering=out;"
; vertices
; edges
; "}"
]
end
module MakeGraphvizVisualizer(D:DOMAIN_AND_BLOCK_ANALYSIS) = struct
let visualise_instr (kw, instr) =
let pre = D.string_of_domain @@ Knowledge.pre kw in
let post = D.string_of_domain @@ Knowledge.post kw in
let instr = string_of_instr instr in
String.concat "\n"
[
Format.sprintf "%s | %s | %s |
" pre instr post
]
let visualise_terminator (kw, t) =
let pre = D.string_of_domain @@ Knowledge.pre kw in
let post = D.string_of_domain @@ Knowledge.post kw in
let t = string_of_terminator t in
String.concat "\n"
[
Format.sprintf "%s | %s | %s |
" pre t post
]
let block_template_pre pre name =
[ Format.sprintf ""
; Format.sprintf "%s |
" name
; Format.sprintf "%s |
" @@ pre
]
let block_template_post post =
[ Format.sprintf "%s |
" post
; Format.sprintf "
"
]
let block_template name pre post body =
String.concat "" @@ List.flatten
[ block_template_pre pre name
; body
; block_template_post post
]
let compute_block_label cfg table v =
let v_str = string_of_label v in
let kw = Hashtbl.find table v in
let pre = D.string_of_domain @@ Knowledge.pre kw in
let post = D.string_of_domain @@ Knowledge.post kw in
if v = ControlFlowGraph.entry_label cfg then
block_template (Format.sprintf "ENTRY %s" v_str) pre post []
else if v = ControlFlowGraph.exit_label cfg then
block_template (Format.sprintf "EXIT %s" v_str) pre post []
else
let bb_kw = D.analyse_block cfg table v in
let body = List.flatten
[ List.map visualise_instr (BlockKnowledge.body bb_kw)
; [visualise_terminator (BlockKnowledge.terminator bb_kw)]
] in
block_template (Format.sprintf "BLOCK %s" v_str) pre post body
let describe_vertex cfg table v =
Format.sprintf "N%s[shape=none, margin=0, label=<%s>];"
(string_of_label v)
(compute_block_label cfg table v)
let describe_outedges cfg v =
let describe_edge w =
Format.sprintf "N%s:x -> N%s:e;" (string_of_label v) (string_of_label w)
in
String.concat "\n" @@ List.map describe_edge @@ ControlFlowGraph.successors cfg v
let visualize cfg table =
let labels = ControlFlowGraph.labels cfg in
let vertices = String.concat "\n" @@ List.map (describe_vertex cfg table) labels in
let edges = String.concat "\n" @@ List.map (describe_outedges cfg) labels in
String.concat "\n"
[ "digraph CFG {"
; "node [shape=none; fontname=\"Courier\" fontsize=\"9\"];"
; "ordering=out;"
; vertices
; edges
; "}"
]
end
module VisualiseRegGraph = struct
let reg_to_name = function
| REG_Hard i -> Format.sprintf "H%u" i
| REG_Tmp i -> Format.sprintf "T%u" i
| REG_Spec i -> Format.sprintf "S%u" i
let describe_vertex v =
Format.sprintf "%s[label=\"%s\"];" (reg_to_name v) (string_of_reg v)
let describe_edge a b =
Format.sprintf "%s -- %s;" (reg_to_name a) (reg_to_name b)
let describe_vertices graph =
String.concat "\n" @@ RegGraph.fold_vertex (fun r xs -> describe_vertex r :: xs) graph []
let describe_edges graph =
String.concat "\n" @@ RegGraph.fold_edges (fun a b xs -> describe_edge a b :: xs) graph []
let visualise_graph reggraph =
String.concat "\n"
[ "graph INF {"
; "layout=circo;"
; describe_vertices reggraph
; describe_edges reggraph
; "}"
]
end
module Lva_Graphviz = NgMakeGraphvizVisualizer(struct
type domain = Analysis_domain.LiveVariables.domain
let string_of_domain = Analysis_domain.LiveVariables.string_of_domain
end)
module Cfa_Graphviz = NgMakeGraphvizVisualizer(struct
type domain = Analysis_domain.ConstantFolding.domain
let string_of_domain = Analysis_domain.ConstantFolding.string_of_domain
end)
let visualize_live_variables = Lva_Graphviz.visualize
let visualize_interference_graph = VisualiseRegGraph.visualise_graph
let visualize_constant_folding = Cfa_Graphviz.visualize