aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/gvpr/subg-fwd
diff options
authorDan Sheridan <djs@postman.org.uk>2007-05-15 12:28:08 +0100
committerJosh Triplett <josh@freedesktop.org>2007-05-22 14:58:29 -0700
commitfdbc0f5de7663893f6fcfe9cbcccb52b9d093db1 (patch)
tree51b8812047efc3be78b8d6b682dd2b314445edd3 /gvpr/subg-fwd
parentbb7ff206a0a1afca8eefbf3fedd7b5962cdec6f1 (diff)
downloadsparse-dev-fdbc0f5de7663893f6fcfe9cbcccb52b9d093db1.tar.gz
Add gvpr-based post-processing for graphs
Three gvpr scripts for post-processing the dot files generated by graph.c: return-paths: splits each call site and adds return edges to complete the control flow graph subg-fwd: find the subgraph reachable from a given function subg-rev: find the subgraph which can reach a given function Signed-off-by: Dan Sheridan <djs@adelard.com>
Diffstat (limited to 'gvpr/subg-fwd')
-rw-r--r--gvpr/subg-fwd78
1 files changed, 78 insertions, 0 deletions
diff --git a/gvpr/subg-fwd b/gvpr/subg-fwd
new file mode 100644
index 00000000..8950fa5c
--- /dev/null
+++ b/gvpr/subg-fwd
@@ -0,0 +1,78 @@
+// Compute the forward partition of the chosen function
+//
+// Run with graph ... | gvpr -f return-paths | gvpr -f subg-fwd -a functionname
+// or graph ... | gvpr -f subg-fwd
+
+
+BEGIN {
+ // Find the immediate parent subgraph of this object
+ graph_t find_owner(obj_t o, graph_t g)
+ {
+ graph_t g1;
+ for (g1 = fstsubg(g); g1; g1 = nxtsubg(g1))
+ if(isIn(g1,o)) return g1;
+ return NULL;
+ }
+}
+
+BEG_G {
+ graph_t sg = subg ($, sprintf("incoming-%s", ARGV[0]));
+ graph_t returns = graph("return-edges", ""); // Temporary graph to hold return edges
+ graph_t target, g, g2;
+ node_t n;
+ edge_t e;
+ int i;
+
+ $tvtype = TV_fwd;
+
+ // find the ep corresponding to ARG[0]
+ for (g = fstsubg($G); g; g = nxtsubg(g)) {
+ if(g.fun == ARGV[0]) {
+ n = node($,g.ep);
+ $tvroot = n;
+ n.style = "filled";
+ target = g;
+ break;
+ }
+ }
+ if(!target) {
+ printf(2, "Function %s not found\n", ARGV[0]);
+ exit(1);
+ }
+}
+
+// Preserve external functions
+E [op == "extern"] {
+ subnode (sg, head);
+}
+
+// Move unused return edges into a separate graph so they don't get followed
+N [op == "ret"] {
+ for (e = fstout($); e; e = nxtout(e))
+ if (e.op == "ret" && !isIn(sg, e.head)) {
+ clone(returns, e);
+ delete($G, e);
+ }
+}
+
+// Recover elided return edge for this target node
+N [op == "target" && indegree == 1] {
+ n = copy(returns, $);
+ e = fstin(n); // each target node can only have one return edge
+ e = edge(copy(sg, e.tail), $, "recovered"); // clone should work here, but doesn't
+ copyA(fstin(n), e);
+}
+
+// Copy relevant nodes
+N {
+ $tvroot = NULL;
+
+ g = find_owner($, $G);
+ if(g && g != sg)
+ subnode (copy(sg, g), $);
+}
+
+END_G {
+ induce(sg);
+ write(sg);
+}