xref: /illumos-gate/usr/src/tools/smatch/src/gvpr/subg-rev (revision 1f5207b7)
1*1f5207b7SJohn Levon#!/usr/bin/gvpr -f
2*1f5207b7SJohn Levon// Compute the reverse partition of the chosen function
3*1f5207b7SJohn Levon//
4*1f5207b7SJohn Levon// Run with graph ... | return-paths | subg-rev -a functionname
5*1f5207b7SJohn Levon
6*1f5207b7SJohn Levon
7*1f5207b7SJohn LevonBEGIN {
8*1f5207b7SJohn Levon	// Find the immediate parent subgraph of this object
9*1f5207b7SJohn Levon	graph_t find_owner(obj_t o, graph_t g)
10*1f5207b7SJohn Levon	{
11*1f5207b7SJohn Levon		graph_t g1;
12*1f5207b7SJohn Levon		for (g1 = fstsubg(g); g1; g1 = nxtsubg(g1))
13*1f5207b7SJohn Levon			if(isIn(g1,o)) return g1;
14*1f5207b7SJohn Levon		return NULL;
15*1f5207b7SJohn Levon	}
16*1f5207b7SJohn Levon}
17*1f5207b7SJohn Levon
18*1f5207b7SJohn LevonBEG_G {
19*1f5207b7SJohn Levon	graph_t calls[]; // Crude hash table for tracking who calls what
20*1f5207b7SJohn Levon	graph_t sg = subg ($, "reachable");
21*1f5207b7SJohn Levon	graph_t target, g, g2;
22*1f5207b7SJohn Levon	edge_t e;
23*1f5207b7SJohn Levon	int i;
24*1f5207b7SJohn Levon
25*1f5207b7SJohn Levon	$tvtype = TV_rev;
26*1f5207b7SJohn Levon
27*1f5207b7SJohn Levon	// find the ep corresponding to ARG[0]
28*1f5207b7SJohn Levon	for (g = fstsubg($G); g; g = nxtsubg(g)) {
29*1f5207b7SJohn Levon		if(g.fun == ARGV[0]) {
30*1f5207b7SJohn Levon			node_t n;
31*1f5207b7SJohn Levon			n = node($,g.ep);
32*1f5207b7SJohn Levon			$tvroot = n;
33*1f5207b7SJohn Levon			n.style = "filled";
34*1f5207b7SJohn Levon			target = g;
35*1f5207b7SJohn Levon			break;
36*1f5207b7SJohn Levon		}
37*1f5207b7SJohn Levon	}
38*1f5207b7SJohn Levon	if(!target) {
39*1f5207b7SJohn Levon		printf(2, "Function %s not found\n", ARGV[0]);
40*1f5207b7SJohn Levon		exit(1);
41*1f5207b7SJohn Levon	}
42*1f5207b7SJohn Levon
43*1f5207b7SJohn Levon	// Add the incoming call edges to the allowed call list
44*1f5207b7SJohn Levon	i = 0;
45*1f5207b7SJohn Levon	for(e = fstin(n); e; e = nxtin(e)) {
46*1f5207b7SJohn Levon		if (e.op = "call") {
47*1f5207b7SJohn Levon			g2 = find_owner(e.tail, $G);
48*1f5207b7SJohn Levon			calls[sprintf("%s%d", g2.name, ++i)] = g;
49*1f5207b7SJohn Levon		}
50*1f5207b7SJohn Levon	}
51*1f5207b7SJohn Levon}
52*1f5207b7SJohn Levon
53*1f5207b7SJohn Levon
54*1f5207b7SJohn LevonE [op == "ret"] {
55*1f5207b7SJohn Levon
56*1f5207b7SJohn Levon	// This is a return edge. Allow the corresponding call
57*1f5207b7SJohn Levon	g = find_owner(head, $G);
58*1f5207b7SJohn Levon	i = 0;
59*1f5207b7SJohn Levon	while(calls[sprintf("%s%d", g.name, ++i)]) {
60*1f5207b7SJohn Levon	}
61*1f5207b7SJohn Levon	calls[sprintf("%s%d", g.name, i)] = find_owner(tail, $G);
62*1f5207b7SJohn Levon	g2 = find_owner(tail, $G);
63*1f5207b7SJohn Levon}
64*1f5207b7SJohn Levon
65*1f5207b7SJohn Levon
66*1f5207b7SJohn LevonN [split == 1] {
67*1f5207b7SJohn Levon
68*1f5207b7SJohn Levon	// Ignore returns back to the target function
69*1f5207b7SJohn Levon	for (e = fstin($); e; e = nxtin(e))
70*1f5207b7SJohn Levon		if (e.op == "ret" && isIn(target,e.tail))
71*1f5207b7SJohn Levon			delete($G,e);
72*1f5207b7SJohn Levon}
73*1f5207b7SJohn Levon
74*1f5207b7SJohn LevonN {
75*1f5207b7SJohn Levon	$tvroot = NULL;
76*1f5207b7SJohn Levon
77*1f5207b7SJohn Levon	for (e = fstin($); e; e = nxtin(e)) {
78*1f5207b7SJohn Levon		if (e.op == "call") {
79*1f5207b7SJohn Levon			int found = 0;
80*1f5207b7SJohn Levon			g = find_owner(e.tail, $G);
81*1f5207b7SJohn Levon			i = 0;
82*1f5207b7SJohn Levon			while(calls[sprintf("%s%d", g.name, ++i)]) {
83*1f5207b7SJohn Levon				if (isIn(calls[sprintf("%s%d", g.name, i)],e.head))
84*1f5207b7SJohn Levon					found = 1;
85*1f5207b7SJohn Levon			}
86*1f5207b7SJohn Levon			g2 = find_owner(e.head, $G);
87*1f5207b7SJohn Levon			if (!found) delete($G, e);
88*1f5207b7SJohn Levon		}
89*1f5207b7SJohn Levon	}
90*1f5207b7SJohn Levon
91*1f5207b7SJohn Levon	for (g = fstsubg($G); g; g = nxtsubg(g)) {
92*1f5207b7SJohn Levon		if(isIn(g,$) && g != sg) {
93*1f5207b7SJohn Levon			subnode (copy(sg, g), $);
94*1f5207b7SJohn Levon		}
95*1f5207b7SJohn Levon	}
96*1f5207b7SJohn Levon}
97*1f5207b7SJohn Levon
98*1f5207b7SJohn LevonEND_G {
99*1f5207b7SJohn Levon	induce(sg);
100*1f5207b7SJohn Levon	write(sg);
101*1f5207b7SJohn Levon}
102