summary refs log tree commit diff
path: root/source/xi_lib/analysis_visualizer.ml
blob: 6c8ccf3cf8940d223052218c8cf45a990c548944 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
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 "<tr><td>%s</td><td align='left'><b>%s</b></td><td>%s</td></tr>" pre instr post
    ]

  let visualise_terminator (pre, post, t) =
    let t = string_of_terminator t in 
    String.concat "\n"
    [
      Format.sprintf "<tr><td>%s</td><td bgcolor='green' ><b>%s</b></td><td>%s</td></tr>" pre t post
    ]

  let block_template_pre pre name =
      [ Format.sprintf "<table cellspacing='0' cellborder='1' align='left' border='0'>"
      ; Format.sprintf "<tr><td colspan='3' port='e' bgcolor='yellow'><b>%s</b></td></tr>" name
      ; Format.sprintf "<tr><td colspan='3'>%s</td></tr>" @@ pre
      ]

  let block_template_post post =
      [ Format.sprintf "<tr><td colspan='3' port='x'>%s</td></tr>" post
      ; Format.sprintf "</table>"
      ]

  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 "<tr><td>%s</td><td align='left'><b>%s</b></td><td>%s</td></tr>" 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 "<tr><td>%s</td><td bgcolor='green' ><b>%s</b></td><td>%s</td></tr>" pre t post
    ]

  let block_template_pre pre name =
      [ Format.sprintf "<table cellspacing='0' cellborder='1' align='left' border='0'>"
      ; Format.sprintf "<tr><td colspan='3' port='e' bgcolor='yellow'><b>%s</b></td></tr>" name
      ; Format.sprintf "<tr><td colspan='3'>%s</td></tr>" @@ pre
      ]

  let block_template_post post =
      [ Format.sprintf "<tr><td colspan='3' port='x'>%s</td></tr>" post
      ; Format.sprintf "</table>"
      ]

  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