1 /* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
4 * Authors: Martin Trapp, Christian Schaefer
6 * irdump.h: dumping of an intermediate representation graph
18 # include "irnode_t.h"
19 # include "irgraph_t.h"
20 # include "entity_t.h"
22 # include "firm_common_t.h"
27 # include "typewalk.h"
30 # include "type_or_entity.h"
42 /* Attributes of nodes */
43 #define PRINT_DEFAULT_NODE_ATTR
44 #define DEFAULT_NODE_ATTR ""
45 #define DEFAULT_TYPE_ATTRIBUTE ""
47 /* Attributes of edges between Firm nodes */
48 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
49 #define CF_EDGE_ATTR "color: red"
50 #define MEM_EDGE_ATTR "color: blue"
51 #define DOMINATOR_EDGE_ATTR "color: red"
53 #define BACK_EDGE_ATTR "linestyle: dashed "
55 /* Attributes of edges between Firm nodes and type/entity nodes */
56 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
58 /* Attributes of edges in type/entity graphs. */
59 #define TYPE_METH_NODE_ATTR "color: lightyellow"
60 #define TYPE_CLASS_NODE_ATTR "color: green"
61 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
62 #define ENTITY_NODE_ATTR "color: yellow"
63 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
64 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
65 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
66 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
67 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
68 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
69 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
70 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
71 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
72 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
73 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
74 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
75 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
78 #if DEBUG_libfirm && NODEID_AS_LABEL
79 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
80 #define PRINT_TYPEID(X) fprintf(F, "t%ld", get_type_nr(X))
81 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
82 #define PRINT_IRGID(X) fprintf(F,"g%ld", get_irg_graph_nr(X))
84 #define PRINT_NODEID(X) fprintf(F, "%p", X)
85 #define PRINT_TYPEID(X) fprintf(F, "%p", X)
86 #define PRINT_ENTID(X) fprintf(F, "%p", X)
87 #define PRINT_IRGID(X) fprintf(F,"%p",X)
90 #define PRINT_TYPE_TYPE_EDGE(S,T,ATR,...) {fprintf (F, "edge: { sourcename:\""); PRINT_TYPEID(S); fprintf (F, "\" targetname: \""); PRINT_TYPEID(T); fprintf (F,"\" " ATR "}\n",##__VA_ARGS__);}
91 #define PRINT_TYPE_ENT_EDGE(S,T,ATR,...) {fprintf (F, "edge: { sourcename:\""); PRINT_TYPEID(S); fprintf (F, "\" targetname: \""); PRINT_ENTID(T); fprintf (F,"\" " ATR "}\n",##__VA_ARGS__);}
92 #define PRINT_ENT_ENT_EDGE(S,T,ATR,...) {fprintf (F, "edge: { sourcename:\""); PRINT_ENTID(S); fprintf (F, "\" targetname: \""); PRINT_ENTID(T); fprintf (F,"\" " ATR "}\n",##__VA_ARGS__);}
93 #define PRINT_ENT_TYPE_EDGE(S,T,ATR,...) {fprintf (F, "edge: { sourcename:\""); PRINT_ENTID(S); fprintf (F, "\" targetname: \""); PRINT_TYPEID(T); fprintf (F,"\" " ATR "}\n",##__VA_ARGS__);}
94 #define PRINT_NODE_TYPE_EDGE(S,T,ATR,...) {fprintf (F, "edge: { sourcename:\""); PRINT_NODEID(S); fprintf (F, "\" targetname: \""); PRINT_TYPEID(T); fprintf (F,"\" " ATR "}\n",##__VA_ARGS__);}
95 #define PRINT_NODE_ENT_EDGE(S,T,ATR,...) {fprintf (F, "edge: { sourcename:\""); PRINT_NODEID(S); fprintf (F, "\" targetname: \""); PRINT_ENTID(T); fprintf (F,"\" " ATR "}\n",##__VA_ARGS__);}
96 #define PRINT_ENT_NODE_EDGE(S,T,ATR,...) {fprintf (F, "edge: { sourcename:\""); PRINT_ENTID(S); fprintf (F, "\" targetname: \""); PRINT_NODEID(T); fprintf (F,"\" " ATR "}\n",##__VA_ARGS__);}
99 /* A suffix to manipulate the file name. */
100 char *dump_file_suffix = NULL;
102 /* file to dump to */
105 /* A compiler option to turn off edge labels */
107 /* A compiler option to turn off dumping values of constant entities */
108 int const_entities = 1;
109 /* A compiler option to dump the keep alive edges */
110 int dump_keepalive = 0;
111 /* Compiler options to dump analysis information in dump_ir_graph */
112 int dump_out_edge_flag = 0;
113 int dump_dominator_information_flag = 0;
114 int dump_loop_information_flag = 0;
115 int dump_const_local = 0;
117 INLINE bool get_opt_dump_const_local(void) {
118 if (!dump_out_edge_flag && !dump_loop_information_flag)
119 return dump_const_local;
124 /* A global variable to record output of the Bad node. */
125 static int Bad_dumped;
127 static void dump_ir_blocks_nodes (ir_node *n, void *env);
128 static void dump_whole_node(ir_node *n, void* env);
130 /*******************************************************************/
131 /* routines to dump information about a single node */
132 /*******************************************************************/
137 dump_node_opcode (ir_node *n)
143 if (get_irn_opcode(n) == iro_Const) { res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
144 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
148 } else if (get_irn_opcode(n) == iro_SymConst) {
149 if (get_SymConst_kind(n) == linkage_ptr_info) {
150 /* don't use get_SymConst_ptr_info as it mangles the name. */
151 fprintf (F, "SymC %s", id_to_str(get_SymConst_ptrinfo(n)));
153 assert(get_kind(get_SymConst_type(n)) == k_type);
154 assert(get_type_ident(get_SymConst_type(n)));
155 fprintf (F, "SymC %s ", id_to_str(get_type_ident(get_SymConst_type(n))));
156 if (get_SymConst_kind(n) == type_tag)
163 } else if (get_irn_opcode(n) == iro_Filter && !interprocedural_view) {
168 fprintf (F, "%s", id_to_str(get_irn_opident(n)));
173 dump_node_mode (ir_node *n)
175 switch (get_irn_opcode(n)) {
193 fprintf (F, "%s", id_to_str(get_mode_ident(get_irn_mode(n))));
201 dump_node_nodeattr (ir_node *n)
203 switch (get_irn_opcode(n)) {
205 if (false && interprocedural_view) {
206 fprintf (F, "%s", id_to_str(get_entity_ident(get_irg_ent(current_ir_graph))));
210 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
211 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
213 fprintf (F, "%ld", get_Proj_proj(n));
217 fprintf (F, "%ld", get_Filter_proj(n));
220 assert(get_kind(get_Sel_entity(n)) == k_entity);
221 fprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
229 dump_node_vcgattr (ir_node *n)
231 switch (get_irn_opcode(n)) {
238 fprintf (F, "color: blue");
241 fprintf (F, "color: lightyellow");
244 fprintf (F, "color: green");
250 fprintf (F, "color: yellow");
253 PRINT_DEFAULT_NODE_ATTR;
257 static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
258 ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n);
261 ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) {
262 ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos));
263 if (is_ip_cfop(pred)) {
264 ir_graph *irg = get_ip_cfop_irg(pred);
265 if (pmap_find(irgmap, irg) == NULL) return true;
274 bool is_constlike_node(ir_node *n) {
275 ir_op *op = get_irn_op(n);
276 return (op == op_Const || op == op_Bad || op == op_SymConst);
280 static void dump_const_node_local(ir_node *n, pmap *irgmap) {
282 if (!get_opt_dump_const_local()) return;
283 /* Use visited flag to avoid outputting nodes twice.
284 initialize it first. */
285 for (i = 0; i < get_irn_arity(n); i++) {
286 ir_node *con = get_irn_n(n, i);
287 if (is_constlike_node(con)) {
288 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
289 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
292 for (i = 0; i < get_irn_arity(n); i++) {
293 ir_node *con = get_irn_n(n, i);
294 if (is_constlike_node(con) && irn_not_visited(con)) {
295 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
296 mark_irn_visited(con);
297 /* Generate a new name for the node by appending the names of
299 fprintf (F, "node: {title: \""); PRINT_NODEID(n); PRINT_NODEID(con);
300 fprintf(F, "\" label: \"");
301 dump_node_opcode(con);
302 dump_node_mode (con);
304 dump_node_nodeattr(con);
306 fprintf (F, " %ld", get_irn_node_nr(con));
309 dump_node_vcgattr(con);
316 dump_node (ir_node *n, pmap * map) {
317 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
320 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
325 dump_node_nodeattr(n);
327 fprintf (F, " %ld", get_irn_node_nr(n));
330 dump_node_vcgattr(n);
332 dump_const_node_local(n, map);
335 /* dump the edge to the block this node belongs to */
337 dump_ir_block_edge(ir_node *n) {
338 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
339 if (is_no_Block(n)) {
340 fprintf (F, "edge: { sourcename: \"");
342 fprintf (F, "\" targetname: \"");
343 PRINT_NODEID(get_nodes_Block(n));
344 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
348 static void print_edge_vcgattr(ir_node *from, int to) {
351 if (is_backedge(from, to)) fprintf (F, BACK_EDGE_ATTR);
353 switch (get_irn_opcode(from)) {
355 fprintf (F, CF_EDGE_ATTR);
357 case iro_Start: break;
360 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
361 fprintf (F, CF_EDGE_ATTR);
362 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
363 fprintf (F, MEM_EDGE_ATTR);
366 case iro_EndReg: break;
367 case iro_EndExcept: break;
369 case iro_Break: break;
370 case iro_Cond: break;
373 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
375 case iro_Const: break;
376 case iro_SymConst:break;
379 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
381 case iro_CallBegin: break;
384 case iro_Minus: break;
390 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
398 case iro_Shrs: break;
401 case iro_Conv: break;
403 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
409 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
412 fprintf (F, MEM_EDGE_ATTR);
414 case iro_Tuple: break;
417 switch (get_irn_modecode(from)) {
419 fprintf (F, CF_EDGE_ATTR);
422 fprintf (F, MEM_EDGE_ATTR);
428 case iro_Unknown: break;
435 /* dump edges to our inputs */
437 dump_ir_data_edges(ir_node *n) {
438 int i, visited = get_irn_visited(n);
440 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
443 for (i = 0; i < get_irn_arity(n); i++) {
444 ir_node * pred = get_irn_n(n, i);
446 if ((interprocedural_view && get_irn_visited(pred) < visited))
447 continue; /* pred not dumped */
448 if (is_backedge(n, i))
449 fprintf (F, "backedge: {sourcename: \"");
451 fprintf (F, "edge: {sourcename: \"");
453 fprintf (F, "\" targetname: \"");
454 if ((get_opt_dump_const_local()) && is_constlike_node(pred))
458 fprintf (F, " label: \"%d\" ", i);
459 print_edge_vcgattr(n, i);
466 dump_out_edge (ir_node *n, void* env) {
468 for (i = 0; i < get_irn_n_outs(n); i++) {
469 assert(get_irn_out(n, i));
470 fprintf (F, "edge: {sourcename: \"");
472 fprintf (F, "\" targetname: \"");
473 PRINT_NODEID(get_irn_out(n, i));
474 fprintf (F, "\" color: red linestyle: dashed");
480 dump_loop_node_edge (ir_loop *loop, int i) {
482 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", loop);
483 PRINT_NODEID(get_loop_node(loop, i));
484 fprintf (F, "\" color: green");
489 void dump_loops (ir_loop *loop) {
491 /* dump this loop node */
492 fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
493 loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
494 /* dump edges to nodes in loop -- only if it is a real loop */
495 if (get_loop_depth(loop) != 0) {
496 for (i = 0; i < get_loop_n_nodes(loop); i++) {
497 dump_loop_node_edge(loop, i);
500 for (i = 0; i < get_loop_n_sons(loop); i++) {
501 dump_loops(get_loop_son(loop, i));
506 void dump_loop_info(ir_graph *irg) {
507 ir_graph *rem = current_ir_graph;
508 current_ir_graph = irg;
510 if (get_irg_loop(irg))
511 dump_loops(get_irg_loop(irg));
513 current_ir_graph = rem;
517 /* dumps the edges between nodes and their type or entity attributes. */
518 static void dump_node2type_edges (ir_node *n, void *env)
522 switch (get_irn_opcode(n)) {
524 /* @@@ some consts have an entity */
527 if ( (get_SymConst_kind(n) == type_tag)
528 || (get_SymConst_kind(n) == size))
530 PRINT_NODE_TYPE_EDGE(n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
534 PRINT_NODE_ENT_EDGE(n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
537 PRINT_NODE_TYPE_EDGE(n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
540 PRINT_NODE_TYPE_EDGE(n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
543 PRINT_NODE_TYPE_EDGE(n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
551 static void dump_const_expression(ir_node *value) {
552 ir_graph *rem = current_ir_graph;
553 int rem_dump_const_local = dump_const_local;
554 dump_const_local = 0;
555 current_ir_graph = get_const_code_irg();
556 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
557 /* Decrease visited flag so that we walk with the same flag for the next
558 expresssion. This guarantees that we don't dump the same node twice,
559 as for const expressions cse is performed to save memory. */
560 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
561 current_ir_graph = rem;
562 dump_const_local = rem_dump_const_local;
566 static void print_type_info(type *tp) {
567 if (get_type_state(tp) == layout_undefined) {
568 fprintf(F, "state: layout_undefined\n");
570 fprintf(F, "state: layout_fixed,\n");
572 if (get_type_mode(tp))
573 fprintf(F, "mode: %s,\n", id_to_str(get_mode_ident(get_type_mode(tp))));
574 fprintf(F, "size: %dB,\n", get_type_size(tp));
578 static void print_typespecific_info(type *tp) {
579 switch (get_type_tpop_code(tp)) {
582 if(existent == get_class_peculiarity(tp))
583 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
585 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
589 fprintf (F, " " TYPE_METH_NODE_ATTR);
600 case tpo_enumeration:
613 static void print_type_node(type *tp) {
614 fprintf (F, "node: {title: \"");
616 fprintf (F, "\" label: \"%s %s\"", id_to_str(get_type_tpop_nameid(tp)), id_to_str(get_type_ident(tp)));
617 fprintf (F, "info1: \"");
620 print_typespecific_info(tp);
624 void dump_entity_node(entity *ent) {
625 fprintf (F, "node: {title: \"");
627 fprintf (F, "\"" DEFAULT_TYPE_ATTRIBUTE);
628 fprintf (F, "label: ");
629 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , id_to_str(get_entity_ident(ent)));
630 fprintf (F, "\n info1:\"\nallocation: ");
631 switch (get_entity_allocation(ent)) {
632 case dynamic_allocated: fprintf (F, "dynamic allocated"); break;
633 case automatic_allocated: fprintf (F, "automatic allocated"); break;
634 case static_allocated: fprintf (F, "static allocated"); break;
635 case parameter_allocated: fprintf (F, "parameter allocated"); break;
637 fprintf (F, "\nvisibility: ");
638 switch (get_entity_visibility(ent)) {
639 case local: fprintf (F, "local"); break;
640 case external_visible: fprintf (F, "external_visible"); break;
641 case external_allocated: fprintf (F, "external_allocate"); break;
643 fprintf (F, "\nvariability: ");
644 switch (get_entity_variability(ent)) {
645 case uninitialized: fprintf (F, "uninitialized");break;
646 case initialized: fprintf (F, "initialized"); break;
647 case part_constant: fprintf (F, "part_constant");break;
648 case constant: fprintf (F, "constant"); break;
650 fprintf (F, "\nvolatility: ");
651 switch (get_entity_volatility(ent)) {
652 case non_volatile: fprintf (F, "non_volatile"); break;
653 case is_volatile: fprintf (F, "is_volatile"); break;
655 fprintf (F, "\npeculiarity: ");
656 switch (get_entity_peculiarity(ent)) {
657 case description: fprintf (F, "description"); break;
658 case inherited: fprintf (F, "inherited"); break;
659 case existent: fprintf (F, "existent"); break;
661 fprintf(F, "\nname: %s\nld_name: %s", id_to_str(get_entity_ident(ent)), id_to_str(get_entity_ld_ident(ent)));
662 fprintf(F, "\noffset: %d", get_entity_offset(ent));
663 if (is_method_type(get_entity_type(ent))) {
664 if (get_entity_irg(ent)) /* can be null */
665 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
667 { fprintf (F, "\nirg = NULL"); }
669 fprintf(F, "\"\n}\n");
672 /* dumps a type or entity and it's edges. */
674 dump_type_info (type_or_ent *tore, void *env) {
675 int i = 0; /* to shutup gcc */
677 /* dump this type or entity */
679 switch (get_kind(tore)) {
682 entity *ent = (entity *)tore;
685 dump_entity_node(ent);
687 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
688 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
689 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
690 PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
691 if(is_class_type(get_entity_owner(ent))) {
692 for(i = 0; i < get_entity_n_overwrites(ent); i++){
693 PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
696 /* attached subgraphs */
697 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
698 if (is_atomic_entity(ent)) {
699 value = get_atomic_ent_value(ent);
701 PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
703 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"", GET_ENTID(ent));
705 fprintf(F, "\" " ENT_VALUE_EDGE_ATTR "\"}\n");
707 dump_const_expression(value);
710 if (is_compound_entity(ent)) {
711 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
712 value = get_compound_ent_value(ent, i);
714 PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
715 dump_const_expression(value);
716 PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
718 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
719 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
720 get_compound_ent_value_member(ent, i), i);
729 type *tp = (type *)tore;
731 /* and now the edges */
732 switch (get_type_tpop_code(tp)) {
735 for (i=0; i < get_class_n_supertypes(tp); i++) {
736 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
739 for (i=0; i < get_class_n_members(tp); i++) {
740 PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
745 for (i=0; i < get_struct_n_members(tp); i++) {
746 PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
751 for (i = 0; i < get_method_n_params(tp); i++)
753 PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
755 for (i = 0; i < get_method_n_ress(tp); i++)
757 PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
762 for (i = 0; i < get_union_n_members(tp); i++)
764 PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
769 PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
770 PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
772 case tpo_enumeration:
777 PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
785 break; /* case k_type */
788 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
790 } /* switch kind_or_entity */
793 /* dumps a class type node and a superclass edge.
794 If env != null dumps entities of classes and overwrites edges. */
796 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
797 int i = 0; /* to shutup gcc */
799 /* dump this type or entity */
800 switch (get_kind(tore)) {
802 entity *ent = (entity *)tore;
803 if (get_entity_owner(ent) == get_glob_type()) break;
804 if ((env) && is_class_type(get_entity_owner(ent))) {
806 dump_entity_node(ent);
808 PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
809 for(i = 0; i < get_entity_n_overwrites(ent); i++)
811 PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
814 } break; /* case k_entity */
817 type *tp = (type *)tore;
818 if (tp == get_glob_type()) break;
819 switch (get_type_tpop_code(tp)) {
822 /* and now the edges */
823 for (i=0; i < get_class_n_supertypes(tp); i++)
825 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
831 break; /* case k_type */
834 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
836 } /* switch kind_or_entity */
839 /************************************************************************/
840 /* open and close vcg file */
841 /************************************************************************/
843 static void vcg_open (ir_graph *irg, char *suffix) {
844 char *fname; /* filename to put the vcg information in */
851 /** open file for vcg graph */
852 ent = get_irg_ent(irg);
853 id = ent->ld_name ? ent->ld_name : ent->name;
854 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
855 len = id_to_strlen (id);
857 if (dump_file_suffix)
858 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
860 fname = malloc (len + 5 + strlen(suffix));
861 strncpy (fname, cp, len); /* copy the filename */
863 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
864 strcat (fname, suffix); /* append file suffix */
865 strcat (fname, ".vcg"); /* append the .vcg suffix */
866 F = fopen (fname, "w"); /* open file for writing */
868 panic ("cannot open %s for writing (%m)", fname); /* not reached */
872 strcpy(label, "yes");
874 strcpy (label, "no");
879 "graph: { title: \"ir graph of %s\"\n"
880 "display_edge_labels: %s\n"
881 "layoutalgorithm: mindepth\n"
882 "manhattan_edges: yes\n"
884 "orientation: bottom_to_top\n"
885 "classname 1: \"Data\"\n"
886 "classname 2: \"Block\"\n"
887 "classname 3: \"Entity type\""
888 "classname 4: \"Entity owner\""
889 "classname 5: \"Method Param\""
890 "classname 6: \"Method Res\""
891 "classname 7: \"Super\""
892 "classname 8: \"Union\""
893 "classname 9: \"Points-to\""
894 "classname 10: \"Array Element Type\""
895 "classname 11: \"Overwrites\""
896 "classname 12: \"Member\""
899 fprintf (F, "\n"); /* a separator */
902 static void vcg_open_name (const char *name) {
903 char *fname; /* filename to put the vcg information in */
907 /** open file for vcg graph */
909 fname = malloc (len + 5);
910 if (dump_file_suffix)
911 fname = malloc (len + 5 + strlen(dump_file_suffix));
913 fname = malloc (len + 5);
914 strcpy (fname, name); /* copy the filename */
915 if (dump_file_suffix) strcat (fname, dump_file_suffix);
916 strcat (fname, ".vcg"); /* append the .vcg suffix */
917 F = fopen (fname, "w"); /* open file for writing */
919 panic ("cannot open %s for writing (%m)", fname); /* not reached */
923 strcpy(label, "yes");
925 strcpy (label, "no");
930 "graph: { title: \"ir graph of %s\"\n"
931 "display_edge_labels: %s\n"
932 "layoutalgorithm: mindepth\n"
933 "manhattan_edges: yes\n"
935 "orientation: bottom_to_top\n"
936 "classname 1: \"Data\"\n"
937 "classname 2: \"Block\"\n"
938 "classname 3: \"Entity type\"\n"
939 "classname 4: \"Entity owner\"\n"
940 "classname 5: \"Method Param\"\n"
941 "classname 6: \"Method Res\"\n"
942 "classname 7: \"Super\"\n"
943 "classname 8: \"Union\"\n"
944 "classname 9: \"Points-to\"\n"
945 "classname 10: \"Array Element Type\"\n"
946 "classname 11: \"Overwrites\"\n"
947 "classname 12: \"Member\"\n"
950 fprintf (F, "\n"); /* a separator */
955 fprintf (F, "}\n"); /* print footer */
956 fclose (F); /* close vcg file */
959 /************************************************************************/
960 /* routines to dump a graph, blocks as conventional nodes. */
961 /************************************************************************/
963 static int node_floats(ir_node *n) {
964 return ((get_op_pinned(get_irn_op(n)) == floats) &&
965 (get_irg_pinned(current_ir_graph) == floats));
969 dump_whole_node (ir_node *n, void* env) {
971 if (!node_floats(n)) dump_ir_block_edge(n);
972 dump_ir_data_edges(n);
976 dump_ir_graph (ir_graph *irg)
979 rem = current_ir_graph;
980 current_ir_graph = irg;
984 /* walk over the graph */
985 /* dump_whole_node must be called in post visiting predecessors */
986 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
988 /* dump the out edges in a separate walk */
989 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
990 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
995 current_ir_graph = rem;
998 /***********************************************************************/
999 /* the following routines dump the nodes as attached to the blocks. */
1000 /***********************************************************************/
1003 dump_ir_blocks_nodes (ir_node *n, void *env) {
1004 ir_node *block = (ir_node *)env;
1006 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1008 dump_ir_data_edges(n);
1010 if (get_irn_op(n) == op_Bad)
1015 dump_ir_block (ir_node *block, void *env) {
1016 ir_graph *irg = (ir_graph *)env;
1018 if (get_irn_opcode(block) == iro_Block) {
1020 /* This is a block. So dump the vcg information to make a block. */
1021 fprintf(F, "graph: { title: \"");
1022 PRINT_NODEID(block);
1023 fprintf(F, "\" label: \"");
1024 #ifdef DEBUG_libfirm
1025 fprintf (F, "%ld", get_irn_node_nr(block));
1027 fprintf (F, "%s", get_op_name(get_irn_op(block)));
1029 if (exc_normal != get_Block_exc (block))
1030 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1032 fprintf(F, "\" status:clustered color:%s \n",
1033 get_Block_matured (block) ? "yellow" : "red");
1034 /* dump the blocks edges */
1035 dump_ir_data_edges(block);
1037 /* dump the nodes that go into the block */
1038 irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1040 /* Close the vcg information for the block */
1041 fprintf(F, "}\n\n");
1042 dump_const_node_local(block, NULL);
1048 dump_blockless_nodes (ir_node *n, void *env) {
1049 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1051 dump_ir_data_edges(n);
1052 dump_ir_block_edge(n);
1053 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1056 if (node_floats(n)) {
1058 dump_ir_data_edges(n);
1059 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1063 static void dump_ir_block_graph_2 (ir_graph *irg)
1066 /* walk over the blocks in the graph */
1067 irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1069 /* dump all nodes that are not in a Block */
1070 irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1072 /* dump the Bad node */
1074 dump_node(get_irg_bad(irg), NULL);
1078 dump_ir_block_graph (ir_graph *irg)
1081 rem = current_ir_graph;
1082 current_ir_graph = irg;
1086 dump_ir_block_graph_2 (irg);
1088 if (dump_loop_information_flag) dump_loop_info(irg);
1091 current_ir_graph = rem;
1095 /***********************************************************************/
1096 /* the following routines dump a control flow graph */
1097 /***********************************************************************/
1101 dump_block_to_cfg (ir_node *block, void *env) {
1105 if (get_irn_opcode(block) == iro_Block) {
1106 /* This is a block. Dump a node for the block. */
1107 fprintf (F, "node: {title:\""); PRINT_NODEID(block);
1108 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block))); PRINT_NODEID(block);
1110 if (exc_normal != get_Block_exc (block))
1111 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1114 if (dump_dominator_information_flag)
1115 fprintf(F, "info1:\"dom depth %d\"", get_Block_dom_depth(block));
1117 /* Dump the edges */
1118 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1119 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1120 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1121 fprintf (F, "edge: { sourcename: \"");
1122 PRINT_NODEID(block);
1123 fprintf (F, "\" targetname: \"");
1125 fprintf (F, "\" }\n");
1128 /* Dump dominator edge */
1129 if (dump_dominator_information_flag && get_Block_idom(block)) {
1130 pred = get_Block_idom(block);
1131 fprintf (F, "edge: { sourcename: \"");
1132 PRINT_NODEID(block);
1133 fprintf (F, "\" targetname: \"");
1135 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1141 dump_cfg (ir_graph *irg)
1143 ir_graph *rem = current_ir_graph;
1144 int ddif = dump_dominator_information_flag;
1145 current_ir_graph = irg;
1146 vcg_open (irg, "-cfg");
1148 if (get_irg_dom_state(irg) != dom_consistent)
1149 dump_dominator_information_flag = 0;
1151 /* walk over the blocks in the graph */
1152 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1153 dump_node (get_irg_bad(irg), NULL);
1155 dump_dominator_information_flag = ddif;
1157 current_ir_graph = rem;
1161 /***********************************************************************/
1162 /* the following routine dumps all type information reachable from an */
1164 /***********************************************************************/
1168 dump_type_graph (ir_graph *irg)
1171 rem = current_ir_graph;
1172 current_ir_graph = irg;
1174 vcg_open (irg, "-type");
1176 /* walk over the blocks in the graph */
1177 type_walk_irg(irg, dump_type_info, NULL, NULL);
1178 /* The walker for the const code can be called several times for the
1179 same (sub) experssion. So that no nodes are dumped several times
1180 we decrease the visited flag of the corresponding graph after each
1181 walk. So now increase it finally. */
1182 inc_irg_visited(get_const_code_irg());
1185 current_ir_graph = rem;
1188 /***********************************************************************/
1189 /* the following routine dumps all type information */
1190 /***********************************************************************/
1194 dump_all_types (void)
1196 vcg_open_name ("All_types");
1197 type_walk(dump_type_info, NULL, NULL);
1198 inc_irg_visited(get_const_code_irg());
1203 dump_class_hierarchy (bool entities)
1205 vcg_open_name ("class_hierarchy");
1207 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1209 type_walk(dump_class_hierarchy_node, NULL, NULL);
1213 /***********************************************************************/
1214 /* dumps a graph with type information */
1215 /***********************************************************************/
1219 dump_ir_graph_w_types (ir_graph *irg)
1222 rem = current_ir_graph;
1223 current_ir_graph = irg;
1225 vcg_open (irg, "-all");
1227 /* dump common ir graph */
1228 irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1229 /* dump type info */
1230 type_walk_irg(irg, dump_type_info, NULL, NULL);
1231 inc_irg_visited(get_const_code_irg());
1232 /* dump edges from graph to type info */
1233 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1236 current_ir_graph = rem;
1240 dump_ir_block_graph_w_types (ir_graph *irg)
1243 rem = current_ir_graph;
1244 current_ir_graph = irg;
1246 vcg_open (irg, "-all");
1248 /* dump common blocked ir graph */
1249 dump_ir_block_graph_2(irg);
1250 /* dump type info */
1251 type_walk_irg(irg, dump_type_info, NULL, NULL);
1252 inc_irg_visited(get_const_code_irg());
1253 /* dump edges from graph to type info */
1254 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1257 current_ir_graph = rem;
1260 /***********************************************************************/
1261 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1263 /* dump_ir_block_graph */
1265 /* dump_type_graph */
1266 /* dump_ir_graph_w_types */
1267 /***********************************************************************/
1268 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1270 for (i=0; i < get_irp_n_irgs(); i++) {
1271 dump_graph(get_irp_irg(i));
1276 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1277 abort with a segmentation fault. */
1278 void turn_off_edge_labels(void) {
1283 void dump_consts_local(bool b) {
1284 dump_const_local = b;
1287 void turn_off_constant_entity_values(void) {
1291 void dump_keepalive_edges(bool b) {
1295 bool get_opt_dump_keepalive_edges(void) {
1296 return dump_keepalive;
1299 void dump_out_edges(void) {
1300 dump_out_edge_flag = 1;
1303 void dump_dominator_information(void) {
1304 dump_dominator_information_flag = 1;
1307 void dump_loop_information(void) {
1308 dump_loop_information_flag = 1;
1311 void dont_dump_loop_information(void) {
1312 dump_loop_information_flag = 0;
1315 static void clear_link(ir_node * node, void * env) {
1316 set_irn_link(node, NULL);
1319 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1321 || node_floats(node)
1322 || get_irn_op(node) == op_Bad
1323 || get_irn_op(node) == op_Unknown) {
1324 pmap_entry * entry = pmap_find(map, current_ir_graph);
1326 ARR_APP1(ir_node *, (ir_node **) entry->value, node);
1328 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1330 pmap_insert(map, current_ir_graph, arr);
1333 ir_node * block = get_nodes_Block(node);
1334 set_irn_link(node, get_irn_link(block));
1335 set_irn_link(block, node);
1340 static void dump_cg_ir_block(ir_node * block, void * env) {
1342 pmap *irgmap = (pmap *)env;
1343 assert(is_Block(block));
1344 fprintf(F, "graph: { title: \"");
1345 PRINT_NODEID(block);
1346 fprintf(F, "\" label: \"");
1347 #ifdef DEBUG_libfirm
1348 fprintf (F, "%ld", get_irn_node_nr(block));
1350 fprintf (F, "%s", get_op_name(get_irn_op(block)));
1352 if (exc_normal != get_Block_exc(block)) {
1353 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1356 fprintf(F, "\" status:clustered color:%s \n",
1357 get_Block_matured(block) ? "yellow" : "red");
1359 /* dump the blocks edges */
1360 dump_ir_data_edges(block);
1362 /* dump the nodes that go into the block */
1363 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1364 dump_node(node, irgmap);
1365 dump_ir_data_edges(node);
1368 /* Close the vcg information for the block */
1369 fprintf(F, "}\n\n");
1372 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1375 fprintf(F, "graph: { title: \"%p\" label: \"%s\" status:clustered color:white \n",
1376 irg, id_to_str(get_entity_ident(get_irg_ent(irg))));
1378 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1379 ir_node * node = arr[i];
1380 if (is_Block(node)) {
1381 /* Dumps the block and all the nodes in the block , which are to
1382 be found in Block->link. */
1383 dump_cg_ir_block(node, irgmap);
1385 /* Nodes that are not in a Block. */
1386 dump_node(node, NULL);
1387 dump_ir_data_edges(node);
1390 /* Close the vcg information for the irg */
1391 fprintf(F, "}\n\n");
1394 /* dump interprocedural graph with surrounding methods */
1395 void dump_cg_block_graph(ir_graph * irg) {
1396 pmap * map = pmap_create();
1397 pmap * map2 = pmap_create();
1402 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1403 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1404 pmap_insert(map2, entry->key, entry->value);
1405 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1406 d_cg_block_graph(entry->key, entry->value, map2);
1407 DEL_ARR_F(entry->value);
1413 if (dump_loop_information_flag) dump_loop_info(irg);
1417 static void collect_node(ir_node * node, void *env) {
1419 || node_floats(node)
1420 || get_irn_op(node) == op_Bad
1421 || get_irn_op(node) == op_Unknown) {
1422 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1423 ARR_APP1(ir_node *, arr, node);
1424 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1426 ir_node * block = get_nodes_Block(node);
1427 set_irn_link(node, get_irn_link(block));
1428 set_irn_link(block, node);
1432 /* Links all nodes that have the block field set in the link field of
1433 the block. Adds all blocks and nodes not associated with a block
1434 in a array in irg->link. */
1435 static void collect_nodes(void) {
1437 for (i = 0; i < get_irp_n_irgs(); i++)
1438 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1439 cg_walk(clear_link, collect_node, NULL);
1442 static void dump_graphs(void) {
1444 for (i = 0; i < get_irp_n_irgs(); i++) {
1445 current_ir_graph = get_irp_irg(i);
1446 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1450 /* Dump all irgs in interprocedural view to a single file. */
1451 void dump_all_cg_block_graph(void) {
1453 int rem_view = interprocedural_view;
1454 interprocedural_view = 1;
1455 vcg_open_name ("All_graphs");
1460 if (dump_loop_information_flag)
1461 for (i = 0; i < get_irp_n_irgs(); i++)
1462 dump_loop_info(get_irp_irg(i));
1465 interprocedural_view = rem_view;
1468 /* dump interprocedural block graph with surrounding methods */
1469 void dump_cg_graph(ir_graph * irg) {
1470 pmap * map = pmap_create();
1471 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1475 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1476 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1477 pmap_insert(map2, entry->key, entry->value);
1478 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1479 ir_node ** arr = entry->value;
1481 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1483 fprintf(F, "graph: { title: \"%s\" label: \"%s\" status:clustered color:white \n",
1484 id_to_str(irg_ident), id_to_str(irg_ident));
1486 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1487 ir_node * node = arr[i];
1488 dump_node(node, map2);
1489 dump_ir_data_edges(node);
1490 if (is_Block(node)) {
1491 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1492 dump_node(node, map2);
1493 dump_ir_block_edge(node);
1494 dump_ir_data_edges(node);
1501 /* Close the vcg information for the irg */
1502 fprintf(F, "}\n\n");