Skip to content

Commit 600060c

Browse files
committed
add gccutils.sorted_callgraph() to get callgraph in topologically-sorted order
1 parent 7b1f523 commit 600060c

File tree

4 files changed

+176
-0
lines changed

4 files changed

+176
-0
lines changed

gccutils.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,3 +634,45 @@ def check_isinstance(obj, types):
634634
"""
635635
if not isinstance(obj, types):
636636
raise TypeError('%s / %r is not an instance of %s' % (obj, obj, types))
637+
638+
def sorted_callgraph():
639+
"""
640+
Return the callgraph, in topologically-sorted order
641+
"""
642+
return topological_sort(gcc.get_callgraph_nodes(),
643+
get_srcs=lambda n: [edge.caller
644+
for edge in n.callers
645+
# Strip out recursive calls:
646+
if edge.caller != n],
647+
get_dsts=lambda n: [edge.callee
648+
for edge in n.callees
649+
# Strip out recursive calls:
650+
if edge.callee != n])
651+
652+
def topological_sort(nodes, get_srcs, get_dsts):
653+
"""
654+
Topological sort in O(n), based on depth-first traversal
655+
"""
656+
result = []
657+
visited = set()
658+
debug = False
659+
def visit(n):
660+
if n not in visited:
661+
if debug:
662+
print('first visit to %s' % n.decl)
663+
visited.add(n)
664+
for m in get_srcs(n):
665+
visit(m)
666+
if debug:
667+
print('adding to result: %s' % n.decl)
668+
result.append(n)
669+
else:
670+
if debug:
671+
print('already visited %s' % n.decl)
672+
673+
for n in nodes:
674+
if not get_dsts(n):
675+
visit(n)
676+
677+
return result
678+
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
/*
2+
Copyright 2012 David Malcolm <dmalcolm@redhat.com>
3+
Copyright 2012 Red Hat, Inc.
4+
5+
This is free software: you can redistribute it and/or modify it
6+
under the terms of the GNU General Public License as published by
7+
the Free Software Foundation, either version 3 of the License, or
8+
(at your option) any later version.
9+
10+
This program is distributed in the hope that it will be useful, but
11+
WITHOUT ANY WARRANTY; without even the implied warranty of
12+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
General Public License for more details.
14+
15+
You should have received a copy of the GNU General Public License
16+
along with this program. If not, see
17+
<http://www.gnu.org/licenses/>.
18+
*/
19+
20+
/*
21+
Verify that the topological sort code in gccutils works
22+
*/
23+
24+
int a(int);
25+
int b(int);
26+
int c(int);
27+
int d(int);
28+
int e(int);
29+
int f(int);
30+
int g(int);
31+
int h(int);
32+
int j(int);
33+
int k(int);
34+
35+
int a(int i)
36+
{
37+
return e(i) + c(i);
38+
}
39+
40+
int b(int i)
41+
{
42+
return 42 - i;
43+
}
44+
45+
int c(int i)
46+
{
47+
return i * i;
48+
}
49+
50+
int d(int i)
51+
{
52+
return a(i) + b(c(i));
53+
}
54+
55+
/* Directly recursive (actually factorial) */
56+
int e(int i)
57+
{
58+
if (i>1) {
59+
return i * e(i-1);
60+
} else {
61+
return 1;
62+
}
63+
}
64+
65+
/* f and g are mutually recursive */
66+
int f(int i)
67+
{
68+
return g(i) + b(i);
69+
}
70+
71+
int g(int i)
72+
{
73+
return f(i) + c(i) + k(i);
74+
}
75+
76+
/* h is entirely disjoint from the rest of the graph */
77+
int h(int i)
78+
{
79+
return i;
80+
}
81+
82+
int j(int i)
83+
{
84+
return 2 * f(i);
85+
}
86+
87+
/* k is not defined */
88+
89+
/*
90+
PEP-7
91+
Local variables:
92+
c-basic-offset: 4
93+
indent-tabs-mode: nil
94+
End:
95+
*/
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright 2012 David Malcolm <dmalcolm@redhat.com>
3+
# Copyright 2012 Red Hat, Inc.
4+
#
5+
# This is free software: you can redistribute it and/or modify it
6+
# under the terms of the GNU General Public License as published by
7+
# the Free Software Foundation, either version 3 of the License, or
8+
# (at your option) any later version.
9+
#
10+
# This program is distributed in the hope that it will be useful, but
11+
# WITHOUT ANY WARRANTY; without even the implied warranty of
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
# General Public License for more details.
14+
#
15+
# You should have received a copy of the GNU General Public License
16+
# along with this program. If not, see
17+
# <http://www.gnu.org/licenses/>.
18+
19+
# Verify that the topological sort code in gccutils works
20+
import gcc
21+
22+
def on_pass_execution(p, fn):
23+
if p.name == '*free_lang_data':
24+
from gccutils import sorted_callgraph
25+
for cgn in sorted_callgraph():
26+
print(cgn.decl)
27+
28+
gcc.register_callback(gcc.PLUGIN_PASS_EXECUTION,
29+
on_pass_execution)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
j
2+
f
3+
g
4+
k
5+
h
6+
d
7+
a
8+
e
9+
c
10+
b

0 commit comments

Comments
 (0)