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", id_to_str(get_entity_ident(ent)), id_to_str(get_entity_ld_ident(ent)));
669 fprintf(F, "\noffset: %d", get_entity_offset(ent));
670 if (is_method_type(get_entity_type(ent))) {
671 if (get_entity_irg(ent)) /* can be null */
672 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
674 { fprintf (F, "\nirg = NULL"); }
676 fprintf(F, "\"\n}\n");
679 /* dumps a type or entity and it's edges. */
681 dump_type_info (type_or_ent *tore, void *env) {
682 int i = 0; /* to shutup gcc */
684 /* dump this type or entity */
686 switch (get_kind(tore)) {
689 entity *ent = (entity *)tore;
692 dump_entity_node(ent);
694 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
695 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
696 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
697 PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
698 if(is_class_type(get_entity_owner(ent))) {
699 for(i = 0; i < get_entity_n_overwrites(ent); i++){
700 PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
703 /* attached subgraphs */
704 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
705 if (is_atomic_entity(ent)) {
706 value = get_atomic_ent_value(ent);
708 PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
710 fprintf (F, "edge: { sourcename: \"%p\" targetname: ", GET_ENTID(ent));
712 fprintf(F, " " ENT_VALUE_EDGE_ATTR "\"}\n");
714 dump_const_expression(value);
717 if (is_compound_entity(ent)) {
718 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
719 value = get_compound_ent_value(ent, i);
721 PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
722 dump_const_expression(value);
723 PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
725 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
726 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
727 get_compound_ent_value_member(ent, i), i);
736 type *tp = (type *)tore;
738 /* and now the edges */
739 switch (get_type_tpop_code(tp)) {
742 for (i=0; i < get_class_n_supertypes(tp); i++) {
743 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
746 for (i=0; i < get_class_n_members(tp); i++) {
747 PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
752 for (i=0; i < get_struct_n_members(tp); i++) {
753 PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
758 for (i = 0; i < get_method_n_params(tp); i++)
760 PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
762 for (i = 0; i < get_method_n_ress(tp); i++)
764 PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
769 for (i = 0; i < get_union_n_members(tp); i++)
771 PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
776 PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
777 PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
779 case tpo_enumeration:
784 PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
792 break; /* case k_type */
795 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
797 } /* switch kind_or_entity */
800 /* dumps a class type node and a superclass edge.
801 If env != null dumps entities of classes and overwrites edges. */
803 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
804 int i = 0; /* to shutup gcc */
806 /* dump this type or entity */
807 switch (get_kind(tore)) {
809 entity *ent = (entity *)tore;
810 if (get_entity_owner(ent) == get_glob_type()) break;
811 if ((env) && is_class_type(get_entity_owner(ent))) {
813 dump_entity_node(ent);
815 PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
816 for(i = 0; i < get_entity_n_overwrites(ent); i++)
818 PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
821 } break; /* case k_entity */
824 type *tp = (type *)tore;
825 if (tp == get_glob_type()) break;
826 switch (get_type_tpop_code(tp)) {
829 /* and now the edges */
830 for (i=0; i < get_class_n_supertypes(tp); i++)
832 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
838 break; /* case k_type */
841 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
843 } /* switch kind_or_entity */
846 /************************************************************************/
847 /* open and close vcg file */
848 /************************************************************************/
850 static void vcg_open (ir_graph *irg, char *suffix) {
851 char *fname; /* filename to put the vcg information in */
858 /** open file for vcg graph */
859 ent = get_irg_ent(irg);
860 id = ent->ld_name ? ent->ld_name : ent->name;
861 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
862 len = id_to_strlen (id);
864 if (dump_file_suffix)
865 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
867 fname = malloc (len + 5 + strlen(suffix));
868 strncpy (fname, cp, len); /* copy the filename */
870 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
871 strcat (fname, suffix); /* append file suffix */
872 strcat (fname, ".vcg"); /* append the .vcg suffix */
873 F = fopen (fname, "w"); /* open file for writing */
875 panic ("cannot open %s for writing (%m)", fname); /* not reached */
879 strcpy(label, "yes");
881 strcpy (label, "no");
886 "graph: { title: \"ir graph of %s\"\n"
887 "display_edge_labels: %s\n"
888 "layoutalgorithm: mindepth\n"
889 "manhattan_edges: yes\n"
891 "orientation: bottom_to_top\n"
892 "classname 1: \"Data\"\n"
893 "classname 2: \"Block\"\n"
894 "classname 3: \"Entity type\""
895 "classname 4: \"Entity owner\""
896 "classname 5: \"Method Param\""
897 "classname 6: \"Method Res\""
898 "classname 7: \"Super\""
899 "classname 8: \"Union\""
900 "classname 9: \"Points-to\""
901 "classname 10: \"Array Element Type\""
902 "classname 11: \"Overwrites\""
903 "classname 12: \"Member\""
906 fprintf (F, "\n"); /* a separator */
909 static void vcg_open_name (const char *name) {
910 char *fname; /* filename to put the vcg information in */
914 /** open file for vcg graph */
916 fname = malloc (len + 5);
917 if (dump_file_suffix)
918 fname = malloc (len + 5 + strlen(dump_file_suffix));
920 fname = malloc (len + 5);
921 strcpy (fname, name); /* copy the filename */
922 if (dump_file_suffix) strcat (fname, dump_file_suffix);
923 strcat (fname, ".vcg"); /* append the .vcg suffix */
924 F = fopen (fname, "w"); /* open file for writing */
926 panic ("cannot open %s for writing (%m)", fname); /* not reached */
930 strcpy(label, "yes");
932 strcpy (label, "no");
937 "graph: { title: \"ir graph of %s\"\n"
938 "display_edge_labels: %s\n"
939 "layoutalgorithm: mindepth\n"
940 "manhattan_edges: yes\n"
942 "orientation: bottom_to_top\n"
943 "classname 1: \"Data\"\n"
944 "classname 2: \"Block\"\n"
945 "classname 3: \"Entity type\"\n"
946 "classname 4: \"Entity owner\"\n"
947 "classname 5: \"Method Param\"\n"
948 "classname 6: \"Method Res\"\n"
949 "classname 7: \"Super\"\n"
950 "classname 8: \"Union\"\n"
951 "classname 9: \"Points-to\"\n"
952 "classname 10: \"Array Element Type\"\n"
953 "classname 11: \"Overwrites\"\n"
954 "classname 12: \"Member\"\n"
957 fprintf (F, "\n"); /* a separator */
962 fprintf (F, "}\n"); /* print footer */
963 fclose (F); /* close vcg file */
966 /************************************************************************/
967 /* routines to dump a graph, blocks as conventional nodes. */
968 /************************************************************************/
970 static int node_floats(ir_node *n) {
971 return ((get_op_pinned(get_irn_op(n)) == floats) &&
972 (get_irg_pinned(current_ir_graph) == floats));
976 dump_whole_node (ir_node *n, void* env) {
978 if (!node_floats(n)) dump_ir_block_edge(n);
979 dump_ir_data_edges(n);
983 dump_ir_graph (ir_graph *irg)
986 rem = current_ir_graph;
987 current_ir_graph = irg;
991 /* walk over the graph */
992 /* dump_whole_node must be called in post visiting predecessors */
993 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
995 /* dump the out edges in a separate walk */
996 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
997 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1002 current_ir_graph = rem;
1005 /***********************************************************************/
1006 /* the following routines dump the nodes as attached to the blocks. */
1007 /***********************************************************************/
1010 dump_ir_blocks_nodes (ir_node *n, void *env) {
1011 ir_node *block = (ir_node *)env;
1013 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1015 dump_ir_data_edges(n);
1017 if (get_irn_op(n) == op_Bad)
1022 dump_ir_block (ir_node *block, void *env) {
1023 ir_graph *irg = (ir_graph *)env;
1025 if (get_irn_opcode(block) == iro_Block) {
1027 /* This is a block. So dump the vcg information to make a block. */
1028 fprintf(F, "graph: { title: ");
1029 PRINT_NODEID(block);
1030 fprintf(F, " label: \"");
1031 #ifdef DEBUG_libfirm
1032 fprintf (F, "%ld", get_irn_node_nr(block));
1034 fprintf (F, "%s", get_op_name(get_irn_op(block)));
1036 if (exc_normal != get_Block_exc (block))
1037 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1039 fprintf(F, "\" status:clustered color:%s \n",
1040 get_Block_matured (block) ? "yellow" : "red");
1041 /* dump the blocks edges */
1042 dump_ir_data_edges(block);
1044 /* dump the nodes that go into the block */
1045 irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1047 /* Close the vcg information for the block */
1048 fprintf(F, "}\n\n");
1049 dump_const_node_local(block, NULL);
1055 dump_blockless_nodes (ir_node *n, void *env) {
1056 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1058 dump_ir_data_edges(n);
1059 dump_ir_block_edge(n);
1060 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1063 if (node_floats(n)) {
1065 dump_ir_data_edges(n);
1066 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1070 static void dump_ir_block_graph_2 (ir_graph *irg)
1073 /* walk over the blocks in the graph */
1074 irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1076 /* dump all nodes that are not in a Block */
1077 irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1079 /* dump the Bad node */
1081 dump_node(get_irg_bad(irg), NULL);
1085 dump_ir_block_graph (ir_graph *irg)
1088 rem = current_ir_graph;
1089 current_ir_graph = irg;
1093 dump_ir_block_graph_2 (irg);
1095 if (dump_loop_information_flag) dump_loop_info(irg);
1098 current_ir_graph = rem;
1102 /***********************************************************************/
1103 /* the following routines dump a control flow graph */
1104 /***********************************************************************/
1108 dump_block_to_cfg (ir_node *block, void *env) {
1112 if (get_irn_opcode(block) == iro_Block) {
1113 /* This is a block. Dump a node for the block. */
1114 fprintf (F, "node: {title:"); PRINT_NODEID(block);
1115 fprintf (F, " label: \"%s ", get_op_name(get_irn_op(block)));
1116 #ifdef DEBUG_libfirm
1117 fprintf (F, "%ld", get_irn_node_nr(block));
1119 fprintf (F, "%p", (void*) block);
1122 if (exc_normal != get_Block_exc (block))
1123 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1126 if (dump_dominator_information_flag)
1127 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1129 /* Dump the edges */
1130 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1131 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1132 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1133 fprintf (F, "edge: { sourcename: ");
1134 PRINT_NODEID(block);
1135 fprintf (F, " targetname: ");
1137 fprintf (F, " }\n");
1140 /* Dump dominator edge */
1141 if (dump_dominator_information_flag && get_Block_idom(block)) {
1142 pred = get_Block_idom(block);
1143 fprintf (F, "edge: { sourcename: ");
1144 PRINT_NODEID(block);
1145 fprintf (F, " targetname: ");
1147 fprintf (F, " " DOMINATOR_EDGE_ATTR "}\n");
1153 dump_cfg (ir_graph *irg)
1155 ir_graph *rem = current_ir_graph;
1156 int ddif = dump_dominator_information_flag;
1157 current_ir_graph = irg;
1158 vcg_open (irg, "-cfg");
1160 if (get_irg_dom_state(irg) != dom_consistent)
1161 dump_dominator_information_flag = 0;
1163 /* walk over the blocks in the graph */
1164 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1165 dump_node (get_irg_bad(irg), NULL);
1167 dump_dominator_information_flag = ddif;
1169 current_ir_graph = rem;
1173 /***********************************************************************/
1174 /* the following routine dumps all type information reachable from an */
1176 /***********************************************************************/
1180 dump_type_graph (ir_graph *irg)
1183 rem = current_ir_graph;
1184 current_ir_graph = irg;
1186 vcg_open (irg, "-type");
1188 /* walk over the blocks in the graph */
1189 type_walk_irg(irg, dump_type_info, NULL, NULL);
1190 /* The walker for the const code can be called several times for the
1191 same (sub) experssion. So that no nodes are dumped several times
1192 we decrease the visited flag of the corresponding graph after each
1193 walk. So now increase it finally. */
1194 inc_irg_visited(get_const_code_irg());
1197 current_ir_graph = rem;
1200 /***********************************************************************/
1201 /* the following routine dumps all type information */
1202 /***********************************************************************/
1206 dump_all_types (void)
1208 vcg_open_name ("All_types");
1209 type_walk(dump_type_info, NULL, NULL);
1210 inc_irg_visited(get_const_code_irg());
1215 dump_class_hierarchy (bool entities)
1217 vcg_open_name ("class_hierarchy");
1219 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1221 type_walk(dump_class_hierarchy_node, NULL, NULL);
1225 /***********************************************************************/
1226 /* dumps a graph with type information */
1227 /***********************************************************************/
1231 dump_ir_graph_w_types (ir_graph *irg)
1234 rem = current_ir_graph;
1235 current_ir_graph = irg;
1237 vcg_open (irg, "-all");
1239 /* dump common ir graph */
1240 irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1241 /* dump type info */
1242 type_walk_irg(irg, dump_type_info, NULL, NULL);
1243 inc_irg_visited(get_const_code_irg());
1244 /* dump edges from graph to type info */
1245 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1248 current_ir_graph = rem;
1252 dump_ir_block_graph_w_types (ir_graph *irg)
1255 rem = current_ir_graph;
1256 current_ir_graph = irg;
1258 vcg_open (irg, "-all");
1260 /* dump common blocked ir graph */
1261 dump_ir_block_graph_2(irg);
1262 /* dump type info */
1263 type_walk_irg(irg, dump_type_info, NULL, NULL);
1264 inc_irg_visited(get_const_code_irg());
1265 /* dump edges from graph to type info */
1266 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1269 current_ir_graph = rem;
1272 /***********************************************************************/
1273 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1275 /* dump_ir_block_graph */
1277 /* dump_type_graph */
1278 /* dump_ir_graph_w_types */
1279 /***********************************************************************/
1280 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1282 for (i=0; i < get_irp_n_irgs(); i++) {
1283 dump_graph(get_irp_irg(i));
1288 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1289 abort with a segmentation fault. */
1290 void turn_off_edge_labels(void) {
1295 void dump_consts_local(bool b) {
1296 dump_const_local = b;
1299 void turn_off_constant_entity_values(void) {
1303 void dump_keepalive_edges(bool b) {
1307 bool get_opt_dump_keepalive_edges(void) {
1308 return dump_keepalive;
1311 void dump_out_edges(void) {
1312 dump_out_edge_flag = 1;
1315 void dump_dominator_information(void) {
1316 dump_dominator_information_flag = 1;
1319 void dump_loop_information(void) {
1320 dump_loop_information_flag = 1;
1323 void dont_dump_loop_information(void) {
1324 dump_loop_information_flag = 0;
1327 static void clear_link(ir_node * node, void * env) {
1328 set_irn_link(node, NULL);
1331 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1333 || node_floats(node)
1334 || get_irn_op(node) == op_Bad
1335 || get_irn_op(node) == op_Unknown) {
1336 pmap_entry * entry = pmap_find(map, current_ir_graph);
1341 ARR_APP1(ir_node *, arr , node);
1343 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1345 pmap_insert(map, current_ir_graph, arr);
1348 ir_node * block = get_nodes_Block(node);
1349 set_irn_link(node, get_irn_link(block));
1350 set_irn_link(block, node);
1355 static void dump_cg_ir_block(ir_node * block, void * env) {
1357 pmap *irgmap = (pmap *)env;
1358 assert(is_Block(block));
1359 fprintf(F, "graph: { title: ");
1360 PRINT_NODEID(block);
1361 fprintf(F, " label: \"");
1362 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1363 #ifdef DEBUG_libfirm
1364 fprintf (F, "%ld", get_irn_node_nr(block));
1366 fprintf (F, "%p", (void*) block);
1368 if (exc_normal != get_Block_exc(block)) {
1369 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1372 fprintf(F, "\" status:clustered color:%s \n",
1373 get_Block_matured(block) ? "yellow" : "red");
1375 /* dump the blocks edges */
1376 dump_ir_data_edges(block);
1378 /* dump the nodes that go into the block */
1379 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1380 dump_node(node, irgmap);
1381 dump_ir_data_edges(node);
1384 /* Close the vcg information for the block */
1385 fprintf(F, "}\n\n");
1388 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1391 fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
1392 (void*) irg, id_to_str(get_entity_ident(get_irg_ent(irg))));
1394 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1395 ir_node * node = arr[i];
1396 if (is_Block(node)) {
1397 /* Dumps the block and all the nodes in the block , which are to
1398 be found in Block->link. */
1399 dump_cg_ir_block(node, irgmap);
1401 /* Nodes that are not in a Block. */
1402 dump_node(node, NULL);
1403 dump_ir_data_edges(node);
1406 /* Close the vcg information for the irg */
1407 fprintf(F, "}\n\n");
1410 /* dump interprocedural graph with surrounding methods */
1411 void dump_cg_block_graph(ir_graph * irg) {
1412 pmap * map = pmap_create();
1413 pmap * map2 = pmap_create();
1418 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1419 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1420 pmap_insert(map2, entry->key, entry->value);
1421 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1422 d_cg_block_graph(entry->key, entry->value, map2);
1423 DEL_ARR_F(entry->value);
1429 if (dump_loop_information_flag) dump_loop_info(irg);
1433 static void collect_node(ir_node * node, void *env) {
1435 || node_floats(node)
1436 || get_irn_op(node) == op_Bad
1437 || get_irn_op(node) == op_Unknown) {
1438 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1439 ARR_APP1(ir_node *, arr, node);
1440 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1442 ir_node * block = get_nodes_Block(node);
1443 set_irn_link(node, get_irn_link(block));
1444 set_irn_link(block, node);
1448 /* Links all nodes that have the block field set in the link field of
1449 the block. Adds all blocks and nodes not associated with a block
1450 in a array in irg->link. */
1451 static void collect_nodes(void) {
1453 for (i = 0; i < get_irp_n_irgs(); i++)
1454 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1455 cg_walk(clear_link, collect_node, NULL);
1458 static void dump_graphs(void) {
1460 for (i = 0; i < get_irp_n_irgs(); i++) {
1461 current_ir_graph = get_irp_irg(i);
1462 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1466 /* Dump all irgs in interprocedural view to a single file. */
1467 void dump_all_cg_block_graph(void) {
1469 int rem_view = interprocedural_view;
1470 interprocedural_view = 1;
1471 vcg_open_name ("All_graphs");
1476 if (dump_loop_information_flag)
1477 for (i = 0; i < get_irp_n_irgs(); i++)
1478 dump_loop_info(get_irp_irg(i));
1481 interprocedural_view = rem_view;
1484 /* dump interprocedural block graph with surrounding methods */
1485 void dump_cg_graph(ir_graph * irg) {
1486 pmap * map = pmap_create();
1487 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1491 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1492 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1493 pmap_insert(map2, entry->key, entry->value);
1494 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1495 ir_node ** arr = entry->value;
1497 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1499 fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1500 id_to_str(irg_ident), id_to_str(irg_ident));
1502 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1503 ir_node * node = arr[i];
1504 dump_node(node, map2);
1505 dump_ir_data_edges(node);
1506 if (is_Block(node)) {
1507 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1508 dump_node(node, map2);
1509 dump_ir_block_edge(node);
1510 dump_ir_data_edges(node);
1517 /* Close the vcg information for the irg */
1518 fprintf(F, "}\n\n");