1 #!/usr/bin/gvpr -f
2 // Compute the forward partition of the chosen function
3 //
4 // Run with graph ... | return-paths | subg-fwd -a functionname
5 // or graph ... | subg-fwd
6
7
8 BEGIN {
9 // Find the immediate parent subgraph of this object
10 graph_t find_owner(obj_t o, graph_t g)
11 {
12 graph_t g1;
13 for (g1 = fstsubg(g); g1; g1 = nxtsubg(g1))
14 if(isIn(g1,o)) return g1;
15 return NULL;
16 }
17 }
18
19 BEG_G {
20 graph_t sg = subg ($, sprintf("incoming-%s", ARGV[0]));
21 graph_t returns = graph("return-edges", ""); // Temporary graph to hold return edges
22 graph_t target, g, g2;
23 node_t n;
24 edge_t e;
25 int i;
26
27 $tvtype = TV_fwd;
28
29 // find the ep corresponding to ARG[0]
30 for (g = fstsubg($G); g; g = nxtsubg(g)) {
31 if(g.fun == ARGV[0]) {
32 n = node($,g.ep);
33 $tvroot = n;
34 n.style = "filled";
35 target = g;
36 break;
37 }
38 }
39 if(!target) {
40 printf(2, "Function %s not found\n", ARGV[0]);
41 exit(1);
42 }
43 }
44
45 // Preserve external functions
46 E [op == "extern"] {
47 subnode (sg, head);
48 }
49
50 // Move unused return edges into a separate graph so they don't get followed
51 N [op == "ret"] {
52 for (e = fstout($); e; e = nxtout(e))
53 if (e.op == "ret" && !isIn(sg, e.head)) {
54 clone(returns, e);
55 delete($G, e);
56 }
57 }
58
59 // Recover elided return edge for this target node
60 N [op == "target" && indegree == 1] {
61 n = copy(returns, $);
62 e = fstin(n); // each target node can only have one return edge
63 e = edge(copy(sg, e.tail), $, "recovered"); // clone should work here, but doesn't
64 copyA(fstin(n), e);
65 }
66
67 // Copy relevant nodes
68 N {
69 $tvroot = NULL;
70
71 g = find_owner($, $G);
72 if(g && g != sg)
73 subnode (copy(sg, g), $);
74 }
75
76 END_G {
77 induce(sg);
78 write(sg);
79 }