123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- #!/usr/bin/gvpr -f
- // Split call sites into call site and return site nodes and add
- // return edges
- //
- // Run with graph ... | return-paths
- BEGIN {
- // Find the immediate parent subgraph of this object
- graph_t find_owner(obj_t o, graph_t g)
- {
- graph_t g1;
- for (g1 = fstsubg(g); g1; g1 = nxtsubg(g1))
- if(isIn(g1,o)) return g1;
- return NULL;
- }
- }
- BEG_G {
- node_t calls[]; // Crude hash table for tracking who calls what
- graph_t g,g2;
- edge_t e,e2;
- string idx;
- node_t n, n2;
- int i;
- $tvtype = TV_en;
- }
- // Each call edge which hasn't already been seen
- E [op == "call" && tail.split != 1] {
- int offset=0;
- // Clear the label of this call
- label = "";
- g = find_owner(tail, $G);
- // Consider each outgoing call. Split the node accordingly
- n = tail;
- for (e = fstout(tail); e; e = nxtout(e)) {
- if (e.op == "call") {
- // Split node
- n2 = node(g, sprintf("%s%s%d", tail.name, "x", offset++));
- copyA(tail, n2);
- n2.line = e.line;
- n2.label = e.line;
- n2.col = e.col;
- n2.split = 1;
- n2.op = "target";
- // Record this call
- g2 = find_owner(e.head, $G);
- i = 0;
- while(calls[sprintf("%s%d", g2.name, ++i)]) {
- }
- calls[sprintf("%s%d", g2.name, i)] = n2;
- // Connect original to split
- e2 = edge(n, n2, "call");
- e2.style = "dotted";
- e2.weight = 50;
- // Replace this outedge
- if (n != tail) {
- e2 = edge(n, e.head, "transformed-call");
- copyA(e,e2);
- e2.label = "";
- delete($G,e);
- }
- // Record where we were
- n = n2;
- }
- }
- // Consider the outgoing control flow: move down to the bottom of
- // the call sequence nodes
- for (e = fstout(tail); e; e = nxtout(e)) {
- if (e.op == "br") {
- // Replace this outedge
- e2 = edge(n,e.head,"transformed");
- copyA(e,e2);
- delete($G,e);
- }
- }
- }
- // Each return node: add edges back to the caller
- N [op == "ret"] {
- for (g = fstsubg($G); g; g = nxtsubg(g)) {
- if(isIn(g,$)) {
- i = 0;
- while(calls[sprintf("%s%d", g.name, ++i)]) {
- e = edge($, calls[sprintf("%s%d", g.name, i)], "return");
- e.style = "dotted";
- e.op = "ret";
- e.line = e.tail.line;
- e.weight = 5;
- }
- }
- }
- }
- END_G {
- write($);
- }
|