2121
2222cfg_dir = Path (args .cfg_dir )
2323
24- targets = []
24+ def parse_target_file (targets_file ):
25+ targets = []
26+ with open (targets_file , 'r' ) as f :
27+ for line in f :
28+ target_file , target_line = line .strip ().split (':' )
29+ target_line = int (target_line )
30+ targets .append ((target_file , target_line ))
31+
32+ for target in targets :
33+ print (f'* user target { target [0 ]} :{ target [1 ]} ' , file = sys .stderr )
34+
35+ return targets
36+
37+ def translate_target (target_file , target_line , target_blocks_map_file ):
38+ # target-blocks-map.txt:simplified-lowering.cc:2927 ../../src/compiler/simplified-lowering.cc:2933
39+ # target-blocks-map.txt:simplified-lowering.cc:2927 ../../src/compiler/simplified-lowering.cc:2933
40+ # target-blocks-map.txt:simplified-lowering.cc:2927 ../../src/compiler/simplified-lowering.cc:2933
41+ # target-blocks-map.txt:simplified-lowering.cc:2927 ../../src/compiler/simplified-lowering.cc:2933
42+ # target-blocks-map.txt:simplified-lowering.cc:2927 ../../src/compiler/simplified-lowering.cc:2933
43+ # target-blocks-map.txt:simplified-lowering.cc:2927 ../../src/compiler/simplified-lowering.cc:2934
44+ targets = []
45+ assert target_blocks_map_file .exists ()
46+ with open (target_blocks_map_file , 'r' ) as f :
47+ for line in f :
48+ bbid , target = line .strip ().split (' ' )
49+ if f'{ target_file } :{ target_line } ' in target :
50+ filename , lineno = bbid .split (':' )
51+ lineno = int (lineno )
52+ targets .append ((filename , lineno ))
53+ return list (set (targets ))
2554
26- for line in open (args .targets_file ):
27- target_file , target_line = line .strip ().split (':' )
28- target_line = int (target_line )
29- targets .append ((target_file , target_line ))
55+ user_targets = parse_target_file (args .targets_file )
56+ assert len (user_targets ) > 0 , f'No targets found in { args .targets_file } '
3057
31- print (target_file , target_line , file = sys .stderr )
58+ targets = []
59+ for filename , lineno in user_targets :
60+ t = translate_target (filename , lineno , cfg_dir / 'target-blocks-map.txt' )
61+ targets .extend (t )
62+
63+ for t in targets :
64+ print (f'* target { t [0 ]} :{ t [1 ]} ' , file = sys .stderr )
3265
33- for target in targets :
34- logging .info (f'Target: { target [0 ]} :{ target [1 ]} ' )
66+ assert len (targets ) > 0 , f'No targets found in { cfg_dir / "target-blocks-map.txt" } '
3567
3668# each line looks like
3769# simplified-lowering.cc:_ZN2v88internal8compiler22RepresentationSelector12EnqueueInputILNS1_5PhaseE0EEEvPNS1_4NodeEiNS1_7UseInfoE:0:0:384103392 _ZN2v88internal8compiler22RepresentationSelector7GetInfoEPNS1_4NodeE
3870def parse_callgraph (callgraph_txt ):
71+ calledges = []
3972 with open (callgraph_txt , 'r' ) as f :
4073 for line in f :
4174 caller , callee = line .strip ().split ()
42- # print(f'{caller} -> {callee}')
4375 filename , funcname , lineno , order , bbid = caller .split (':' )
44- yield (filename , funcname , lineno , order , hex (int (bbid ))), callee
76+ edge = (filename , funcname , lineno , order , hex (int (bbid ))), callee
77+ calledges .append (edge )
78+ return calledges
79+
80+
81+ def merge_cfgs (cfgs , callgraph ):
82+ merged = nx .MultiDiGraph ()
83+ for cfg in cfgs :
84+ merged = nx .compose (merged , cfg )
85+
86+ for caller , callee in callgraph :
87+ _filename , _funcname , _lineno , _order , bbid = caller
88+ node = 'Node' + bbid
89+ assert node in merged , f'Node { node } not found in entire CFG'
90+ if callee in func_to_node :
91+ merged .add_edge (node , func_to_node [callee ], weight = 10 )
92+
93+ # print('nodes in the merged graph', merged.nodes(data=True), file=sys.stderr)
94+ # print('edges in the merged graph', merged.edges(keys=True, data=True), file=sys.stderr)
95+
96+ return merged
4597
4698target_nodes = []
4799
48100# need to extract (function name -> first block id)
49- def parse_cfg (cfg_file ):
101+ def parse_cfg (cfg_file , targets ):
50102 graph : pydot .Graph = pydot .graph_from_dot_file (cfg_file )[0 ]
51103 graph : nx .MultiDiGraph = nx .drawing .nx_pydot .from_pydot (graph )
52- # print('graph name', graph.name)
53- # set edge weight as 1
54104 for u , v , k , d in graph .edges (keys = True , data = True ):
55105 d ['weight' ] = 1
56106
@@ -68,48 +118,38 @@ def parse_cfg(cfg_file):
68118 logging .info (f'Found target node { n } in { cfg_file } ' )
69119 break
70120
71- # print('graph nodes', graph.nodes(data=True))
72- # print('graph edges', graph.edges(keys=True, data=True))
73121 return graph
74122
75- callgraph = list ( parse_callgraph ( cfg_dir / 'callgraph.txt' ))
76- cfgs = []
77- func_to_node = {}
78- for f in cfg_dir . glob ( '*.dot' ):
79- g = parse_cfg ( f )
80- cfgs . append ( g )
123+ def parse_cfgs ( cfg_dir , targets ):
124+ cfgs = []
125+ for f in cfg_dir . glob ( '*.dot' ):
126+ g = parse_cfg ( f , targets )
127+ cfgs . append ( g )
128+ return cfgs
81129
82- the_node = min (g .nodes (data = True ), key = lambda n : n [1 ]['order' ])
83- # print(the_node)
84- func_to_node [g .name ] = the_node [0 ]
130+ def build_funcmap (cfgs ):
131+ func_to_node = {}
132+ for g in cfgs :
133+ the_node = min (g .nodes (data = True ), key = lambda n : n [1 ]['order' ])
134+ func_to_node [g .name ] = the_node [0 ]
135+ return func_to_node
85136
86- # for func, first_node in func_to_node.items():
87- # print(f'{func} -> {first_node}')
88137
89- logging .info (f'{ len (target_nodes )} target nodes found' )
138+ callgraph = parse_callgraph (cfg_dir / 'callgraph.txt' )
139+ cfgs = parse_cfgs (cfg_dir , targets )
140+ func_to_node = build_funcmap (cfgs )
90141
91- logging .info (f'{ len (callgraph )} call edges found in callgraph.txt' )
92- logging .info (f'{ len (cfgs )} CFG files found in { cfg_dir } ' )
142+ print (f'{ len (cfgs )} CFG files found in { cfg_dir } ' , file = sys .stderr )
143+ print (f'{ len (target_nodes )} target nodes found' , file = sys .stderr )
144+ print (f'{ len (callgraph )} call edges found' , file = sys .stderr )
93145
94146node_cnt = sum ([cfg .number_of_nodes () for cfg in cfgs ])
95147edge_cnt = sum ([cfg .number_of_edges () for cfg in cfgs ])
96148
97- logging .info (f'Total number of nodes: { node_cnt } ' )
98- logging .info (f'Total number of edges: { edge_cnt } ' )
99-
100- # merge cfgs into one
101- entire_cfg = nx .MultiDiGraph ()
102- for cfg in cfgs :
103- entire_cfg = nx .compose (entire_cfg , cfg )
104-
105- for caller , callee in callgraph :
106- filename , funcname , lineno , order , bbid = caller
107- node = 'Node' + bbid
108- assert node in entire_cfg , f'Node { node } not found in entire CFG'
109- entire_cfg .add_edge (node , func_to_node [callee ], weight = 10 )
149+ print (f'Total number of nodes: { node_cnt } ' , file = sys .stderr )
150+ print (f'Total number of edges: { edge_cnt } ' , file = sys .stderr )
110151
111- logging .info (f'Number of nodes in entire CFG: { entire_cfg .number_of_nodes ()} ' )
112- logging .info (f'Number of edges in entire CFG: { entire_cfg .number_of_edges ()} ' )
152+ entire_cfg = merge_cfgs (cfgs , callgraph )
113153
114154fulldistmap = defaultdict (list )
115155for v in target_nodes :
0 commit comments