@@ -80,6 +80,67 @@ def disasm
8080 fmt . string
8181 end
8282
83+ def to_mermaid
84+ output = StringIO . new
85+ output . puts ( "flowchart TD" )
86+
87+ fmt = Disassembler ::Mermaid . new
88+ links = [ ]
89+
90+ cfg . blocks . each do |block |
91+ block_flow = block_flows . fetch ( block . id )
92+ graph_name =
93+ if block_flow . in . any?
94+ "#{ block . id } #{ block_flows [ block . id ] . in . join ( ", " ) } "
95+ else
96+ block . id
97+ end
98+
99+ output . puts ( " subgraph \" #{ CGI . escapeHTML ( graph_name ) } \" " )
100+ previous = nil
101+
102+ block . each_with_length do |insn , length |
103+ node_id = "node_#{ length } "
104+ label = "%04d %s" % [ length , insn . disasm ( fmt ) ]
105+
106+ output . puts ( " #{ node_id } (\" #{ CGI . escapeHTML ( label ) } \" )" )
107+
108+ if previous
109+ output . puts ( " #{ previous } --> #{ node_id } " )
110+ links << "red"
111+ end
112+
113+ insn_flows [ length ] . in . each do |input |
114+ if input . is_a? ( Integer )
115+ output . puts ( " node_#{ input } --> #{ node_id } " )
116+ links << "green"
117+ end
118+ end
119+
120+ previous = node_id
121+ end
122+
123+ output . puts ( " end" )
124+ end
125+
126+ cfg . blocks . each do |block |
127+ block . outgoing_blocks . each do |outgoing |
128+ offset =
129+ block . block_start + block . insns . sum ( &:length ) -
130+ block . insns . last . length
131+
132+ output . puts ( " node_#{ offset } --> node_#{ outgoing . block_start } " )
133+ links << "red"
134+ end
135+ end
136+
137+ links . each_with_index do |color , index |
138+ output . puts ( " linkStyle #{ index } stroke:#{ color } " )
139+ end
140+
141+ output . string
142+ end
143+
83144 # Verify that we constructed the data flow graph correctly.
84145 def verify
85146 # Check that the first block has no arguments.
0 commit comments