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, "\""); 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, "\""); 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, "\""); 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, "\""); 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;
261 dump_node_info (ir_node *n) {
262 fprintf (F, " info1: \"visited: %ld\n\"", get_irn_visited(n));
265 static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
266 ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n);
269 ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) {
270 ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos));
271 if (is_ip_cfop(pred)) {
272 ir_graph *irg = get_ip_cfop_irg(pred);
273 if (pmap_find(irgmap, irg) == NULL) return true;
282 bool is_constlike_node(ir_node *n) {
283 ir_op *op = get_irn_op(n);
284 return (op == op_Const || op == op_Bad || op == op_SymConst);
288 static void dump_const_node_local(ir_node *n, pmap *irgmap) {
290 if (!get_opt_dump_const_local()) return;
291 /* Use visited flag to avoid outputting nodes twice.
292 initialize it first. */
293 for (i = 0; i < get_irn_arity(n); i++) {
294 ir_node *con = get_irn_n(n, i);
295 if (is_constlike_node(con)) {
296 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
297 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
300 for (i = 0; i < get_irn_arity(n); i++) {
301 ir_node *con = get_irn_n(n, i);
302 if (is_constlike_node(con) && irn_not_visited(con)) {
303 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
304 mark_irn_visited(con);
305 /* Generate a new name for the node by appending the names of
307 fprintf (F, "node: {title: "); PRINT_CONSTID(n,con);
308 fprintf(F, " label: \"");
309 dump_node_opcode(con);
310 dump_node_mode (con);
312 dump_node_nodeattr(con);
314 fprintf (F, " %ld", get_irn_node_nr(con));
317 dump_node_vcgattr(con);
325 dump_node (ir_node *n, pmap * map) {
326 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
329 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
334 dump_node_nodeattr(n);
336 fprintf (F, " %ld", get_irn_node_nr(n));
339 dump_node_vcgattr(n);
342 dump_const_node_local(n, map);
345 /* dump the edge to the block this node belongs to */
347 dump_ir_block_edge(ir_node *n) {
348 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
349 if (is_no_Block(n)) {
350 fprintf (F, "edge: { sourcename: \"");
352 fprintf (F, "\" targetname: \"");
353 PRINT_NODEID(get_nodes_Block(n));
354 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
358 static void print_edge_vcgattr(ir_node *from, int to) {
361 if (is_backedge(from, to)) fprintf (F, BACK_EDGE_ATTR);
363 switch (get_irn_opcode(from)) {
365 fprintf (F, CF_EDGE_ATTR);
367 case iro_Start: break;
370 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
371 fprintf (F, CF_EDGE_ATTR);
372 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
373 fprintf (F, MEM_EDGE_ATTR);
376 case iro_EndReg: break;
377 case iro_EndExcept: break;
379 case iro_Break: break;
380 case iro_Cond: break;
383 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
385 case iro_Const: break;
386 case iro_SymConst:break;
389 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
391 case iro_CallBegin: break;
394 case iro_Minus: break;
400 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
408 case iro_Shrs: break;
411 case iro_Conv: break;
413 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
419 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
422 fprintf (F, MEM_EDGE_ATTR);
424 case iro_Tuple: break;
427 switch (get_irn_modecode(from)) {
429 fprintf (F, CF_EDGE_ATTR);
432 fprintf (F, MEM_EDGE_ATTR);
438 case iro_Unknown: break;
445 /* dump edges to our inputs */
447 dump_ir_data_edges(ir_node *n) {
448 int i, visited = get_irn_visited(n);
450 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
453 for (i = 0; i < get_irn_arity(n); i++) {
454 ir_node * pred = get_irn_n(n, i);
456 if ((interprocedural_view && get_irn_visited(pred) < visited))
457 continue; /* pred not dumped */
458 if (is_backedge(n, i))
459 fprintf (F, "backedge: {sourcename: ");
461 fprintf (F, "edge: {sourcename: \"");
463 fprintf (F, "\" targetname: ");
464 if ((get_opt_dump_const_local()) && is_constlike_node(pred))
466 PRINT_CONSTID(n,pred);
469 {fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
471 fprintf (F, " label: \"%d\" ", i);
472 print_edge_vcgattr(n, i);
479 dump_out_edge (ir_node *n, void* env) {
481 for (i = 0; i < get_irn_n_outs(n); i++) {
482 assert(get_irn_out(n, i));
483 fprintf (F, "edge: {sourcename: \"");
485 fprintf (F, "\" targetname: \"");
486 PRINT_NODEID(get_irn_out(n, i));
487 fprintf (F, "\" color: red linestyle: dashed");
493 dump_loop_node_edge (ir_loop *loop, int i) {
495 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", (void*) loop);
496 PRINT_NODEID(get_loop_node(loop, i));
497 fprintf (F, "\" color: green");
502 void dump_loops (ir_loop *loop) {
504 /* dump this loop node */
505 fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
506 (void*)loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
507 /* dump edges to nodes in loop -- only if it is a real loop */
508 if (get_loop_depth(loop) != 0) {
509 for (i = 0; i < get_loop_n_nodes(loop); i++) {
510 dump_loop_node_edge(loop, i);
513 for (i = 0; i < get_loop_n_sons(loop); i++) {
514 dump_loops(get_loop_son(loop, i));
519 void dump_loop_info(ir_graph *irg) {
520 ir_graph *rem = current_ir_graph;
521 current_ir_graph = irg;
523 if (get_irg_loop(irg))
524 dump_loops(get_irg_loop(irg));
526 current_ir_graph = rem;
530 /* dumps the edges between nodes and their type or entity attributes. */
531 static void dump_node2type_edges (ir_node *n, void *env)
535 switch (get_irn_opcode(n)) {
537 /* @@@ some consts have an entity */
540 if ( (get_SymConst_kind(n) == type_tag)
541 || (get_SymConst_kind(n) == size))
543 PRINT_NODE_TYPE_EDGE(n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
547 PRINT_NODE_ENT_EDGE(n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
550 PRINT_NODE_TYPE_EDGE(n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
553 PRINT_NODE_TYPE_EDGE(n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
556 PRINT_NODE_TYPE_EDGE(n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
564 /* @@@@ Does not work as someone kills the visited flag. */
565 static void dump_const_expression(ir_node *value) {
566 ir_graph *rem = current_ir_graph;
567 int rem_dump_const_local = dump_const_local;
568 dump_const_local = 0;
569 current_ir_graph = get_const_code_irg();
570 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
571 /* Decrease visited flag so that we walk with the same flag for the next
572 expresssion. This guarantees that we don't dump the same node twice,
573 as for const expressions cse is performed to save memory. */
574 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
575 current_ir_graph = rem;
576 dump_const_local = rem_dump_const_local;
580 static void print_type_info(type *tp) {
581 if (get_type_state(tp) == layout_undefined) {
582 fprintf(F, "state: layout_undefined\n");
584 fprintf(F, "state: layout_fixed,\n");
586 if (get_type_mode(tp))
587 fprintf(F, "mode: %s,\n", id_to_str(get_mode_ident(get_type_mode(tp))));
588 fprintf(F, "size: %dB,\n", get_type_size(tp));
592 static void print_typespecific_info(type *tp) {
593 switch (get_type_tpop_code(tp)) {
596 if(existent == get_class_peculiarity(tp))
597 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
599 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
603 fprintf (F, " " TYPE_METH_NODE_ATTR);
614 case tpo_enumeration:
627 static void print_type_node(type *tp) {
628 fprintf (F, "node: {title: ");
630 fprintf (F, " label: \"%s %s\"", id_to_str(get_type_tpop_nameid(tp)), id_to_str(get_type_ident(tp)));
631 fprintf (F, " info1: \"");
634 print_typespecific_info(tp);
638 void dump_entity_node(entity *ent) {
639 fprintf (F, "node: {title: \"");
640 PRINT_ENTID(ent); fprintf(F, "\"");
641 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
642 fprintf (F, "label: ");
643 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , id_to_str(get_entity_ident(ent)));
644 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
645 fprintf (F, "\nallocation: ");
646 switch (get_entity_allocation(ent)) {
647 case dynamic_allocated: fprintf (F, "dynamic allocated"); break;
648 case automatic_allocated: fprintf (F, "automatic allocated"); break;
649 case static_allocated: fprintf (F, "static allocated"); break;
650 case parameter_allocated: fprintf (F, "parameter allocated"); break;
652 fprintf (F, "\nvisibility: ");
653 switch (get_entity_visibility(ent)) {
654 case local: fprintf (F, "local"); break;
655 case external_visible: fprintf (F, "external visible"); break;
656 case external_allocated: fprintf (F, "external allocated"); break;
658 fprintf (F, "\nvariability: ");
659 switch (get_entity_variability(ent)) {
660 case uninitialized: fprintf (F, "uninitialized");break;
661 case initialized: fprintf (F, "initialized"); break;
662 case part_constant: fprintf (F, "part_constant");break;
663 case constant: fprintf (F, "constant"); break;
665 fprintf (F, "\nvolatility: ");
666 switch (get_entity_volatility(ent)) {
667 case non_volatile: fprintf (F, "non_volatile"); break;
668 case is_volatile: fprintf (F, "is_volatile"); break;
670 fprintf (F, "\npeculiarity: ");
671 switch (get_entity_peculiarity(ent)) {
672 case description: fprintf (F, "description"); break;
673 case inherited: fprintf (F, "inherited"); break;
674 case existent: fprintf (F, "existent"); break;
676 fprintf(F, "\nname: %s\nld_name: %s",
677 id_to_str(get_entity_ident(ent)),
678 id_to_str(get_entity_ld_ident(ent)));
679 fprintf(F, "\noffset: %d", get_entity_offset(ent));
680 if (is_method_type(get_entity_type(ent))) {
681 if (get_entity_irg(ent)) /* can be null */
682 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
684 { fprintf (F, "\nirg = NULL"); }
686 fprintf(F, "\"\n}\n");
689 /* dumps a type or entity and it's edges. */
691 dump_type_info (type_or_ent *tore, void *env) {
692 int i = 0; /* to shutup gcc */
694 /* dump this type or entity */
696 switch (get_kind(tore)) {
699 entity *ent = (entity *)tore;
702 dump_entity_node(ent);
704 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
705 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
706 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
707 PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
708 if(is_class_type(get_entity_owner(ent))) {
709 for(i = 0; i < get_entity_n_overwrites(ent); i++){
710 PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
713 /* attached subgraphs */
714 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
715 if (is_atomic_entity(ent)) {
716 value = get_atomic_ent_value(ent);
718 PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
719 /* DDMN(value); $$$ */
720 dump_const_expression(value);
723 if (is_compound_entity(ent)) {
724 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
725 value = get_compound_ent_value(ent, i);
727 PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
728 dump_const_expression(value);
729 PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
731 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
732 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
733 get_compound_ent_value_member(ent, i), i);
742 type *tp = (type *)tore;
744 /* and now the edges */
745 switch (get_type_tpop_code(tp)) {
748 for (i=0; i < get_class_n_supertypes(tp); i++) {
749 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
752 for (i=0; i < get_class_n_members(tp); i++) {
753 PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
758 for (i=0; i < get_struct_n_members(tp); i++) {
759 PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
764 for (i = 0; i < get_method_n_params(tp); i++)
766 PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
768 for (i = 0; i < get_method_n_ress(tp); i++)
770 PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
775 for (i = 0; i < get_union_n_members(tp); i++)
777 PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
782 PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
783 PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
785 case tpo_enumeration:
790 PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
798 break; /* case k_type */
801 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
803 } /* switch kind_or_entity */
806 /* dumps a class type node and a superclass edge.
807 If env != null dumps entities of classes and overwrites edges. */
809 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
810 int i = 0; /* to shutup gcc */
812 /* dump this type or entity */
813 switch (get_kind(tore)) {
815 entity *ent = (entity *)tore;
816 if (get_entity_owner(ent) == get_glob_type()) break;
817 if ((env) && is_class_type(get_entity_owner(ent))) {
819 dump_entity_node(ent);
821 PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
822 for(i = 0; i < get_entity_n_overwrites(ent); i++)
824 PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
827 } break; /* case k_entity */
830 type *tp = (type *)tore;
831 if (tp == get_glob_type()) break;
832 switch (get_type_tpop_code(tp)) {
835 /* and now the edges */
836 for (i=0; i < get_class_n_supertypes(tp); i++)
838 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
844 break; /* case k_type */
847 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
849 } /* switch kind_or_entity */
852 /************************************************************************/
853 /* open and close vcg file */
854 /************************************************************************/
856 static void vcg_open (ir_graph *irg, char *suffix) {
857 char *fname; /* filename to put the vcg information in */
864 /** open file for vcg graph */
865 ent = get_irg_ent(irg);
866 id = ent->ld_name ? ent->ld_name : ent->name;
867 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
868 len = id_to_strlen (id);
870 if (dump_file_suffix)
871 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
873 fname = malloc (len + 5 + strlen(suffix));
874 strncpy (fname, cp, len); /* copy the filename */
876 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
877 strcat (fname, suffix); /* append file suffix */
878 strcat (fname, ".vcg"); /* append the .vcg suffix */
879 F = fopen (fname, "w"); /* open file for writing */
881 panic ("cannot open %s for writing (%m)", fname); /* not reached */
885 strcpy(label, "yes");
887 strcpy (label, "no");
892 "graph: { title: \"ir graph of %s\"\n"
893 "display_edge_labels: %s\n"
894 "layoutalgorithm: mindepth\n"
895 "manhattan_edges: yes\n"
897 "orientation: bottom_to_top\n"
898 "classname 1: \"Data\"\n"
899 "classname 2: \"Block\"\n"
900 "classname 3: \"Entity type\"\n"
901 "classname 4: \"Entity owner\"\n"
902 "classname 5: \"Method Param\"\n"
903 "classname 6: \"Method Res\"\n"
904 "classname 7: \"Super\"\n"
905 "classname 8: \"Union\"\n"
906 "classname 9: \"Points-to\"\n"
907 "classname 10: \"Array Element Type\"\n"
908 "classname 11: \"Overwrites\"\n"
909 "classname 12: \"Member\"\n"
912 fprintf (F, "\n"); /* a separator */
915 static void vcg_open_name (const char *name) {
916 char *fname; /* filename to put the vcg information in */
920 /** open file for vcg graph */
922 fname = malloc (len + 5);
923 if (dump_file_suffix)
924 fname = malloc (len + 5 + strlen(dump_file_suffix));
926 fname = malloc (len + 5);
927 strcpy (fname, name); /* copy the filename */
928 if (dump_file_suffix) strcat (fname, dump_file_suffix);
929 strcat (fname, ".vcg"); /* append the .vcg suffix */
930 F = fopen (fname, "w"); /* open file for writing */
932 panic ("cannot open %s for writing (%m)", fname); /* not reached */
936 strcpy(label, "yes");
938 strcpy (label, "no");
943 "graph: { title: \"ir graph of %s\"\n"
944 "display_edge_labels: %s\n"
945 "layoutalgorithm: mindepth\n"
946 "manhattan_edges: yes\n"
948 "orientation: bottom_to_top\n"
949 "classname 1: \"Data\"\n"
950 "classname 2: \"Block\"\n"
951 "classname 3: \"Entity type\"\n"
952 "classname 4: \"Entity owner\"\n"
953 "classname 5: \"Method Param\"\n"
954 "classname 6: \"Method Res\"\n"
955 "classname 7: \"Super\"\n"
956 "classname 8: \"Union\"\n"
957 "classname 9: \"Points-to\"\n"
958 "classname 10: \"Array Element Type\"\n"
959 "classname 11: \"Overwrites\"\n"
960 "classname 12: \"Member\"\n"
963 fprintf (F, "\n"); /* a separator */
968 fprintf (F, "}\n"); /* print footer */
969 fclose (F); /* close vcg file */
972 /************************************************************************/
973 /* routines to dump a graph, blocks as conventional nodes. */
974 /************************************************************************/
976 static int node_floats(ir_node *n) {
977 return ((get_op_pinned(get_irn_op(n)) == floats) &&
978 (get_irg_pinned(current_ir_graph) == floats));
982 dump_whole_node (ir_node *n, void* env) {
984 if (!node_floats(n)) dump_ir_block_edge(n);
985 dump_ir_data_edges(n);
989 dump_ir_graph (ir_graph *irg)
992 rem = current_ir_graph;
993 current_ir_graph = irg;
997 /* walk over the graph */
998 /* dump_whole_node must be called in post visiting predecessors */
999 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1001 /* dump the out edges in a separate walk */
1002 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1003 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1008 current_ir_graph = rem;
1011 /***********************************************************************/
1012 /* the following routines dump the nodes as attached to the blocks. */
1013 /***********************************************************************/
1016 dump_ir_blocks_nodes (ir_node *n, void *env) {
1017 ir_node *block = (ir_node *)env;
1019 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1021 dump_ir_data_edges(n);
1023 if (get_irn_op(n) == op_Bad)
1028 dump_ir_block (ir_node *block, void *env) {
1029 ir_graph *irg = (ir_graph *)env;
1031 if (get_irn_opcode(block) == iro_Block) {
1033 /* This is a block. So dump the vcg information to make a block. */
1034 fprintf(F, "graph: { title: \"");
1035 PRINT_NODEID(block);
1036 fprintf(F, "\" label: \"");
1037 #ifdef DEBUG_libfirm
1038 fprintf (F, "%ld", get_irn_node_nr(block));
1040 fprintf (F, "%s", get_op_name(get_irn_op(block)));
1042 if (exc_normal != get_Block_exc (block))
1043 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1045 fprintf(F, "\" status:clustered color:%s \n",
1046 get_Block_matured (block) ? "yellow" : "red");
1047 /* dump the blocks edges */
1048 dump_ir_data_edges(block);
1050 /* dump the nodes that go into the block */
1051 irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1053 /* Close the vcg information for the block */
1054 fprintf(F, "}\n\n");
1055 dump_const_node_local(block, NULL);
1061 dump_blockless_nodes (ir_node *n, void *env) {
1062 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1064 dump_ir_data_edges(n);
1065 dump_ir_block_edge(n);
1066 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1069 if (node_floats(n)) {
1071 dump_ir_data_edges(n);
1072 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1076 static void dump_ir_block_graph_2 (ir_graph *irg)
1079 /* walk over the blocks in the graph */
1080 irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1082 /* dump all nodes that are not in a Block */
1083 irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1085 /* dump the Bad node */
1087 dump_node(get_irg_bad(irg), NULL);
1091 dump_ir_block_graph (ir_graph *irg)
1094 rem = current_ir_graph;
1095 current_ir_graph = irg;
1099 dump_ir_block_graph_2 (irg);
1101 if (dump_loop_information_flag) dump_loop_info(irg);
1104 current_ir_graph = rem;
1108 /***********************************************************************/
1109 /* the following routines dump a control flow graph */
1110 /***********************************************************************/
1114 dump_block_to_cfg (ir_node *block, void *env) {
1118 if (get_irn_opcode(block) == iro_Block) {
1119 /* This is a block. Dump a node for the block. */
1120 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1121 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1122 #ifdef DEBUG_libfirm
1123 fprintf (F, "%ld", get_irn_node_nr(block));
1125 fprintf (F, "%p", (void*) block);
1128 if (exc_normal != get_Block_exc (block))
1129 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1132 if (dump_dominator_information_flag)
1133 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1135 /* Dump the edges */
1136 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1137 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1138 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1139 fprintf (F, "edge: { sourcename: \"");
1140 PRINT_NODEID(block);
1141 fprintf (F, "\" targetname: \"");
1143 fprintf (F, "\"}\n");
1146 /* Dump dominator edge */
1147 if (dump_dominator_information_flag && get_Block_idom(block)) {
1148 pred = get_Block_idom(block);
1149 fprintf (F, "edge: { sourcename: \"");
1150 PRINT_NODEID(block);
1151 fprintf (F, "\" targetname: \"");
1153 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1159 dump_cfg (ir_graph *irg)
1161 ir_graph *rem = current_ir_graph;
1162 int ddif = dump_dominator_information_flag;
1163 current_ir_graph = irg;
1164 vcg_open (irg, "-cfg");
1166 if (get_irg_dom_state(irg) != dom_consistent)
1167 dump_dominator_information_flag = 0;
1169 /* walk over the blocks in the graph */
1170 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1171 dump_node (get_irg_bad(irg), NULL);
1173 dump_dominator_information_flag = ddif;
1175 current_ir_graph = rem;
1179 /***********************************************************************/
1180 /* the following routine dumps all type information reachable from an */
1182 /***********************************************************************/
1186 dump_type_graph (ir_graph *irg)
1189 rem = current_ir_graph;
1190 current_ir_graph = irg;
1192 vcg_open (irg, "-type");
1194 /* walk over the blocks in the graph */
1195 type_walk_irg(irg, dump_type_info, NULL, NULL);
1196 /* The walker for the const code can be called several times for the
1197 same (sub) experssion. So that no nodes are dumped several times
1198 we decrease the visited flag of the corresponding graph after each
1199 walk. So now increase it finally. */
1200 inc_irg_visited(get_const_code_irg());
1203 current_ir_graph = rem;
1206 /***********************************************************************/
1207 /* the following routine dumps all type information */
1208 /***********************************************************************/
1212 dump_all_types (void)
1214 vcg_open_name ("All_types");
1215 type_walk(dump_type_info, NULL, NULL);
1216 inc_irg_visited(get_const_code_irg());
1221 dump_class_hierarchy (bool entities)
1223 vcg_open_name ("class_hierarchy");
1225 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1227 type_walk(dump_class_hierarchy_node, NULL, NULL);
1231 /***********************************************************************/
1232 /* dumps a graph with type information */
1233 /***********************************************************************/
1237 dump_ir_graph_w_types (ir_graph *irg)
1240 rem = current_ir_graph;
1241 current_ir_graph = irg;
1243 vcg_open (irg, "-all");
1245 /* dump common ir graph */
1246 irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1247 /* dump type info */
1248 type_walk_irg(irg, dump_type_info, NULL, NULL);
1249 inc_irg_visited(get_const_code_irg());
1250 /* dump edges from graph to type info */
1251 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1254 current_ir_graph = rem;
1258 dump_ir_block_graph_w_types (ir_graph *irg)
1261 rem = current_ir_graph;
1262 current_ir_graph = irg;
1264 vcg_open (irg, "-all");
1266 /* dump common blocked ir graph */
1267 dump_ir_block_graph_2(irg);
1268 /* dump type info */
1269 type_walk_irg(irg, dump_type_info, NULL, NULL);
1270 inc_irg_visited(get_const_code_irg());
1271 /* dump edges from graph to type info */
1272 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1275 current_ir_graph = rem;
1278 /***********************************************************************/
1279 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1281 /* dump_ir_block_graph */
1283 /* dump_type_graph */
1284 /* dump_ir_graph_w_types */
1285 /***********************************************************************/
1286 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1288 for (i=0; i < get_irp_n_irgs(); i++) {
1289 dump_graph(get_irp_irg(i));
1294 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1295 abort with a segmentation fault. */
1296 void turn_off_edge_labels(void) {
1301 void dump_consts_local(bool b) {
1302 dump_const_local = b;
1305 void turn_off_constant_entity_values(void) {
1309 void dump_keepalive_edges(bool b) {
1313 bool get_opt_dump_keepalive_edges(void) {
1314 return dump_keepalive;
1317 void dump_out_edges(void) {
1318 dump_out_edge_flag = 1;
1321 void dump_dominator_information(void) {
1322 dump_dominator_information_flag = 1;
1325 void dump_loop_information(void) {
1326 dump_loop_information_flag = 1;
1329 void dont_dump_loop_information(void) {
1330 dump_loop_information_flag = 0;
1333 static void clear_link(ir_node * node, void * env) {
1334 set_irn_link(node, NULL);
1337 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1338 assert(node); assert(map);
1340 || node_floats(node)
1341 || get_irn_op(node) == op_Bad
1342 || get_irn_op(node) == op_Unknown) {
1343 pmap_entry * entry = pmap_find(map, current_ir_graph);
1349 ARR_APP1(ir_node *, arr , node);
1351 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1354 pmap_insert(map, current_ir_graph, arr);
1357 ir_node * block = get_nodes_Block(node);
1358 set_irn_link(node, get_irn_link(block));
1359 set_irn_link(block, node);
1364 static void dump_cg_ir_block(ir_node * block, void * env) {
1366 pmap *irgmap = (pmap *)env;
1367 assert(is_Block(block));
1368 fprintf(F, "graph: { title: \"");
1369 PRINT_NODEID(block);
1370 fprintf(F, "\" label: \"");
1371 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1372 #ifdef DEBUG_libfirm
1373 fprintf (F, "%ld", get_irn_node_nr(block));
1375 fprintf (F, "%p", (void*) block);
1377 if (exc_normal != get_Block_exc(block)) {
1378 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1381 fprintf(F, "\" status:clustered color:%s \n",
1382 get_Block_matured(block) ? "yellow" : "red");
1384 /* dump the blocks edges */
1385 dump_ir_data_edges(block);
1387 /* dump the nodes that go into the block */
1388 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1389 dump_node(node, irgmap);
1390 dump_ir_data_edges(node);
1393 /* Close the vcg information for the block */
1394 fprintf(F, "}\n\n");
1397 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1400 fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
1401 (void*) irg, id_to_str(get_entity_ident(get_irg_ent(irg))));
1403 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1404 ir_node * node = arr[i];
1405 if (is_Block(node)) {
1406 /* Dumps the block and all the nodes in the block , which are to
1407 be found in Block->link. */
1408 dump_cg_ir_block(node, irgmap);
1410 /* Nodes that are not in a Block. */
1411 dump_node(node, NULL);
1412 dump_ir_data_edges(node);
1415 /* Close the vcg information for the irg */
1416 fprintf(F, "}\n\n");
1419 /* dump interprocedural graph with surrounding methods */
1420 void dump_cg_block_graph(ir_graph * irg) {
1421 pmap * map = pmap_create();
1422 pmap * map2 = pmap_create();
1427 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1428 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1429 pmap_insert(map2, entry->key, entry->value);
1430 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1431 d_cg_block_graph(entry->key, entry->value, map2);
1432 DEL_ARR_F(entry->value);
1438 if (dump_loop_information_flag) dump_loop_info(irg);
1442 static void collect_node(ir_node * node, void *env) {
1444 || node_floats(node)
1445 || get_irn_op(node) == op_Bad
1446 || get_irn_op(node) == op_Unknown) {
1447 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1448 ARR_APP1(ir_node *, arr, node);
1449 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1451 ir_node * block = get_nodes_Block(node);
1452 set_irn_link(node, get_irn_link(block));
1453 set_irn_link(block, node);
1457 /* Links all nodes that have the block field set in the link field of
1458 the block. Adds all blocks and nodes not associated with a block
1459 in a array in irg->link. */
1460 static void collect_nodes(void) {
1462 for (i = 0; i < get_irp_n_irgs(); i++)
1463 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1464 cg_walk(clear_link, collect_node, NULL);
1467 static void dump_graphs(void) {
1469 for (i = 0; i < get_irp_n_irgs(); i++) {
1470 current_ir_graph = get_irp_irg(i);
1471 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1475 /* Dump all irgs in interprocedural view to a single file. */
1476 void dump_all_cg_block_graph(void) {
1478 int rem_view = interprocedural_view;
1479 interprocedural_view = 1;
1480 vcg_open_name ("All_graphs");
1485 if (dump_loop_information_flag)
1486 for (i = 0; i < get_irp_n_irgs(); i++)
1487 dump_loop_info(get_irp_irg(i));
1490 interprocedural_view = rem_view;
1493 /* dump interprocedural block graph with surrounding methods */
1494 void dump_cg_graph(ir_graph * irg) {
1495 pmap * map = pmap_create();
1496 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1500 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1501 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1502 pmap_insert(map2, entry->key, entry->value);
1503 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1504 ir_node ** arr = entry->value;
1506 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1508 fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1509 id_to_str(irg_ident), id_to_str(irg_ident));
1511 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1512 ir_node * node = arr[i];
1513 dump_node(node, map2);
1514 dump_ir_data_edges(node);
1515 if (is_Block(node)) {
1516 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1517 dump_node(node, map2);
1518 dump_ir_block_edge(node);
1519 dump_ir_data_edges(node);
1526 /* Close the vcg information for the irg */
1527 fprintf(F, "}\n\n");