/** * Recursively visit b and its successors. We search exception edges * first in a weak attempt to put exception blocks later in the final * reverse-postorder numbering, but it shouldn't matter and anyone * counting on that has a bug. */ void RpoSort::visit(Block* b) { if (visited[b->id]) return; visited[b->id] = true; for (BlockPtrRange i = exnBlocks(g, b); !i.empty(); ) visit(i.popBack()); for (BlockPtrRange i = succBlocks(b); !i.empty(); ) visit(i.popBack()); b->next_rpo = g->first_rpo; g->first_rpo = b; rpo_id++; b->rpo_id = g->block_count - rpo_id; }
std::string blockToString(const Block* b, const Graph* /*g*/, const Unit* u) { std::stringstream out; out << "B" << b->id << ":" << u->offsetOf(b->start) << "-" << u->offsetOf(b->last) << " rpo=" << b->rpo_id << " succ="; for (BlockPtrRange j = succBlocks(b); !j.empty(); ) { const Block* s = j.popFront(); out << "B" << s->id << (j.empty() ? "" : ","); } if (b->exn) { out << " exn=B" << b->exn->id; } return out.str(); }
std::string blockToString(const Block* b, const Graph* g, const Unit* u) { std::stringstream out; out << "B" << b->id << ":" << u->offsetOf((Opcode*)b->start) << "-" << u->offsetOf((Opcode*)b->last) << " rpo=" << b->rpo_id << " succ="; for (BlockPtrRange j = succBlocks(b); !j.empty(); ) { const Block* s = j.popFront(); out << "B" << s->id << (j.empty() ? "" : ","); } if (g->exn_cap) { out << " exns="; for (BlockPtrRange j = exnBlocks(g, b); !j.empty(); ) { const Block* s = j.popFront(); out << "B" << s->id << (j.empty() ? "" : ","); } } return out.str(); }
void printGml(const Unit* unit) { string filename = unit->md5().toString() + ".gml"; FILE* file = fopen(filename.c_str(), "w"); if (!file) { std::cerr << "Couldn't open GML output file " << filename << std::endl; return; } int nextid = 1; fprintf(file, "graph [\n" " hierarchic 1\n" " directed 1\n"); for (AllFuncs i(unit); !i.empty(); ) { const Func* func = i.popFront(); Arena scratch; GraphBuilder builder(scratch, func); const Graph* g = builder.build(); int gid = nextid++; fprintf(file, "node [ isGroup 1 id %d ]\n", gid); // nodes for (LinearBlocks j = linearBlocks(g); !j.empty();) { const Block* b = j.popFront(); std::stringstream strbuf; unit->prettyPrint(strbuf, Unit::PrintOpts().range(unit->offsetOf(b->start), unit->offsetOf(b->end))); std::string code = strbuf.str(); for (int i = 0, n = code.size(); i < n; ++i) { if (code[i] == '"') code[i] = '\''; } fprintf(file, " node [ id %d gid %d\n" " graphics [ type \"roundrectangle\" ]" " LabelGraphics [" " anchor \"e\"" " alignment \"left\"" " fontName \"Consolas\"\n" " text \"%s\"\n" " ]\n" " ]\n", nextid + b->id, gid, code.c_str()); } // edges for (LinearBlocks j = linearBlocks(g); !j.empty();) { const Block* b = j.popFront(); for (BlockPtrRange k = succBlocks(b); !k.empty();) { const Block* s = k.popFront(); fprintf(file, " edge [ source %d target %d ]\n", nextid + b->id, nextid + s->id); } for (BlockPtrRange k = exnBlocks(g, b); !k.empty();) { const Block* s = k.popFront(); fprintf(file, " edge [ source %d target %d" " graphics [ style \"dotted\" ]" " ]\n", nextid + b->id, nextid + s->id); } } nextid += g->block_count + 1; } fprintf(file, "]\n"); fclose(file); }