/* dot_flow.c "emit" flow graphs to dot (graphvis). Copyright (C) 2011 Bill Currie Author: Bill Currie Date: 2011/01/21 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to: Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef HAVE_STRING_H # include #endif #ifdef HAVE_STRINGS_H # include #endif #include #include #include #include #include "expr.h" #include "statements.h" #include "strpool.h" #include "symtab.h" #include "type.h" static void flow_statement (dstring_t *dstr, statement_t *s) { dasprintf (dstr, " "); dasprintf (dstr, "%s", html_string(quote_string (s->opcode))); dasprintf (dstr, "%s", html_string(operand_string (s->opa))); dasprintf (dstr, "%s", html_string(operand_string (s->opb))); dasprintf (dstr, "%s", html_string(operand_string (s->opc))); dasprintf (dstr, "\n"); } static int is_goto (statement_t *s) { if (!s) return 0; return !strcmp (s->opcode, ""); } static int is_return (statement_t *s) { if (!s) return 0; return !strncmp (s->opcode, "opcode, "opb->o.label->dest; if (!strcmp (s->opcode, "")) return s->opa->o.label->dest; return 0; } static void flow_sblock (dstring_t *dstr, sblock_t *sblock, int blockno) { statement_t *s; sblock_t *target; ex_label_t *l; dasprintf (dstr, " sb_%p [shape=none,label=<\n", sblock); dasprintf (dstr, " \n"); dasprintf (dstr, " \n"); dasprintf (dstr, " \n", sblock, blockno); dasprintf (dstr, " \n"); dasprintf (dstr, " \n"); dasprintf (dstr, " \n"); for (s = sblock->statements; s; s = s->next) flow_statement (dstr, s); dasprintf (dstr, " \n"); dasprintf (dstr, " \n"); dasprintf (dstr, " \n"); dasprintf (dstr, " \n"); dasprintf (dstr, " \n"); dasprintf (dstr, "
%p(%d)\n"); for (l = sblock->labels; l; l = l->next) dasprintf (dstr, " %s(%d)\n", l->name, l->used); dasprintf (dstr, "
>];\n"); if (sblock->next && !is_goto ((statement_t *) sblock->tail) && !is_return ((statement_t *) sblock->tail)) dasprintf (dstr, " sb_%p:e -> sb_%p:s;\n", sblock, sblock->next); if ((target = get_target ((statement_t *) sblock->tail))) dasprintf (dstr, " sb_%p:e -> sb_%p:s [label=\"%s\"];\n", sblock, target, ((statement_t *) sblock->tail)->opcode); dasprintf (dstr, "\n"); } void print_flow (sblock_t *sblock, const char *filename) { int i; dstring_t *dstr = dstring_newstr(); dasprintf (dstr, "digraph flow_%p {\n", sblock); dasprintf (dstr, " layout=dot; rankdir=TB;\n"); for (i = 0; sblock; sblock = sblock->next, i++) flow_sblock (dstr, sblock, i); dasprintf (dstr, "}\n"); if (filename) { QFile *file; file = Qopen (filename, "wt"); Qwrite (file, dstr->str, dstr->size - 1); Qclose (file); } else { fputs (dstr->str, stdout); } dstring_delete (dstr); }