@@ -6,6 +6,15 @@ module YARV
6
6
# control-flow-graph. Data flow is discovered locally and then globally. The
7
7
# graph only considers data flow through the stack - local variables and
8
8
# objects are considered fully escaped in this analysis.
9
+ #
10
+ # You can use this class by calling the ::compile method and passing it a
11
+ # control flow graph. It will return a data flow graph object.
12
+ #
13
+ # iseq = RubyVM::InstructionSequence.compile("1 + 2")
14
+ # iseq = SyntaxTree::YARV::InstructionSequence.from(iseq.to_a)
15
+ # cfg = SyntaxTree::YARV::ControlFlowGraph.compile(iseq)
16
+ # dfg = SyntaxTree::YARV::DataFlowGraph.compile(cfg)
17
+ #
9
18
class DataFlowGraph
10
19
# This object represents the flow of data between instructions.
11
20
class DataFlow
@@ -28,42 +37,42 @@ def initialize(cfg, insn_flows, block_flows)
28
37
29
38
def disasm
30
39
fmt = Disassembler . new ( cfg . iseq )
31
- fmt . output . puts ( "== dfg: #{ cfg . iseq . inspect } " )
40
+ fmt . puts ( "== dfg: #{ cfg . iseq . inspect } " )
32
41
33
42
cfg . blocks . each do |block |
34
- fmt . output . puts ( block . id )
43
+ fmt . puts ( block . id )
35
44
fmt . with_prefix ( " " ) do |prefix |
36
45
unless block . incoming_blocks . empty?
37
46
from = block . incoming_blocks . map ( &:id )
38
- fmt . output . puts ( "#{ prefix } == from: #{ from . join ( ", " ) } " )
47
+ fmt . puts ( "#{ prefix } == from: #{ from . join ( ", " ) } " )
39
48
end
40
49
41
50
block_flow = block_flows . fetch ( block . id )
42
51
unless block_flow . in . empty?
43
- fmt . output . puts ( "#{ prefix } == in: #{ block_flow . in . join ( ", " ) } " )
52
+ fmt . puts ( "#{ prefix } == in: #{ block_flow . in . join ( ", " ) } " )
44
53
end
45
54
46
55
fmt . format_insns! ( block . insns , block . block_start ) do |_ , length |
47
56
insn_flow = insn_flows [ length ]
48
57
next if insn_flow . in . empty? && insn_flow . out . empty?
49
58
50
- fmt . output . print ( " # " )
59
+ fmt . print ( " # " )
51
60
unless insn_flow . in . empty?
52
- fmt . output . print ( "in: #{ insn_flow . in . join ( ", " ) } " )
53
- fmt . output . print ( "; " ) unless insn_flow . out . empty?
61
+ fmt . print ( "in: #{ insn_flow . in . join ( ", " ) } " )
62
+ fmt . print ( "; " ) unless insn_flow . out . empty?
54
63
end
55
64
56
65
unless insn_flow . out . empty?
57
- fmt . output . print ( "out: #{ insn_flow . out . join ( ", " ) } " )
66
+ fmt . print ( "out: #{ insn_flow . out . join ( ", " ) } " )
58
67
end
59
68
end
60
69
61
70
to = block . outgoing_blocks . map ( &:id )
62
71
to << "leaves" if block . insns . last . leaves?
63
- fmt . output . puts ( "#{ prefix } == to: #{ to . join ( ", " ) } " )
72
+ fmt . puts ( "#{ prefix } == to: #{ to . join ( ", " ) } " )
64
73
65
74
unless block_flow . out . empty?
66
- fmt . output . puts ( "#{ prefix } == out: #{ block_flow . out . join ( ", " ) } " )
75
+ fmt . puts ( "#{ prefix } == out: #{ block_flow . out . join ( ", " ) } " )
67
76
end
68
77
end
69
78
end
0 commit comments