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