/*
- * Project: libFIRM
- * File name: ir/ir/irdump.c
- * Purpose: Write vcg representation of firm to file.
- * Author: Martin Trapp, Christian Schaefer
- * Modified by: Goetz Lindenmaier, Hubert Schmidt
- * Created:
- * CVS-ID: $Id$
- * Copyright: (c) 1998-2006 Universit�t Karlsruhe
- * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
+ * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
+ *
+ * This file is part of libFirm.
+ *
+ * This file may be distributed and/or modified under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * Licensees holding valid libFirm Professional Edition licenses may use
+ * this file in accordance with the libFirm Commercial License.
+ * Agreement provided with the Software.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ */
+
+/**
+ * @file
+ * @brief Write vcg representation of firm to file.
+ * @author Martin Trapp, Christian Schaefer, Goetz Lindenmaier, Hubert Schmidt
+ * @version $Id$
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#include "irdump_t.h"
#include "irgwalk.h"
-#include "typewalk.h"
#include "tv_t.h"
-#include "type_or_entity.h"
#include "irouts.h"
+#include "iredges.h"
#include "irdom.h"
#include "irloop_t.h"
#include "callgraph.h"
static int const_entities = 1;
/** An option to dump the keep alive edges */
static int dump_keepalive = 0;
+/** An option to dump the new out edges */
+static int dump_new_edges_flag = 0;
/** An option to dump ld_names instead of names. */
static int dump_ld_name = 1;
/** Compiler options to dump analysis information in dump_ir_graph */
static int dump_loop_information_flag = 0;
static int dump_backedge_information_flag = 1;
static int dump_const_local = 0;
+static int dump_node_idx_labels = 0;
/** An option to dump all graph anchors */
static int dump_anchors = 0;
* are set, else returns dump_const_local_flag.
*/
int get_opt_dump_const_local(void) {
- if (!dump_out_edge_flag && !dump_loop_information_flag)
- return dump_const_local;
- else
+ if (dump_out_edge_flag || dump_loop_information_flag || (dump_new_edges_flag && edges_activated(current_ir_graph)))
return 0;
+ return dump_const_local;
}
/* Set a prefix filter for output functions. */
dump_const_local = flag;
}
+void dump_node_idx_label(int flag) {
+ dump_node_idx_labels = flag;
+}
+
void dump_constant_entity_values(int flag) {
const_entities = flag;
}
dump_keepalive = flag;
}
+void dump_new_edges(int flag) {
+ dump_new_edges_flag = flag;
+}
+
int get_opt_dump_keepalive_edges(void) {
return dump_keepalive;
}
* Walker, clears the private link field.
*/
static void clear_link(ir_node * node, void * env) {
+ (void) env;
ird_set_irn_link(node, NULL);
}
* Walker that visits the anchors
*/
static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
- irg_walk_graph(irg, pre, post, env);
-
- if (dump_anchors) {
- int i;
-
- for (i = anchor_max - 1; i >= 0; --i) {
- ir_node *n = irg->anchors[i];
-
- if (n) {
- /* reset the visit flag: will be increase in the walker */
- set_irg_visited(irg, get_irg_visited(irg) - 1);
- irg_walk(n, pre, post, env);
- }
- }
+ if (dump_anchors || (dump_new_edges_flag && edges_activated(irg))) {
+ irg_walk_anchors(irg, pre, post, env);
+ } else {
+ irg_walk_graph(irg, pre, post, env);
}
}
* Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
*/
static void collect_node(ir_node * node, void *env) {
+ (void) env;
if (is_Block(node)
|| node_floats(node)
|| get_irn_op(node) == op_Bad
* Free the list with DEL_ARR_F().
*/
static ir_node **construct_block_lists(ir_graph *irg) {
- int i, rem_view = get_interprocedural_view();
- ir_graph *rem = current_ir_graph;
+ int i;
+#ifdef INTERPROCEDURAL_VIEW
+ int rem_view = get_interprocedural_view();
+#endif
+ int walk_flag = using_visited(irg);
+ ir_graph *rem = current_ir_graph;
+
current_ir_graph = irg;
+ if(walk_flag)
+ clear_using_visited(current_ir_graph);
+
for (i = get_irp_n_irgs() - 1; i >= 0; --i)
ird_set_irg_link(get_irp_irg(i), NULL);
ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
+#ifdef INTERPROCEDURAL_VIEW
/* Collect also EndReg and EndExcept. We do not want to change the walker. */
set_interprocedural_view(0);
+#endif
set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
+#ifdef INTERPROCEDURAL_VIEW
set_interprocedural_view(rem_view);
+#endif
+
+ if(walk_flag)
+ set_using_visited(current_ir_graph);
current_ir_graph = rem;
return ird_get_irg_link(irg);
int res;
char buf[1024];
res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
- assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
+ assert(res < (int) sizeof(buf) && "buffer to small for tarval_snprintf");
fprintf(F, buf);
} break;
case symconst_enum_const:
fprintf(F, "SymC %s enum", get_enumeration_name(get_SymConst_enum(n)));
break;
+ case symconst_label:
+ fprintf(F, "SymC %lu label", get_SymConst_label(n));
+ break;
}
} break;
break;
}
case iro_Load:
+ if (get_Load_align(n) == align_non_aligned)
+ fprintf(F, "ua");
fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Load_mode(n), &bad));
break;
+ case iro_Store:
+ if (get_Store_align(n) == align_non_aligned)
+ fprintf(F, "ua");
+ fprintf(F, "%s", get_irn_opname(n));
+ break;
case iro_Block:
fprintf(F, "%s%s", is_Block_dead(n) ? "Dead " : "", get_irn_opname(n));
break;
fprintf(F, "strict");
fprintf(F, "%s", get_irn_opname(n));
break;
+ case iro_Div:
+ fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Div_resmode(n), &bad));
+ break;
+ case iro_Mod:
+ fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_Mod_resmode(n), &bad));
+ break;
+ case iro_DivMod:
+ fprintf(F, "%s[%s]", get_irn_opname(n), get_mode_name_ex(get_DivMod_resmode(n), &bad));
+ break;
default:
default_case:
static const pns_lookup_t call_lut[] = {
#define X(a) { pn_Call_##a, #a }
X(M_regular),
- X(T_result),
- X(P_value_res_base),
+ X(X_regular),
X(X_except),
- X(M_except)
+ X(T_result),
+ X(M_except),
+ X(P_value_res_base)
#undef X
};
static const pns_lookup_t quot_lut[] = {
#define X(a) { pn_Quot_##a, #a }
X(M),
+ X(X_regular),
X(X_except),
X(res)
#undef X
static const pns_lookup_t divmod_lut[] = {
#define X(a) { pn_DivMod_##a, #a }
X(M),
+ X(X_regular),
X(X_except),
X(res_div),
X(res_mod)
static const pns_lookup_t div_lut[] = {
#define X(a) { pn_Div_##a, #a }
X(M),
+ X(X_regular),
X(X_except),
X(res)
#undef X
static const pns_lookup_t mod_lut[] = {
#define X(a) { pn_Mod_##a, #a }
X(M),
+ X(X_regular),
X(X_except),
X(res)
#undef X
static const pns_lookup_t load_lut[] = {
#define X(a) { pn_Load_##a, #a }
X(M),
+ X(X_regular),
X(X_except),
X(res)
#undef X
static const pns_lookup_t store_lut[] = {
#define X(a) { pn_Store_##a, #a }
X(M),
+ X(X_regular),
X(X_except)
#undef X
};
static const pns_lookup_t alloc_lut[] = {
#define X(a) { pn_Alloc_##a, #a }
X(M),
+ X(X_regular),
X(X_except),
X(res)
#undef X
static const pns_lookup_t copyb_lut[] = {
#define X(a) { pn_CopyB_##a, #a }
X(M),
+ X(X_regular),
X(X_except),
X(M_except)
#undef X
static const pns_lookup_t instof_lut[] = {
#define X(a) { pn_InstOf_##a, #a }
X(M),
+ X(X_regular),
X(X_except),
X(res),
X(M_except),
static const pns_lookup_t bound_lut[] = {
#define X(a) { pn_Bound_##a, #a }
X(M),
+ X(X_regular),
X(X_except),
X(res),
#undef X
#include <math.h>
#include "execution_frequency.h"
-#include "callgraph.h"
static void dump_node_ana_vals(FILE *F, ir_node *n) {
+ (void) F;
+ (void) n;
return;
+#ifdef INTERPROCEDURAL_VIEW
fprintf(F, " %lf*(%2.0lf + %2.0lf) = %2.0lf ",
get_irn_exec_freq(n),
get_irg_method_execution_frequency(get_irn_irg(n)),
pow(5, get_irg_recursion_depth(get_irn_irg(n))),
get_irn_exec_freq(n) * (get_irg_method_execution_frequency(get_irn_irg(n)) + pow(5, get_irg_recursion_depth(get_irn_irg(n))))
);
+#endif
}
fprintf(F, " ");
bad |= dump_node_typeinfo(F, n);
bad |= dump_node_nodeattr(F, n);
- fprintf(F, "%ld:%d", get_irn_node_nr(n), get_irn_idx(n));
+ if(dump_node_idx_labels) {
+ fprintf(F, "%ld:%d", get_irn_node_nr(n), get_irn_idx(n));
+ } else {
+ fprintf(F, "%ld", get_irn_node_nr(n));
+ }
return bad;
}
case iro_Tuple:
print_vcg_color(F, ird_color_yellow);
break;
+ case iro_ASM:
+ print_vcg_color(F, ird_color_darkyellow);
+ break;
default:
PRINT_DEFAULT_NODE_ATTR;
}
fprintf(F, INTER_MEM_EDGE_ATTR);
}
-static void
-print_edge_vcgattr(FILE *F, ir_node *from, int to) {
+/** Print the vcg attributes for the edge from node from to it's to's input */
+static void print_edge_vcgattr(FILE *F, ir_node *from, int to) {
assert(from);
if (dump_edge_vcgattr_hook)
case iro_End:
if (to >= 0) {
if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
- fprintf(F, CF_EDGE_ATTR);
- if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
- fprintf(F, INTER_MEM_EDGE_ATTR);
+ fprintf(F, KEEP_ALIVE_CF_EDGE_ATTR);
+ else
+ fprintf(F, KEEP_ALIVE_DF_EDGE_ATTR);
}
break;
default:
}
}
-/* dump edges to our inputs */
-static void
-dump_ir_data_edges(FILE *F, ir_node *n) {
+/** dump edges to our inputs */
+static void dump_ir_data_edges(FILE *F, ir_node *n) {
int i;
unsigned long visited = get_irn_visited(n);
for (i = 0; i < get_irn_deps(n); ++i) {
ir_node *dep = get_irn_dep(n, i);
- if(dep) {
+ if (dep) {
fprintf(F, "edge: {sourcename: \"");
PRINT_NODEID(n);
fprintf(F, "\" targetname: ");
}
}
+/**
+ * Dump the ir_edges
+ */
+static void
+dump_ir_edges(FILE *F, ir_node *n) {
+ const ir_edge_t *edge;
+ int i = 0;
+
+ foreach_out_edge(n, edge) {
+ ir_node *succ = get_edge_src_irn(edge);
+
+ fprintf(F, "edge: {sourcename: \"");
+ PRINT_NODEID(n);
+ fprintf(F, "\" targetname: \"");
+ PRINT_NODEID(succ);
+ fprintf(F, "\"");
+
+ fprintf(F, " label: \"%d\" ", i);
+ fprintf(F, OUT_EDGE_ATTR);
+ fprintf(F, "}\n");
+ ++i;
+ }
+}
+
+
/** Dumps a node and its edges but not the block edge
*/
-static INLINE void
+static void
dump_node_wo_blockedge(ir_node *n, void *env) {
FILE *F = env;
dump_node(F, n);
dump_whole_node(ir_node *n, void *env) {
FILE *F = env;
dump_node_wo_blockedge(n, env);
- if (!node_floats(n)) dump_ir_block_edge(F, n);
+ if (!node_floats(n))
+ dump_ir_block_edge(F, n);
+ if (dump_new_edges_flag && edges_activated(current_ir_graph))
+ dump_ir_edges(F, n);
}
static void
}
dump_ir_data_edges(F, node);
}
+ if (dump_new_edges_flag && edges_activated(irg))
+ dump_ir_edges(F, node);
}
if (dump_loop_information_flag && (get_irg_loopinfo_state(irg) & loopinfo_valid))
"classname 17: \"interblock Memory\"\n"
"classname 18: \"Exception Control Flow for Interval Analysis\"\n"
"classname 19: \"Postdominators\"\n"
+ "classname 20: \"Keep Alive\"\n"
+ "classname 21: \"Out Edges\"\n"
"infoname 1: \"Attribute\"\n"
"infoname 2: \"Verification errors\"\n"
"infoname 3: \"Debug info\"\n",
name, label, orientation);
- /* don't use all, the range is too whith/black. */
+ /* don't use all, the range is too wide. */
n_colors = 18;
base_color = 105;
fprintf(F,
if (!is_filtered_dump_name(get_entity_ident(get_irg_entity(irg))))
return;
+ if (dump_backedge_information_flag && get_irg_loopinfo_state(irg) != loopinfo_consistent) {
+ construct_backedges(irg);
+ }
+
rem = current_ir_graph;
current_ir_graph = irg;
if (get_interprocedural_view()) suffix1 = "-pure-ip";
* from irg.
*/
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
- ir_node **arr = ird_get_irg_link(get_irp_irg(i));
+ ir_graph *g = get_irp_irg(i);
+ ir_node **arr = ird_get_irg_link(g);
if (arr) {
- dump_graph_from_list(f, get_irp_irg(i));
+ dump_graph_from_list(f, g);
DEL_ARR_F(arr);
}
}
f = vcg_open(irg, suffix, "-cfg");
if (f != NULL) {
ir_graph *rem = current_ir_graph;
+#ifdef INTERPROCEDURAL_VIEW
int ipv = get_interprocedural_view();
+#endif
current_ir_graph = irg;
dump_vcg_header(f, get_irg_dump_name(irg), NULL);
+#ifdef INTERPROCEDURAL_VIEW
if (ipv) {
printf("Warning: dumping cfg not in interprocedural view!\n");
set_interprocedural_view(0);
}
+#endif
/* walk over the blocks in the graph */
irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, f);
dump_node(f, get_irg_bad(irg));
+#ifdef INTERPROCEDURAL_VIEW
set_interprocedural_view(ipv);
+#endif
vcg_close(f);
current_ir_graph = rem;
}
}
}
-
+#if 0
static int weight_overall(int rec, int loop) {
return 2*rec + loop;
}
return base_color + n_colors - color;
}
+/**
+ * Calculate a entity color depending on it's execution propability.
+ */
static int get_entity_color(ir_entity *ent) {
ir_graph *irg = get_entity_irg(ent);
assert(irg);
return my_overall_color;
}
}
+#endif
+#ifdef INTERPROCEDURAL_VIEW
void dump_callgraph(const char *suffix) {
FILE *F = vcg_open_name("Callgraph", suffix);
if (F != NULL) {
int i, rem = edge_label;
+ //int colorize;
edge_label = 1;
dump_vcg_header(F, "Callgraph", NULL);
+ //colorize = get_irp_callgraph_state() == irp_callgraph_and_calltree_consistent;
+
for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
ir_graph *irg = get_irp_irg(i);
ir_entity *ent = get_irg_entity(irg);
- int j, n_callees = get_irg_n_callees(irg);
+ int j;
+ //int n_callees = get_irg_n_callees(irg);
+ int color;
- /* Do not dump runtime system. */
- //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue;
-
- dump_entity_node(F, ent, get_entity_color(ent));
+ //color = colorize ? get_entity_color(ent) : ird_color_green;
+ color = ird_color_green;
+ dump_entity_node(F, ent, color);
for (j = 0; j < n_callees; ++j) {
ir_entity *c = get_irg_entity(get_irg_callee(irg, j));
//if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue;
attr = (be) ?
"label:\"recursion %d\" color:%d" :
"label:\"calls %d\" color:%d";
- print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent));
+ print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), color);
}
}
set_interprocedural_view(rem_view);
}
}
+#endif
/*---------------------------------------------------------------------*/
/* the following routines dumps type information without any ir nodes. */
}
-/*-----------------------------------------------------------------------------*/
-/* Dumps the firm nodes in the loop tree to a graph along with the loop nodes. */
-/*-----------------------------------------------------------------------------*/
+/*----------------------------------------------------------------------------*/
+/* Dumps the firm nodes in the loop tree to a graph along with the loop nodes.*/
+/*----------------------------------------------------------------------------*/
void collect_nodeloop(FILE *F, ir_loop *loop, eset *loopnodes) {
int i, son_number = 0, node_number = 0;