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