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))
83 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
86 #define PRINT_NODEID(X) fprintf(F, "\"n%p\"", (void*) X)
87 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *) X)
88 #define PRINT_ENTID(X) fprintf(F, "\"e%p\"", (void*) X)
89 #define PRINT_IRGID(X) fprintf(F, "g%p",(void*) X)
90 #define PRINT_CONSTID(X,Y) fprintf(F, "\"%p%p\"", (void*) X, (void*) Y)
93 #define PRINT_TYPE_TYPE_EDGE(S,T,...){fprintf (F, "edge: { sourcename: "); PRINT_TYPEID(S); fprintf (F, " targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
94 #define PRINT_TYPE_ENT_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: "); PRINT_TYPEID(S); fprintf (F, " targetname: "); PRINT_ENTID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
95 #define PRINT_ENT_ENT_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: "); PRINT_ENTID(S); fprintf (F, " targetname: "); PRINT_ENTID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
96 #define PRINT_ENT_TYPE_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: "); PRINT_ENTID(S); fprintf (F, " targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
97 #define PRINT_NODE_TYPE_EDGE(S,T,...){fprintf (F, "edge: { sourcename: "); PRINT_NODEID(S); fprintf (F, " targetname: "); PRINT_TYPEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
98 #define PRINT_NODE_ENT_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: "); PRINT_NODEID(S); fprintf (F, " targetname: "); PRINT_ENTID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
99 #define PRINT_ENT_NODE_EDGE(S,T,...) {fprintf (F, "edge: { sourcename: "); PRINT_ENTID(S); fprintf (F, " targetname: "); PRINT_NODEID(T); fprintf (F, ##__VA_ARGS__); fprintf(F,"}\n"); }
102 /* A suffix to manipulate the file name. */
103 char *dump_file_suffix = NULL;
105 /* file to dump to */
108 /* A compiler option to turn off edge labels */
110 /* A compiler option to turn off dumping values of constant entities */
111 int const_entities = 1;
112 /* A compiler option to dump the keep alive edges */
113 int dump_keepalive = 0;
114 /* Compiler options to dump analysis information in dump_ir_graph */
115 int dump_out_edge_flag = 0;
116 int dump_dominator_information_flag = 0;
117 int dump_loop_information_flag = 0;
118 int dump_const_local = 0;
120 INLINE bool get_opt_dump_const_local(void) {
121 if (!dump_out_edge_flag && !dump_loop_information_flag)
122 return dump_const_local;
127 /* A global variable to record output of the Bad node. */
128 static int Bad_dumped;
130 static void dump_ir_blocks_nodes (ir_node *n, void *env);
131 static void dump_whole_node(ir_node *n, void* env);
133 /*******************************************************************/
134 /* routines to dump information about a single node */
135 /*******************************************************************/
140 dump_node_opcode (ir_node *n)
146 if (get_irn_opcode(n) == iro_Const) { res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
147 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
151 } else if (get_irn_opcode(n) == iro_SymConst) {
152 if (get_SymConst_kind(n) == linkage_ptr_info) {
153 /* don't use get_SymConst_ptr_info as it mangles the name. */
154 fprintf (F, "SymC %s", id_to_str(get_SymConst_ptrinfo(n)));
156 assert(get_kind(get_SymConst_type(n)) == k_type);
157 assert(get_type_ident(get_SymConst_type(n)));
158 fprintf (F, "SymC %s ", id_to_str(get_type_ident(get_SymConst_type(n))));
159 if (get_SymConst_kind(n) == type_tag)
166 } else if (get_irn_opcode(n) == iro_Filter && !interprocedural_view) {
171 fprintf (F, "%s", id_to_str(get_irn_opident(n)));
176 dump_node_mode (ir_node *n)
178 switch (get_irn_opcode(n)) {
196 fprintf (F, "%s", id_to_str(get_mode_ident(get_irn_mode(n))));
204 dump_node_nodeattr (ir_node *n)
206 switch (get_irn_opcode(n)) {
208 if (false && interprocedural_view) {
209 fprintf (F, "%s", id_to_str(get_entity_ident(get_irg_ent(current_ir_graph))));
213 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
214 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
216 fprintf (F, "%ld", get_Proj_proj(n));
220 fprintf (F, "%ld", get_Filter_proj(n));
223 assert(get_kind(get_Sel_entity(n)) == k_entity);
224 fprintf (F, "%s", id_to_str(get_entity_ident(get_Sel_entity(n))));
232 dump_node_vcgattr (ir_node *n)
234 switch (get_irn_opcode(n)) {
241 fprintf (F, "color: blue");
244 fprintf (F, "color: lightyellow");
247 fprintf (F, "color: green");
253 fprintf (F, "color: yellow");
256 PRINT_DEFAULT_NODE_ATTR;
260 static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
261 ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n);
264 ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) {
265 ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos));
266 if (is_ip_cfop(pred)) {
267 ir_graph *irg = get_ip_cfop_irg(pred);
268 if (pmap_find(irgmap, irg) == NULL) return true;
277 bool is_constlike_node(ir_node *n) {
278 ir_op *op = get_irn_op(n);
279 return (op == op_Const || op == op_Bad || op == op_SymConst);
283 static void dump_const_node_local(ir_node *n, pmap *irgmap) {
285 if (!get_opt_dump_const_local()) return;
286 /* Use visited flag to avoid outputting nodes twice.
287 initialize it first. */
288 for (i = 0; i < get_irn_arity(n); i++) {
289 ir_node *con = get_irn_n(n, i);
290 if (is_constlike_node(con)) {
291 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
292 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
295 for (i = 0; i < get_irn_arity(n); i++) {
296 ir_node *con = get_irn_n(n, i);
297 if (is_constlike_node(con) && irn_not_visited(con)) {
298 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
299 mark_irn_visited(con);
300 /* Generate a new name for the node by appending the names of
302 fprintf (F, "node: {title: "); PRINT_CONSTID(n,con);
303 fprintf(F, " label: \"");
304 dump_node_opcode(con);
305 dump_node_mode (con);
307 dump_node_nodeattr(con);
309 fprintf (F, " %ld", get_irn_node_nr(con));
312 dump_node_vcgattr(con);
319 dump_node (ir_node *n, pmap * map) {
320 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
323 fprintf (F, "node: {title: "); PRINT_NODEID(n); fprintf(F, " label: \"");
328 dump_node_nodeattr(n);
330 fprintf (F, " %ld", get_irn_node_nr(n));
333 dump_node_vcgattr(n);
335 dump_const_node_local(n, map);
338 /* dump the edge to the block this node belongs to */
340 dump_ir_block_edge(ir_node *n) {
341 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
342 if (is_no_Block(n)) {
343 fprintf (F, "edge: { sourcename: ");
345 fprintf (F, " targetname: ");
346 PRINT_NODEID(get_nodes_Block(n));
347 fprintf (F, " " BLOCK_EDGE_ATTR "}\n");
351 static void print_edge_vcgattr(ir_node *from, int to) {
354 if (is_backedge(from, to)) fprintf (F, BACK_EDGE_ATTR);
356 switch (get_irn_opcode(from)) {
358 fprintf (F, CF_EDGE_ATTR);
360 case iro_Start: break;
363 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
364 fprintf (F, CF_EDGE_ATTR);
365 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
366 fprintf (F, MEM_EDGE_ATTR);
369 case iro_EndReg: break;
370 case iro_EndExcept: break;
372 case iro_Break: break;
373 case iro_Cond: break;
376 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
378 case iro_Const: break;
379 case iro_SymConst:break;
382 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
384 case iro_CallBegin: break;
387 case iro_Minus: break;
393 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
401 case iro_Shrs: break;
404 case iro_Conv: break;
406 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
412 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
415 fprintf (F, MEM_EDGE_ATTR);
417 case iro_Tuple: break;
420 switch (get_irn_modecode(from)) {
422 fprintf (F, CF_EDGE_ATTR);
425 fprintf (F, MEM_EDGE_ATTR);
431 case iro_Unknown: break;
438 /* dump edges to our inputs */
440 dump_ir_data_edges(ir_node *n) {
441 int i, visited = get_irn_visited(n);
443 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
446 for (i = 0; i < get_irn_arity(n); i++) {
447 ir_node * pred = get_irn_n(n, i);
449 if ((interprocedural_view && get_irn_visited(pred) < visited))
450 continue; /* pred not dumped */
451 if (is_backedge(n, i))
452 fprintf (F, "backedge: {sourcename: ");
454 fprintf (F, "edge: {sourcename: ");
456 fprintf (F, " targetname: ");
457 if ((get_opt_dump_const_local()) && is_constlike_node(pred))
459 PRINT_CONSTID(n,pred);
465 fprintf (F, " label: \"%d\" ", i);
466 print_edge_vcgattr(n, i);
473 dump_out_edge (ir_node *n, void* env) {
475 for (i = 0; i < get_irn_n_outs(n); i++) {
476 assert(get_irn_out(n, i));
477 fprintf (F, "edge: {sourcename: ");
479 fprintf (F, " targetname: ");
480 PRINT_NODEID(get_irn_out(n, i));
481 fprintf (F, " color: red linestyle: dashed");
487 dump_loop_node_edge (ir_loop *loop, int i) {
489 fprintf (F, "edge: {sourcename: \"%p\" targetname: ", (void*) loop);
490 PRINT_NODEID(get_loop_node(loop, i));
491 fprintf (F, " color: green");
496 void dump_loops (ir_loop *loop) {
498 /* dump this loop node */
499 fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
500 (void*)loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
501 /* dump edges to nodes in loop -- only if it is a real loop */
502 if (get_loop_depth(loop) != 0) {
503 for (i = 0; i < get_loop_n_nodes(loop); i++) {
504 dump_loop_node_edge(loop, i);
507 for (i = 0; i < get_loop_n_sons(loop); i++) {
508 dump_loops(get_loop_son(loop, i));
513 void dump_loop_info(ir_graph *irg) {
514 ir_graph *rem = current_ir_graph;
515 current_ir_graph = irg;
517 if (get_irg_loop(irg))
518 dump_loops(get_irg_loop(irg));
520 current_ir_graph = rem;
524 /* dumps the edges between nodes and their type or entity attributes. */
525 static void dump_node2type_edges (ir_node *n, void *env)
529 switch (get_irn_opcode(n)) {
531 /* @@@ some consts have an entity */
534 if ( (get_SymConst_kind(n) == type_tag)
535 || (get_SymConst_kind(n) == size))
537 PRINT_NODE_TYPE_EDGE(n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
541 PRINT_NODE_ENT_EDGE(n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
544 PRINT_NODE_TYPE_EDGE(n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
547 PRINT_NODE_TYPE_EDGE(n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
550 PRINT_NODE_TYPE_EDGE(n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
558 static void dump_const_expression(ir_node *value) {
559 ir_graph *rem = current_ir_graph;
560 int rem_dump_const_local = dump_const_local;
561 dump_const_local = 0;
562 current_ir_graph = get_const_code_irg();
563 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
564 /* Decrease visited flag so that we walk with the same flag for the next
565 expresssion. This guarantees that we don't dump the same node twice,
566 as for const expressions cse is performed to save memory. */
567 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
568 current_ir_graph = rem;
569 dump_const_local = rem_dump_const_local;
573 static void print_type_info(type *tp) {
574 if (get_type_state(tp) == layout_undefined) {
575 fprintf(F, "state: layout_undefined\n");
577 fprintf(F, "state: layout_fixed,\n");
579 if (get_type_mode(tp))
580 fprintf(F, "mode: %s,\n", id_to_str(get_mode_ident(get_type_mode(tp))));
581 fprintf(F, "size: %dB,\n", get_type_size(tp));
585 static void print_typespecific_info(type *tp) {
586 switch (get_type_tpop_code(tp)) {
589 if(existent == get_class_peculiarity(tp))
590 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
592 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
596 fprintf (F, " " TYPE_METH_NODE_ATTR);
607 case tpo_enumeration:
620 static void print_type_node(type *tp) {
621 fprintf (F, "node: {title: ");
623 fprintf (F, " label: \"%s %s\"", id_to_str(get_type_tpop_nameid(tp)), id_to_str(get_type_ident(tp)));
624 fprintf (F, " info1: \"");
627 print_typespecific_info(tp);
631 void dump_entity_node(entity *ent) {
632 fprintf (F, "node: {title: ");
634 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
635 fprintf (F, "label: ");
636 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , id_to_str(get_entity_ident(ent)));
637 fprintf (F, "\n info1:\"\nallocation: ");
638 switch (get_entity_allocation(ent)) {
639 case dynamic_allocated: fprintf (F, "dynamic allocated"); break;
640 case automatic_allocated: fprintf (F, "automatic allocated"); break;
641 case static_allocated: fprintf (F, "static allocated"); break;
642 case parameter_allocated: fprintf (F, "parameter allocated"); break;
644 fprintf (F, "\nvisibility: ");
645 switch (get_entity_visibility(ent)) {
646 case local: fprintf (F, "local"); break;
647 case external_visible: fprintf (F, "external_visible"); break;
648 case external_allocated: fprintf (F, "external_allocate"); break;
650 fprintf (F, "\nvariability: ");
651 switch (get_entity_variability(ent)) {
652 case uninitialized: fprintf (F, "uninitialized");break;
653 case initialized: fprintf (F, "initialized"); break;
654 case part_constant: fprintf (F, "part_constant");break;
655 case constant: fprintf (F, "constant"); break;
657 fprintf (F, "\nvolatility: ");
658 switch (get_entity_volatility(ent)) {
659 case non_volatile: fprintf (F, "non_volatile"); break;
660 case is_volatile: fprintf (F, "is_volatile"); break;
662 fprintf (F, "\npeculiarity: ");
663 switch (get_entity_peculiarity(ent)) {
664 case description: fprintf (F, "description"); break;
665 case inherited: fprintf (F, "inherited"); break;
666 case existent: fprintf (F, "existent"); break;
668 fprintf(F, "\nname: %s\nld_name: %s",
669 id_to_str(get_entity_ident(ent)),
670 id_to_str(get_entity_ld_ident(ent)));
671 fprintf(F, "\noffset: %d", get_entity_offset(ent));
672 if (is_method_type(get_entity_type(ent))) {
673 if (get_entity_irg(ent)) /* can be null */
674 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
676 { fprintf (F, "\nirg = NULL"); }
678 fprintf(F, "\"\n}\n");
681 /* dumps a type or entity and it's edges. */
683 dump_type_info (type_or_ent *tore, void *env) {
684 int i = 0; /* to shutup gcc */
686 /* dump this type or entity */
688 switch (get_kind(tore)) {
691 entity *ent = (entity *)tore;
694 dump_entity_node(ent);
696 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
697 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
698 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
699 PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
700 if(is_class_type(get_entity_owner(ent))) {
701 for(i = 0; i < get_entity_n_overwrites(ent); i++){
702 PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
705 /* attached subgraphs */
706 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
707 if (is_atomic_entity(ent)) {
708 value = get_atomic_ent_value(ent);
710 PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
712 fprintf (F, "edge: { sourcename: \"%p\" targetname: ", GET_ENTID(ent));
714 fprintf(F, " " ENT_VALUE_EDGE_ATTR "\"}\n");
716 dump_const_expression(value);
719 if (is_compound_entity(ent)) {
720 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
721 value = get_compound_ent_value(ent, i);
723 PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
724 dump_const_expression(value);
725 PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
727 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
728 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
729 get_compound_ent_value_member(ent, i), i);
738 type *tp = (type *)tore;
740 /* and now the edges */
741 switch (get_type_tpop_code(tp)) {
744 for (i=0; i < get_class_n_supertypes(tp); i++) {
745 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
748 for (i=0; i < get_class_n_members(tp); i++) {
749 PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
754 for (i=0; i < get_struct_n_members(tp); i++) {
755 PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
760 for (i = 0; i < get_method_n_params(tp); i++)
762 PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
764 for (i = 0; i < get_method_n_ress(tp); i++)
766 PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
771 for (i = 0; i < get_union_n_members(tp); i++)
773 PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
778 PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
779 PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
781 case tpo_enumeration:
786 PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
794 break; /* case k_type */
797 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
799 } /* switch kind_or_entity */
802 /* dumps a class type node and a superclass edge.
803 If env != null dumps entities of classes and overwrites edges. */
805 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
806 int i = 0; /* to shutup gcc */
808 /* dump this type or entity */
809 switch (get_kind(tore)) {
811 entity *ent = (entity *)tore;
812 if (get_entity_owner(ent) == get_glob_type()) break;
813 if ((env) && is_class_type(get_entity_owner(ent))) {
815 dump_entity_node(ent);
817 PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
818 for(i = 0; i < get_entity_n_overwrites(ent); i++)
820 PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
823 } break; /* case k_entity */
826 type *tp = (type *)tore;
827 if (tp == get_glob_type()) break;
828 switch (get_type_tpop_code(tp)) {
831 /* and now the edges */
832 for (i=0; i < get_class_n_supertypes(tp); i++)
834 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
840 break; /* case k_type */
843 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
845 } /* switch kind_or_entity */
848 /************************************************************************/
849 /* open and close vcg file */
850 /************************************************************************/
852 static void vcg_open (ir_graph *irg, char *suffix) {
853 char *fname; /* filename to put the vcg information in */
860 /** open file for vcg graph */
861 ent = get_irg_ent(irg);
862 id = ent->ld_name ? ent->ld_name : ent->name;
863 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
864 len = id_to_strlen (id);
866 if (dump_file_suffix)
867 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
869 fname = malloc (len + 5 + strlen(suffix));
870 strncpy (fname, cp, len); /* copy the filename */
872 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
873 strcat (fname, suffix); /* append file suffix */
874 strcat (fname, ".vcg"); /* append the .vcg suffix */
875 F = fopen (fname, "w"); /* open file for writing */
877 panic ("cannot open %s for writing (%m)", fname); /* not reached */
881 strcpy(label, "yes");
883 strcpy (label, "no");
888 "graph: { title: \"ir graph of %s\"\n"
889 "display_edge_labels: %s\n"
890 "layoutalgorithm: mindepth\n"
891 "manhattan_edges: yes\n"
893 "orientation: bottom_to_top\n"
894 "classname 1: \"Data\"\n"
895 "classname 2: \"Block\"\n"
896 "classname 3: \"Entity type\""
897 "classname 4: \"Entity owner\""
898 "classname 5: \"Method Param\""
899 "classname 6: \"Method Res\""
900 "classname 7: \"Super\""
901 "classname 8: \"Union\""
902 "classname 9: \"Points-to\""
903 "classname 10: \"Array Element Type\""
904 "classname 11: \"Overwrites\""
905 "classname 12: \"Member\""
908 fprintf (F, "\n"); /* a separator */
911 static void vcg_open_name (const char *name) {
912 char *fname; /* filename to put the vcg information in */
916 /** open file for vcg graph */
918 fname = malloc (len + 5);
919 if (dump_file_suffix)
920 fname = malloc (len + 5 + strlen(dump_file_suffix));
922 fname = malloc (len + 5);
923 strcpy (fname, name); /* copy the filename */
924 if (dump_file_suffix) strcat (fname, dump_file_suffix);
925 strcat (fname, ".vcg"); /* append the .vcg suffix */
926 F = fopen (fname, "w"); /* open file for writing */
928 panic ("cannot open %s for writing (%m)", fname); /* not reached */
932 strcpy(label, "yes");
934 strcpy (label, "no");
939 "graph: { title: \"ir graph of %s\"\n"
940 "display_edge_labels: %s\n"
941 "layoutalgorithm: mindepth\n"
942 "manhattan_edges: yes\n"
944 "orientation: bottom_to_top\n"
945 "classname 1: \"Data\"\n"
946 "classname 2: \"Block\"\n"
947 "classname 3: \"Entity type\"\n"
948 "classname 4: \"Entity owner\"\n"
949 "classname 5: \"Method Param\"\n"
950 "classname 6: \"Method Res\"\n"
951 "classname 7: \"Super\"\n"
952 "classname 8: \"Union\"\n"
953 "classname 9: \"Points-to\"\n"
954 "classname 10: \"Array Element Type\"\n"
955 "classname 11: \"Overwrites\"\n"
956 "classname 12: \"Member\"\n"
959 fprintf (F, "\n"); /* a separator */
964 fprintf (F, "}\n"); /* print footer */
965 fclose (F); /* close vcg file */
968 /************************************************************************/
969 /* routines to dump a graph, blocks as conventional nodes. */
970 /************************************************************************/
972 static int node_floats(ir_node *n) {
973 return ((get_op_pinned(get_irn_op(n)) == floats) &&
974 (get_irg_pinned(current_ir_graph) == floats));
978 dump_whole_node (ir_node *n, void* env) {
980 if (!node_floats(n)) dump_ir_block_edge(n);
981 dump_ir_data_edges(n);
985 dump_ir_graph (ir_graph *irg)
988 rem = current_ir_graph;
989 current_ir_graph = irg;
993 /* walk over the graph */
994 /* dump_whole_node must be called in post visiting predecessors */
995 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
997 /* dump the out edges in a separate walk */
998 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
999 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1004 current_ir_graph = rem;
1007 /***********************************************************************/
1008 /* the following routines dump the nodes as attached to the blocks. */
1009 /***********************************************************************/
1012 dump_ir_blocks_nodes (ir_node *n, void *env) {
1013 ir_node *block = (ir_node *)env;
1015 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1017 dump_ir_data_edges(n);
1019 if (get_irn_op(n) == op_Bad)
1024 dump_ir_block (ir_node *block, void *env) {
1025 ir_graph *irg = (ir_graph *)env;
1027 if (get_irn_opcode(block) == iro_Block) {
1029 /* This is a block. So dump the vcg information to make a block. */
1030 fprintf(F, "graph: { title: ");
1031 PRINT_NODEID(block);
1032 fprintf(F, " label: \"");
1033 #ifdef DEBUG_libfirm
1034 fprintf (F, "%ld", get_irn_node_nr(block));
1036 fprintf (F, "%s", get_op_name(get_irn_op(block)));
1038 if (exc_normal != get_Block_exc (block))
1039 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1041 fprintf(F, "\" status:clustered color:%s \n",
1042 get_Block_matured (block) ? "yellow" : "red");
1043 /* dump the blocks edges */
1044 dump_ir_data_edges(block);
1046 /* dump the nodes that go into the block */
1047 irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1049 /* Close the vcg information for the block */
1050 fprintf(F, "}\n\n");
1051 dump_const_node_local(block, NULL);
1057 dump_blockless_nodes (ir_node *n, void *env) {
1058 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1060 dump_ir_data_edges(n);
1061 dump_ir_block_edge(n);
1062 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1065 if (node_floats(n)) {
1067 dump_ir_data_edges(n);
1068 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1072 static void dump_ir_block_graph_2 (ir_graph *irg)
1075 /* walk over the blocks in the graph */
1076 irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1078 /* dump all nodes that are not in a Block */
1079 irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1081 /* dump the Bad node */
1083 dump_node(get_irg_bad(irg), NULL);
1087 dump_ir_block_graph (ir_graph *irg)
1090 rem = current_ir_graph;
1091 current_ir_graph = irg;
1095 dump_ir_block_graph_2 (irg);
1097 if (dump_loop_information_flag) dump_loop_info(irg);
1100 current_ir_graph = rem;
1104 /***********************************************************************/
1105 /* the following routines dump a control flow graph */
1106 /***********************************************************************/
1110 dump_block_to_cfg (ir_node *block, void *env) {
1114 if (get_irn_opcode(block) == iro_Block) {
1115 /* This is a block. Dump a node for the block. */
1116 fprintf (F, "node: {title:"); PRINT_NODEID(block);
1117 fprintf (F, " label: \"%s ", get_op_name(get_irn_op(block)));
1118 #ifdef DEBUG_libfirm
1119 fprintf (F, "%ld", get_irn_node_nr(block));
1121 fprintf (F, "%p", (void*) block);
1124 if (exc_normal != get_Block_exc (block))
1125 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1128 if (dump_dominator_information_flag)
1129 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1131 /* Dump the edges */
1132 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1133 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1134 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1135 fprintf (F, "edge: { sourcename: ");
1136 PRINT_NODEID(block);
1137 fprintf (F, " targetname: ");
1139 fprintf (F, " }\n");
1142 /* Dump dominator edge */
1143 if (dump_dominator_information_flag && get_Block_idom(block)) {
1144 pred = get_Block_idom(block);
1145 fprintf (F, "edge: { sourcename: ");
1146 PRINT_NODEID(block);
1147 fprintf (F, " targetname: ");
1149 fprintf (F, " " DOMINATOR_EDGE_ATTR "}\n");
1155 dump_cfg (ir_graph *irg)
1157 ir_graph *rem = current_ir_graph;
1158 int ddif = dump_dominator_information_flag;
1159 current_ir_graph = irg;
1160 vcg_open (irg, "-cfg");
1162 if (get_irg_dom_state(irg) != dom_consistent)
1163 dump_dominator_information_flag = 0;
1165 /* walk over the blocks in the graph */
1166 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1167 dump_node (get_irg_bad(irg), NULL);
1169 dump_dominator_information_flag = ddif;
1171 current_ir_graph = rem;
1175 /***********************************************************************/
1176 /* the following routine dumps all type information reachable from an */
1178 /***********************************************************************/
1182 dump_type_graph (ir_graph *irg)
1185 rem = current_ir_graph;
1186 current_ir_graph = irg;
1188 vcg_open (irg, "-type");
1190 /* walk over the blocks in the graph */
1191 type_walk_irg(irg, dump_type_info, NULL, NULL);
1192 /* The walker for the const code can be called several times for the
1193 same (sub) experssion. So that no nodes are dumped several times
1194 we decrease the visited flag of the corresponding graph after each
1195 walk. So now increase it finally. */
1196 inc_irg_visited(get_const_code_irg());
1199 current_ir_graph = rem;
1202 /***********************************************************************/
1203 /* the following routine dumps all type information */
1204 /***********************************************************************/
1208 dump_all_types (void)
1210 vcg_open_name ("All_types");
1211 type_walk(dump_type_info, NULL, NULL);
1212 inc_irg_visited(get_const_code_irg());
1217 dump_class_hierarchy (bool entities)
1219 vcg_open_name ("class_hierarchy");
1221 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1223 type_walk(dump_class_hierarchy_node, NULL, NULL);
1227 /***********************************************************************/
1228 /* dumps a graph with type information */
1229 /***********************************************************************/
1233 dump_ir_graph_w_types (ir_graph *irg)
1236 rem = current_ir_graph;
1237 current_ir_graph = irg;
1239 vcg_open (irg, "-all");
1241 /* dump common ir graph */
1242 irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1243 /* dump type info */
1244 type_walk_irg(irg, dump_type_info, NULL, NULL);
1245 inc_irg_visited(get_const_code_irg());
1246 /* dump edges from graph to type info */
1247 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1250 current_ir_graph = rem;
1254 dump_ir_block_graph_w_types (ir_graph *irg)
1257 rem = current_ir_graph;
1258 current_ir_graph = irg;
1260 vcg_open (irg, "-all");
1262 /* dump common blocked ir graph */
1263 dump_ir_block_graph_2(irg);
1264 /* dump type info */
1265 type_walk_irg(irg, dump_type_info, NULL, NULL);
1266 inc_irg_visited(get_const_code_irg());
1267 /* dump edges from graph to type info */
1268 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1271 current_ir_graph = rem;
1274 /***********************************************************************/
1275 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1277 /* dump_ir_block_graph */
1279 /* dump_type_graph */
1280 /* dump_ir_graph_w_types */
1281 /***********************************************************************/
1282 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1284 for (i=0; i < get_irp_n_irgs(); i++) {
1285 dump_graph(get_irp_irg(i));
1290 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1291 abort with a segmentation fault. */
1292 void turn_off_edge_labels(void) {
1297 void dump_consts_local(bool b) {
1298 dump_const_local = b;
1301 void turn_off_constant_entity_values(void) {
1305 void dump_keepalive_edges(bool b) {
1309 bool get_opt_dump_keepalive_edges(void) {
1310 return dump_keepalive;
1313 void dump_out_edges(void) {
1314 dump_out_edge_flag = 1;
1317 void dump_dominator_information(void) {
1318 dump_dominator_information_flag = 1;
1321 void dump_loop_information(void) {
1322 dump_loop_information_flag = 1;
1325 void dont_dump_loop_information(void) {
1326 dump_loop_information_flag = 0;
1329 static void clear_link(ir_node * node, void * env) {
1330 set_irn_link(node, NULL);
1333 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1334 assert(node); assert(map);
1336 || node_floats(node)
1337 || get_irn_op(node) == op_Bad
1338 || get_irn_op(node) == op_Unknown) {
1339 pmap_entry * entry = pmap_find(map, current_ir_graph);
1345 ARR_APP1(ir_node *, arr , node);
1347 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1350 pmap_insert(map, current_ir_graph, arr);
1353 ir_node * block = get_nodes_Block(node);
1354 set_irn_link(node, get_irn_link(block));
1355 set_irn_link(block, node);
1360 static void dump_cg_ir_block(ir_node * block, void * env) {
1362 pmap *irgmap = (pmap *)env;
1363 assert(is_Block(block));
1364 fprintf(F, "graph: { title: ");
1365 PRINT_NODEID(block);
1366 fprintf(F, " label: \"");
1367 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1368 #ifdef DEBUG_libfirm
1369 fprintf (F, "%ld", get_irn_node_nr(block));
1371 fprintf (F, "%p", (void*) block);
1373 if (exc_normal != get_Block_exc(block)) {
1374 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1377 fprintf(F, "\" status:clustered color:%s \n",
1378 get_Block_matured(block) ? "yellow" : "red");
1380 /* dump the blocks edges */
1381 dump_ir_data_edges(block);
1383 /* dump the nodes that go into the block */
1384 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1385 dump_node(node, irgmap);
1386 dump_ir_data_edges(node);
1389 /* Close the vcg information for the block */
1390 fprintf(F, "}\n\n");
1393 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1396 fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
1397 (void*) irg, id_to_str(get_entity_ident(get_irg_ent(irg))));
1399 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1400 ir_node * node = arr[i];
1401 if (is_Block(node)) {
1402 /* Dumps the block and all the nodes in the block , which are to
1403 be found in Block->link. */
1404 dump_cg_ir_block(node, irgmap);
1406 /* Nodes that are not in a Block. */
1407 dump_node(node, NULL);
1408 dump_ir_data_edges(node);
1411 /* Close the vcg information for the irg */
1412 fprintf(F, "}\n\n");
1415 /* dump interprocedural graph with surrounding methods */
1416 void dump_cg_block_graph(ir_graph * irg) {
1417 pmap * map = pmap_create();
1418 pmap * map2 = pmap_create();
1423 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1424 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1425 pmap_insert(map2, entry->key, entry->value);
1426 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1427 d_cg_block_graph(entry->key, entry->value, map2);
1428 DEL_ARR_F(entry->value);
1434 if (dump_loop_information_flag) dump_loop_info(irg);
1438 static void collect_node(ir_node * node, void *env) {
1440 || node_floats(node)
1441 || get_irn_op(node) == op_Bad
1442 || get_irn_op(node) == op_Unknown) {
1443 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1444 ARR_APP1(ir_node *, arr, node);
1445 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1447 ir_node * block = get_nodes_Block(node);
1448 set_irn_link(node, get_irn_link(block));
1449 set_irn_link(block, node);
1453 /* Links all nodes that have the block field set in the link field of
1454 the block. Adds all blocks and nodes not associated with a block
1455 in a array in irg->link. */
1456 static void collect_nodes(void) {
1458 for (i = 0; i < get_irp_n_irgs(); i++)
1459 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1460 cg_walk(clear_link, collect_node, NULL);
1463 static void dump_graphs(void) {
1465 for (i = 0; i < get_irp_n_irgs(); i++) {
1466 current_ir_graph = get_irp_irg(i);
1467 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1471 /* Dump all irgs in interprocedural view to a single file. */
1472 void dump_all_cg_block_graph(void) {
1474 int rem_view = interprocedural_view;
1475 interprocedural_view = 1;
1476 vcg_open_name ("All_graphs");
1481 if (dump_loop_information_flag)
1482 for (i = 0; i < get_irp_n_irgs(); i++)
1483 dump_loop_info(get_irp_irg(i));
1486 interprocedural_view = rem_view;
1489 /* dump interprocedural block graph with surrounding methods */
1490 void dump_cg_graph(ir_graph * irg) {
1491 pmap * map = pmap_create();
1492 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1496 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1497 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1498 pmap_insert(map2, entry->key, entry->value);
1499 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1500 ir_node ** arr = entry->value;
1502 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1504 fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1505 id_to_str(irg_ident), id_to_str(irg_ident));
1507 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1508 ir_node * node = arr[i];
1509 dump_node(node, map2);
1510 dump_ir_data_edges(node);
1511 if (is_Block(node)) {
1512 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1513 dump_node(node, map2);
1514 dump_ir_block_edge(node);
1515 dump_ir_data_edges(node);
1522 /* Close the vcg information for the irg */
1523 fprintf(F, "}\n\n");