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", get_entity_name(get_Sel_entity(n)));
227 fprintf (F, "to %s", get_type_name(get_Cast_type(n)));
235 dump_node_vcgattr (ir_node *n)
237 switch (get_irn_opcode(n)) {
244 fprintf (F, "color: blue");
247 fprintf (F, "color: lightyellow");
250 fprintf (F, "color: green");
256 fprintf (F, "color: yellow");
259 PRINT_DEFAULT_NODE_ATTR;
264 dump_node_info (ir_node *n) {
265 fprintf (F, " info1: \"visited: %ld\n\"", get_irn_visited(n));
268 static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
269 ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n);
272 ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) {
273 ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos));
274 if (is_ip_cfop(pred)) {
275 ir_graph *irg = get_ip_cfop_irg(pred);
276 if (pmap_find(irgmap, irg) == NULL) return true;
285 bool is_constlike_node(ir_node *n) {
286 ir_op *op = get_irn_op(n);
287 return (op == op_Const || op == op_Bad || op == op_SymConst);
291 static void dump_const_node_local(ir_node *n, pmap *irgmap) {
293 if (!get_opt_dump_const_local()) return;
294 /* Use visited flag to avoid outputting nodes twice.
295 initialize it first. */
296 for (i = 0; i < get_irn_arity(n); i++) {
297 ir_node *con = get_irn_n(n, i);
298 if (is_constlike_node(con)) {
299 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
300 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
303 for (i = 0; i < get_irn_arity(n); i++) {
304 ir_node *con = get_irn_n(n, i);
305 if (is_constlike_node(con) && irn_not_visited(con)) {
306 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
307 mark_irn_visited(con);
308 /* Generate a new name for the node by appending the names of
310 fprintf (F, "node: {title: "); PRINT_CONSTID(n,con);
311 fprintf(F, " label: \"");
312 dump_node_opcode(con);
313 dump_node_mode (con);
315 dump_node_nodeattr(con);
317 fprintf (F, " %ld", get_irn_node_nr(con));
320 dump_node_vcgattr(con);
328 dump_node (ir_node *n, pmap * map) {
329 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
332 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
337 dump_node_nodeattr(n);
339 fprintf (F, " %ld", get_irn_node_nr(n));
342 dump_node_vcgattr(n);
345 dump_const_node_local(n, map);
348 /* dump the edge to the block this node belongs to */
350 dump_ir_block_edge(ir_node *n) {
351 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
352 if (is_no_Block(n)) {
353 fprintf (F, "edge: { sourcename: \"");
355 fprintf (F, "\" targetname: \"");
356 PRINT_NODEID(get_nodes_Block(n));
357 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
361 static void print_edge_vcgattr(ir_node *from, int to) {
364 if (is_backedge(from, to)) fprintf (F, BACK_EDGE_ATTR);
366 switch (get_irn_opcode(from)) {
368 fprintf (F, CF_EDGE_ATTR);
370 case iro_Start: break;
373 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
374 fprintf (F, CF_EDGE_ATTR);
375 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
376 fprintf (F, MEM_EDGE_ATTR);
379 case iro_EndReg: break;
380 case iro_EndExcept: break;
382 case iro_Break: break;
383 case iro_Cond: break;
386 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
388 case iro_Const: break;
389 case iro_SymConst:break;
392 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
394 case iro_CallBegin: break;
397 case iro_Minus: break;
403 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
411 case iro_Shrs: break;
414 case iro_Conv: break;
416 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
422 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
425 fprintf (F, MEM_EDGE_ATTR);
427 case iro_Tuple: break;
430 switch (get_irn_modecode(from)) {
432 fprintf (F, CF_EDGE_ATTR);
435 fprintf (F, MEM_EDGE_ATTR);
441 case iro_Unknown: break;
448 /* dump edges to our inputs */
450 dump_ir_data_edges(ir_node *n) {
451 int i, visited = get_irn_visited(n);
453 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
456 for (i = 0; i < get_irn_arity(n); i++) {
457 ir_node * pred = get_irn_n(n, i);
459 if ((interprocedural_view && get_irn_visited(pred) < visited))
460 continue; /* pred not dumped */
461 if (is_backedge(n, i))
462 fprintf (F, "backedge: {sourcename: \"");
464 fprintf (F, "edge: {sourcename: \"");
466 fprintf (F, "\" targetname: ");
467 if ((get_opt_dump_const_local()) && is_constlike_node(pred))
469 PRINT_CONSTID(n,pred);
472 {fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
474 fprintf (F, " label: \"%d\" ", i);
475 print_edge_vcgattr(n, i);
482 dump_out_edge (ir_node *n, void* env) {
484 for (i = 0; i < get_irn_n_outs(n); i++) {
485 assert(get_irn_out(n, i));
486 fprintf (F, "edge: {sourcename: \"");
488 fprintf (F, "\" targetname: \"");
489 PRINT_NODEID(get_irn_out(n, i));
490 fprintf (F, "\" color: red linestyle: dashed");
496 dump_loop_node_edge (ir_loop *loop, int i) {
498 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", (void*) loop);
499 PRINT_NODEID(get_loop_node(loop, i));
500 fprintf (F, "\" color: green");
505 void dump_loops (ir_loop *loop) {
507 /* dump this loop node */
508 fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
509 (void*)loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
510 /* dump edges to nodes in loop -- only if it is a real loop */
511 if (get_loop_depth(loop) != 0) {
512 for (i = 0; i < get_loop_n_nodes(loop); i++) {
513 dump_loop_node_edge(loop, i);
516 for (i = 0; i < get_loop_n_sons(loop); i++) {
517 dump_loops(get_loop_son(loop, i));
522 void dump_loop_info(ir_graph *irg) {
523 ir_graph *rem = current_ir_graph;
524 current_ir_graph = irg;
526 if (get_irg_loop(irg))
527 dump_loops(get_irg_loop(irg));
529 current_ir_graph = rem;
533 /* dumps the edges between nodes and their type or entity attributes. */
534 static void dump_node2type_edges (ir_node *n, void *env)
538 switch (get_irn_opcode(n)) {
540 /* @@@ some consts have an entity */
543 if ( (get_SymConst_kind(n) == type_tag)
544 || (get_SymConst_kind(n) == size))
546 PRINT_NODE_TYPE_EDGE(n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
550 PRINT_NODE_ENT_EDGE(n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
553 PRINT_NODE_TYPE_EDGE(n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
556 PRINT_NODE_TYPE_EDGE(n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
559 PRINT_NODE_TYPE_EDGE(n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
562 PRINT_NODE_TYPE_EDGE(n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
570 static void dump_const_expression(ir_node *value) {
571 ir_graph *rem = current_ir_graph;
572 int rem_dump_const_local = dump_const_local;
573 dump_const_local = 0;
574 current_ir_graph = get_const_code_irg();
575 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
576 /* Decrease visited flag so that we walk with the same flag for the next
577 expresssion. This guarantees that we don't dump the same node twice,
578 as for const expressions cse is performed to save memory. */
579 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
580 current_ir_graph = rem;
581 dump_const_local = rem_dump_const_local;
585 static void print_type_info(type *tp) {
586 if (get_type_state(tp) == layout_undefined) {
587 fprintf(F, "state: layout_undefined\n");
589 fprintf(F, "state: layout_fixed,\n");
591 if (get_type_mode(tp))
592 fprintf(F, "mode: %s,\n", id_to_str(get_mode_ident(get_type_mode(tp))));
593 fprintf(F, "size: %dB,\n", get_type_size(tp));
597 static void print_typespecific_info(type *tp) {
598 switch (get_type_tpop_code(tp)) {
601 if(existent == get_class_peculiarity(tp))
602 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
604 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
608 fprintf (F, " " TYPE_METH_NODE_ATTR);
619 case tpo_enumeration:
632 static void print_type_node(type *tp) {
633 fprintf (F, "node: {title: ");
635 fprintf (F, " label: \"%s %s\"", id_to_str(get_type_tpop_nameid(tp)), id_to_str(get_type_ident(tp)));
636 fprintf (F, " info1: \"");
639 print_typespecific_info(tp);
643 void dump_entity_node(entity *ent) {
644 fprintf (F, "node: {title: \"");
645 PRINT_ENTID(ent); fprintf(F, "\"");
646 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
647 fprintf (F, "label: ");
648 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , id_to_str(get_entity_ident(ent)));
649 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
650 fprintf (F, "\nallocation: ");
651 switch (get_entity_allocation(ent)) {
652 case dynamic_allocated: fprintf (F, "dynamic allocated"); break;
653 case automatic_allocated: fprintf (F, "automatic allocated"); break;
654 case static_allocated: fprintf (F, "static allocated"); break;
655 case parameter_allocated: fprintf (F, "parameter allocated"); break;
657 fprintf (F, "\nvisibility: ");
658 switch (get_entity_visibility(ent)) {
659 case local: fprintf (F, "local"); break;
660 case external_visible: fprintf (F, "external visible"); break;
661 case external_allocated: fprintf (F, "external allocated"); break;
663 fprintf (F, "\nvariability: ");
664 switch (get_entity_variability(ent)) {
665 case uninitialized: fprintf (F, "uninitialized");break;
666 case initialized: fprintf (F, "initialized"); break;
667 case part_constant: fprintf (F, "part_constant");break;
668 case constant: fprintf (F, "constant"); break;
670 fprintf (F, "\nvolatility: ");
671 switch (get_entity_volatility(ent)) {
672 case non_volatile: fprintf (F, "non_volatile"); break;
673 case is_volatile: fprintf (F, "is_volatile"); break;
675 fprintf (F, "\npeculiarity: ");
676 switch (get_entity_peculiarity(ent)) {
677 case description: fprintf (F, "description"); break;
678 case inherited: fprintf (F, "inherited"); break;
679 case existent: fprintf (F, "existent"); break;
681 fprintf(F, "\nname: %s\nld_name: %s",
682 id_to_str(get_entity_ident(ent)),
683 id_to_str(get_entity_ld_ident(ent)));
684 fprintf(F, "\noffset: %d", get_entity_offset(ent));
685 if (is_method_type(get_entity_type(ent))) {
686 if (get_entity_irg(ent)) /* can be null */
687 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
689 { fprintf (F, "\nirg = NULL"); }
691 fprintf(F, "\"\n}\n");
694 /* dumps a type or entity and it's edges. */
696 dump_type_info (type_or_ent *tore, void *env) {
697 int i = 0; /* to shutup gcc */
699 /* dump this type or entity */
701 switch (get_kind(tore)) {
704 entity *ent = (entity *)tore;
707 dump_entity_node(ent);
709 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
710 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
711 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
712 PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
713 if(is_class_type(get_entity_owner(ent))) {
714 for(i = 0; i < get_entity_n_overwrites(ent); i++){
715 PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
718 /* attached subgraphs */
719 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
720 if (is_atomic_entity(ent)) {
721 value = get_atomic_ent_value(ent);
723 PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
724 /* DDMN(value); $$$ */
725 dump_const_expression(value);
728 if (is_compound_entity(ent)) {
729 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
730 value = get_compound_ent_value(ent, i);
732 PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
733 dump_const_expression(value);
734 PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
736 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
737 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
738 get_compound_ent_value_member(ent, i), i);
747 type *tp = (type *)tore;
749 /* and now the edges */
750 switch (get_type_tpop_code(tp)) {
753 for (i=0; i < get_class_n_supertypes(tp); i++) {
754 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
757 for (i=0; i < get_class_n_members(tp); i++) {
758 PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
763 for (i=0; i < get_struct_n_members(tp); i++) {
764 PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
769 for (i = 0; i < get_method_n_params(tp); i++)
771 PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
773 for (i = 0; i < get_method_n_ress(tp); i++)
775 PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
780 for (i = 0; i < get_union_n_members(tp); i++)
782 PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
787 PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
788 PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
789 for (i = 0; i < get_array_n_dimensions(tp); i++) {
790 ir_node *upper = get_array_upper_bound(tp, i);
791 ir_node *lower = get_array_lower_bound(tp, i);
792 PRINT_NODE_TYPE_EDGE(upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
793 PRINT_NODE_TYPE_EDGE(lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
794 dump_const_expression(upper);
795 dump_const_expression(lower);
799 case tpo_enumeration:
804 PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
812 break; /* case k_type */
815 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
817 } /* switch kind_or_entity */
820 /* dumps a class type node and a superclass edge.
821 If env != null dumps entities of classes and overwrites edges. */
823 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
824 int i = 0; /* to shutup gcc */
826 /* dump this type or entity */
827 switch (get_kind(tore)) {
829 entity *ent = (entity *)tore;
830 if (get_entity_owner(ent) == get_glob_type()) break;
831 if ((env) && is_class_type(get_entity_owner(ent))) {
833 dump_entity_node(ent);
835 PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
836 for(i = 0; i < get_entity_n_overwrites(ent); i++)
838 PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
841 } break; /* case k_entity */
844 type *tp = (type *)tore;
845 if (tp == get_glob_type()) break;
846 switch (get_type_tpop_code(tp)) {
849 /* and now the edges */
850 for (i=0; i < get_class_n_supertypes(tp); i++)
852 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
858 break; /* case k_type */
861 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
863 } /* switch kind_or_entity */
866 /************************************************************************/
867 /* open and close vcg file */
868 /************************************************************************/
870 static void vcg_open (ir_graph *irg, char *suffix) {
871 char *fname; /* filename to put the vcg information in */
878 /** open file for vcg graph */
879 ent = get_irg_ent(irg);
880 id = ent->ld_name ? ent->ld_name : ent->name;
881 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
882 len = id_to_strlen (id);
884 if (dump_file_suffix)
885 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
887 fname = malloc (len + 5 + strlen(suffix));
888 strncpy (fname, cp, len); /* copy the filename */
890 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
891 strcat (fname, suffix); /* append file suffix */
892 strcat (fname, ".vcg"); /* append the .vcg suffix */
893 F = fopen (fname, "w"); /* open file for writing */
895 panic ("cannot open %s for writing (%m)", fname); /* not reached */
899 strcpy(label, "yes");
901 strcpy (label, "no");
906 "graph: { title: \"ir graph of %s\"\n"
907 "display_edge_labels: %s\n"
908 "layoutalgorithm: mindepth\n"
909 "manhattan_edges: yes\n"
911 "orientation: bottom_to_top\n"
912 "classname 1: \"Data\"\n"
913 "classname 2: \"Block\"\n"
914 "classname 3: \"Entity type\"\n"
915 "classname 4: \"Entity owner\"\n"
916 "classname 5: \"Method Param\"\n"
917 "classname 6: \"Method Res\"\n"
918 "classname 7: \"Super\"\n"
919 "classname 8: \"Union\"\n"
920 "classname 9: \"Points-to\"\n"
921 "classname 10: \"Array Element Type\"\n"
922 "classname 11: \"Overwrites\"\n"
923 "classname 12: \"Member\"\n"
926 fprintf (F, "\n"); /* a separator */
929 static void vcg_open_name (const char *name) {
930 char *fname; /* filename to put the vcg information in */
934 /** open file for vcg graph */
936 fname = malloc (len + 5);
937 if (dump_file_suffix)
938 fname = malloc (len + 5 + strlen(dump_file_suffix));
940 fname = malloc (len + 5);
941 strcpy (fname, name); /* copy the filename */
942 if (dump_file_suffix) strcat (fname, dump_file_suffix);
943 strcat (fname, ".vcg"); /* append the .vcg suffix */
944 F = fopen (fname, "w"); /* open file for writing */
946 panic ("cannot open %s for writing (%m)", fname); /* not reached */
950 strcpy(label, "yes");
952 strcpy (label, "no");
957 "graph: { title: \"ir graph of %s\"\n"
958 "display_edge_labels: %s\n"
959 "layoutalgorithm: mindepth\n"
960 "manhattan_edges: yes\n"
962 "orientation: bottom_to_top\n"
963 "classname 1: \"Data\"\n"
964 "classname 2: \"Block\"\n"
965 "classname 3: \"Entity type\"\n"
966 "classname 4: \"Entity owner\"\n"
967 "classname 5: \"Method Param\"\n"
968 "classname 6: \"Method Res\"\n"
969 "classname 7: \"Super\"\n"
970 "classname 8: \"Union\"\n"
971 "classname 9: \"Points-to\"\n"
972 "classname 10: \"Array Element Type\"\n"
973 "classname 11: \"Overwrites\"\n"
974 "classname 12: \"Member\"\n"
977 fprintf (F, "\n"); /* a separator */
982 fprintf (F, "}\n"); /* print footer */
983 fclose (F); /* close vcg file */
986 /************************************************************************/
987 /* routines to dump a graph, blocks as conventional nodes. */
988 /************************************************************************/
990 static int node_floats(ir_node *n) {
991 return ((get_op_pinned(get_irn_op(n)) == floats) &&
992 (get_irg_pinned(current_ir_graph) == floats));
996 dump_whole_node (ir_node *n, void* env) {
998 if (!node_floats(n)) dump_ir_block_edge(n);
999 dump_ir_data_edges(n);
1003 dump_ir_graph (ir_graph *irg)
1006 rem = current_ir_graph;
1007 current_ir_graph = irg;
1011 /* walk over the graph */
1012 /* dump_whole_node must be called in post visiting predecessors */
1013 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1015 /* dump the out edges in a separate walk */
1016 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1017 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1022 current_ir_graph = rem;
1025 /***********************************************************************/
1026 /* the following routines dump the nodes as attached to the blocks. */
1027 /***********************************************************************/
1030 dump_ir_blocks_nodes (ir_node *n, void *env) {
1031 ir_node *block = (ir_node *)env;
1033 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1035 dump_ir_data_edges(n);
1037 if (get_irn_op(n) == op_Bad)
1042 dump_ir_block (ir_node *block, void *env) {
1043 ir_graph *irg = (ir_graph *)env;
1045 if (get_irn_opcode(block) == iro_Block) {
1047 /* This is a block. So dump the vcg information to make a block. */
1048 fprintf(F, "graph: { title: \"");
1049 PRINT_NODEID(block);
1050 fprintf(F, "\" label: \"");
1051 #ifdef DEBUG_libfirm
1052 fprintf (F, "%ld", get_irn_node_nr(block));
1054 fprintf (F, "%s", get_op_name(get_irn_op(block)));
1056 if (exc_normal != get_Block_exc (block))
1057 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1059 fprintf(F, "\" status:clustered color:%s \n",
1060 get_Block_matured (block) ? "yellow" : "red");
1061 /* dump the blocks edges */
1062 dump_ir_data_edges(block);
1064 /* dump the nodes that go into the block */
1065 irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1067 /* Close the vcg information for the block */
1068 fprintf(F, "}\n\n");
1069 dump_const_node_local(block, NULL);
1075 dump_blockless_nodes (ir_node *n, void *env) {
1076 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1078 dump_ir_data_edges(n);
1079 dump_ir_block_edge(n);
1080 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1083 if (node_floats(n)) {
1085 dump_ir_data_edges(n);
1086 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1090 static void dump_ir_block_graph_2 (ir_graph *irg)
1093 /* walk over the blocks in the graph */
1094 irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1096 /* dump all nodes that are not in a Block */
1097 irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1099 /* dump the Bad node */
1101 dump_node(get_irg_bad(irg), NULL);
1105 dump_ir_block_graph (ir_graph *irg)
1108 rem = current_ir_graph;
1109 current_ir_graph = irg;
1113 dump_ir_block_graph_2 (irg);
1115 if (dump_loop_information_flag) dump_loop_info(irg);
1118 current_ir_graph = rem;
1122 /***********************************************************************/
1123 /* the following routines dump a control flow graph */
1124 /***********************************************************************/
1128 dump_block_to_cfg (ir_node *block, void *env) {
1132 if (get_irn_opcode(block) == iro_Block) {
1133 /* This is a block. Dump a node for the block. */
1134 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1135 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1136 #ifdef DEBUG_libfirm
1137 fprintf (F, "%ld", get_irn_node_nr(block));
1139 fprintf (F, "%p", (void*) block);
1142 if (exc_normal != get_Block_exc (block))
1143 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1146 if (dump_dominator_information_flag)
1147 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1149 /* Dump the edges */
1150 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1151 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1152 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1153 fprintf (F, "edge: { sourcename: \"");
1154 PRINT_NODEID(block);
1155 fprintf (F, "\" targetname: \"");
1157 fprintf (F, "\"}\n");
1160 /* Dump dominator edge */
1161 if (dump_dominator_information_flag && get_Block_idom(block)) {
1162 pred = get_Block_idom(block);
1163 fprintf (F, "edge: { sourcename: \"");
1164 PRINT_NODEID(block);
1165 fprintf (F, "\" targetname: \"");
1167 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1173 dump_cfg (ir_graph *irg)
1175 ir_graph *rem = current_ir_graph;
1176 int ddif = dump_dominator_information_flag;
1177 current_ir_graph = irg;
1178 vcg_open (irg, "-cfg");
1180 if (get_irg_dom_state(irg) != dom_consistent)
1181 dump_dominator_information_flag = 0;
1183 /* walk over the blocks in the graph */
1184 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1185 dump_node (get_irg_bad(irg), NULL);
1187 dump_dominator_information_flag = ddif;
1189 current_ir_graph = rem;
1193 /***********************************************************************/
1194 /* the following routine dumps all type information reachable from an */
1196 /***********************************************************************/
1200 dump_type_graph (ir_graph *irg)
1203 rem = current_ir_graph;
1204 current_ir_graph = irg;
1206 vcg_open (irg, "-type");
1208 /* walk over the blocks in the graph */
1209 type_walk_irg(irg, dump_type_info, NULL, NULL);
1210 /* The walker for the const code can be called several times for the
1211 same (sub) experssion. So that no nodes are dumped several times
1212 we decrease the visited flag of the corresponding graph after each
1213 walk. So now increase it finally. */
1214 inc_irg_visited(get_const_code_irg());
1217 current_ir_graph = rem;
1220 /***********************************************************************/
1221 /* the following routine dumps all type information */
1222 /***********************************************************************/
1226 dump_all_types (void)
1228 vcg_open_name ("All_types");
1229 type_walk(dump_type_info, NULL, NULL);
1230 inc_irg_visited(get_const_code_irg());
1235 dump_class_hierarchy (bool entities)
1237 vcg_open_name ("class_hierarchy");
1239 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1241 type_walk(dump_class_hierarchy_node, NULL, NULL);
1245 /***********************************************************************/
1246 /* dumps a graph with type information */
1247 /***********************************************************************/
1251 dump_ir_graph_w_types (ir_graph *irg)
1254 rem = current_ir_graph;
1255 current_ir_graph = irg;
1257 vcg_open (irg, "-all");
1259 /* dump common ir graph */
1260 irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1261 /* dump type info */
1262 type_walk_irg(irg, dump_type_info, NULL, NULL);
1263 inc_irg_visited(get_const_code_irg());
1264 /* dump edges from graph to type info */
1265 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1268 current_ir_graph = rem;
1272 dump_ir_block_graph_w_types (ir_graph *irg)
1275 rem = current_ir_graph;
1276 current_ir_graph = irg;
1278 vcg_open (irg, "-all");
1280 /* dump common blocked ir graph */
1281 dump_ir_block_graph_2(irg);
1282 /* dump type info */
1283 type_walk_irg(irg, dump_type_info, NULL, NULL);
1284 inc_irg_visited(get_const_code_irg());
1285 /* dump edges from graph to type info */
1286 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1289 current_ir_graph = rem;
1292 /***********************************************************************/
1293 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1295 /* dump_ir_block_graph */
1297 /* dump_type_graph */
1298 /* dump_ir_graph_w_types */
1299 /***********************************************************************/
1300 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1302 for (i=0; i < get_irp_n_irgs(); i++) {
1303 dump_graph(get_irp_irg(i));
1308 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1309 abort with a segmentation fault. */
1310 void turn_off_edge_labels(void) {
1315 void dump_consts_local(bool b) {
1316 dump_const_local = b;
1319 void turn_off_constant_entity_values(void) {
1323 void dump_keepalive_edges(bool b) {
1327 bool get_opt_dump_keepalive_edges(void) {
1328 return dump_keepalive;
1331 void dump_out_edges(void) {
1332 dump_out_edge_flag = 1;
1335 void dump_dominator_information(void) {
1336 dump_dominator_information_flag = 1;
1339 void dump_loop_information(void) {
1340 dump_loop_information_flag = 1;
1343 void dont_dump_loop_information(void) {
1344 dump_loop_information_flag = 0;
1347 static void clear_link(ir_node * node, void * env) {
1348 set_irn_link(node, NULL);
1351 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1352 assert(node); assert(map);
1354 || node_floats(node)
1355 || get_irn_op(node) == op_Bad
1356 || get_irn_op(node) == op_Unknown) {
1357 pmap_entry * entry = pmap_find(map, current_ir_graph);
1363 ARR_APP1(ir_node *, arr , node);
1365 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1368 pmap_insert(map, current_ir_graph, arr);
1371 ir_node * block = get_nodes_Block(node);
1372 set_irn_link(node, get_irn_link(block));
1373 set_irn_link(block, node);
1378 static void dump_cg_ir_block(ir_node * block, void * env) {
1380 pmap *irgmap = (pmap *)env;
1381 assert(is_Block(block));
1382 fprintf(F, "graph: { title: \"");
1383 PRINT_NODEID(block);
1384 fprintf(F, "\" label: \"");
1385 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1386 #ifdef DEBUG_libfirm
1387 fprintf (F, "%ld", get_irn_node_nr(block));
1389 fprintf (F, "%p", (void*) block);
1391 if (exc_normal != get_Block_exc(block)) {
1392 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1395 fprintf(F, "\" status:clustered color:%s \n",
1396 get_Block_matured(block) ? "yellow" : "red");
1398 /* dump the blocks edges */
1399 dump_ir_data_edges(block);
1401 /* dump the nodes that go into the block */
1402 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1403 dump_node(node, irgmap);
1404 dump_ir_data_edges(node);
1407 /* Close the vcg information for the block */
1408 fprintf(F, "}\n\n");
1411 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1414 fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
1415 (void*) irg, id_to_str(get_entity_ident(get_irg_ent(irg))));
1417 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1418 ir_node * node = arr[i];
1419 if (is_Block(node)) {
1420 /* Dumps the block and all the nodes in the block , which are to
1421 be found in Block->link. */
1422 dump_cg_ir_block(node, irgmap);
1424 /* Nodes that are not in a Block. */
1425 dump_node(node, NULL);
1426 dump_ir_data_edges(node);
1429 /* Close the vcg information for the irg */
1430 fprintf(F, "}\n\n");
1433 /* dump interprocedural graph with surrounding methods */
1434 void dump_cg_block_graph(ir_graph * irg) {
1435 pmap * map = pmap_create();
1436 pmap * map2 = pmap_create();
1441 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1442 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1443 pmap_insert(map2, entry->key, entry->value);
1444 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1445 d_cg_block_graph(entry->key, entry->value, map2);
1446 DEL_ARR_F(entry->value);
1452 if (dump_loop_information_flag) dump_loop_info(irg);
1456 static void collect_node(ir_node * node, void *env) {
1458 || node_floats(node)
1459 || get_irn_op(node) == op_Bad
1460 || get_irn_op(node) == op_Unknown) {
1461 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1462 ARR_APP1(ir_node *, arr, node);
1463 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1465 ir_node * block = get_nodes_Block(node);
1466 set_irn_link(node, get_irn_link(block));
1467 set_irn_link(block, node);
1471 /* Links all nodes that have the block field set in the link field of
1472 the block. Adds all blocks and nodes not associated with a block
1473 in a array in irg->link. */
1474 static void collect_nodes(void) {
1476 for (i = 0; i < get_irp_n_irgs(); i++)
1477 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1478 cg_walk(clear_link, collect_node, NULL);
1481 static void dump_graphs(void) {
1483 for (i = 0; i < get_irp_n_irgs(); i++) {
1484 current_ir_graph = get_irp_irg(i);
1485 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1489 /* Dump all irgs in interprocedural view to a single file. */
1490 void dump_all_cg_block_graph(void) {
1492 int rem_view = interprocedural_view;
1493 interprocedural_view = 1;
1494 vcg_open_name ("All_graphs");
1499 if (dump_loop_information_flag)
1500 for (i = 0; i < get_irp_n_irgs(); i++)
1501 dump_loop_info(get_irp_irg(i));
1504 interprocedural_view = rem_view;
1507 /* dump interprocedural block graph with surrounding methods */
1508 void dump_cg_graph(ir_graph * irg) {
1509 pmap * map = pmap_create();
1510 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1514 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1515 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1516 pmap_insert(map2, entry->key, entry->value);
1517 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1518 ir_node ** arr = entry->value;
1520 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1522 fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1523 id_to_str(irg_ident), id_to_str(irg_ident));
1525 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1526 ir_node * node = arr[i];
1527 dump_node(node, map2);
1528 dump_ir_data_edges(node);
1529 if (is_Block(node)) {
1530 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1531 dump_node(node, map2);
1532 dump_ir_block_edge(node);
1533 dump_ir_data_edges(node);
1540 /* Close the vcg information for the irg */
1541 fprintf(F, "}\n\n");