xref: /illumos-gate/usr/src/tools/smatch/src/gvpr/subg-fwd (revision 1f5207b7)
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
8BEGIN {
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
19BEG_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
46E [op == "extern"] {
47	subnode (sg, head);
48}
49
50// Move unused return edges into a separate graph so they don't get followed
51N [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
60N [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
68N {
69	$tvroot = NULL;
70
71	g = find_owner($, $G);
72	if(g && g != sg)
73		subnode (copy(sg, g), $);
74}
75
76END_G {
77	induce(sg);
78	write(sg);
79}
80