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