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 static void dump_const_expression(ir_node *value) {
565 ir_graph *rem = current_ir_graph;
566 int rem_dump_const_local = dump_const_local;
567 dump_const_local = 0;
568 current_ir_graph = get_const_code_irg();
569 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
570 /* Decrease visited flag so that we walk with the same flag for the next
571 expresssion. This guarantees that we don't dump the same node twice,
572 as for const expressions cse is performed to save memory. */
573 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
574 current_ir_graph = rem;
575 dump_const_local = rem_dump_const_local;
579 static void print_type_info(type *tp) {
580 if (get_type_state(tp) == layout_undefined) {
581 fprintf(F, "state: layout_undefined\n");
583 fprintf(F, "state: layout_fixed,\n");
585 if (get_type_mode(tp))
586 fprintf(F, "mode: %s,\n", id_to_str(get_mode_ident(get_type_mode(tp))));
587 fprintf(F, "size: %dB,\n", get_type_size(tp));
591 static void print_typespecific_info(type *tp) {
592 switch (get_type_tpop_code(tp)) {
595 if(existent == get_class_peculiarity(tp))
596 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
598 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
602 fprintf (F, " " TYPE_METH_NODE_ATTR);
613 case tpo_enumeration:
626 static void print_type_node(type *tp) {
627 fprintf (F, "node: {title: ");
629 fprintf (F, " label: \"%s %s\"", id_to_str(get_type_tpop_nameid(tp)), id_to_str(get_type_ident(tp)));
630 fprintf (F, " info1: \"");
633 print_typespecific_info(tp);
637 void dump_entity_node(entity *ent) {
638 fprintf (F, "node: {title: \"");
639 PRINT_ENTID(ent); fprintf(F, "\"");
640 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
641 fprintf (F, "label: ");
642 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , id_to_str(get_entity_ident(ent)));
643 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
644 fprintf (F, "\nallocation: ");
645 switch (get_entity_allocation(ent)) {
646 case dynamic_allocated: fprintf (F, "dynamic allocated"); break;
647 case automatic_allocated: fprintf (F, "automatic allocated"); break;
648 case static_allocated: fprintf (F, "static allocated"); break;
649 case parameter_allocated: fprintf (F, "parameter allocated"); break;
651 fprintf (F, "\nvisibility: ");
652 switch (get_entity_visibility(ent)) {
653 case local: fprintf (F, "local"); break;
654 case external_visible: fprintf (F, "external visible"); break;
655 case external_allocated: fprintf (F, "external allocated"); break;
657 fprintf (F, "\nvariability: ");
658 switch (get_entity_variability(ent)) {
659 case uninitialized: fprintf (F, "uninitialized");break;
660 case initialized: fprintf (F, "initialized"); break;
661 case part_constant: fprintf (F, "part_constant");break;
662 case constant: fprintf (F, "constant"); break;
664 fprintf (F, "\nvolatility: ");
665 switch (get_entity_volatility(ent)) {
666 case non_volatile: fprintf (F, "non_volatile"); break;
667 case is_volatile: fprintf (F, "is_volatile"); break;
669 fprintf (F, "\npeculiarity: ");
670 switch (get_entity_peculiarity(ent)) {
671 case description: fprintf (F, "description"); break;
672 case inherited: fprintf (F, "inherited"); break;
673 case existent: fprintf (F, "existent"); break;
675 fprintf(F, "\nname: %s\nld_name: %s",
676 id_to_str(get_entity_ident(ent)),
677 id_to_str(get_entity_ld_ident(ent)));
678 fprintf(F, "\noffset: %d", get_entity_offset(ent));
679 if (is_method_type(get_entity_type(ent))) {
680 if (get_entity_irg(ent)) /* can be null */
681 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
683 { fprintf (F, "\nirg = NULL"); }
685 fprintf(F, "\"\n}\n");
688 /* dumps a type or entity and it's edges. */
690 dump_type_info (type_or_ent *tore, void *env) {
691 int i = 0; /* to shutup gcc */
693 /* dump this type or entity */
695 switch (get_kind(tore)) {
698 entity *ent = (entity *)tore;
701 dump_entity_node(ent);
703 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
704 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
705 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
706 PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
707 if(is_class_type(get_entity_owner(ent))) {
708 for(i = 0; i < get_entity_n_overwrites(ent); i++){
709 PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
712 /* attached subgraphs */
713 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
714 if (is_atomic_entity(ent)) {
715 value = get_atomic_ent_value(ent);
717 PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
718 /* DDMN(value); $$$ */
719 dump_const_expression(value);
722 if (is_compound_entity(ent)) {
723 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
724 value = get_compound_ent_value(ent, i);
726 PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
727 dump_const_expression(value);
728 PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
730 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
731 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
732 get_compound_ent_value_member(ent, i), i);
741 type *tp = (type *)tore;
743 /* and now the edges */
744 switch (get_type_tpop_code(tp)) {
747 for (i=0; i < get_class_n_supertypes(tp); i++) {
748 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
751 for (i=0; i < get_class_n_members(tp); i++) {
752 PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
757 for (i=0; i < get_struct_n_members(tp); i++) {
758 PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
763 for (i = 0; i < get_method_n_params(tp); i++)
765 PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
767 for (i = 0; i < get_method_n_ress(tp); i++)
769 PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
774 for (i = 0; i < get_union_n_members(tp); i++)
776 PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
781 PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
782 PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
783 for (i = 0; i < get_array_n_dimensions(tp); i++) {
784 ir_node *upper = get_array_upper_bound(tp, i);
785 ir_node *lower = get_array_lower_bound(tp, i);
786 PRINT_NODE_TYPE_EDGE(upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
787 PRINT_NODE_TYPE_EDGE(lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
788 dump_const_expression(upper);
789 dump_const_expression(lower);
793 case tpo_enumeration:
798 PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
806 break; /* case k_type */
809 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
811 } /* switch kind_or_entity */
814 /* dumps a class type node and a superclass edge.
815 If env != null dumps entities of classes and overwrites edges. */
817 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
818 int i = 0; /* to shutup gcc */
820 /* dump this type or entity */
821 switch (get_kind(tore)) {
823 entity *ent = (entity *)tore;
824 if (get_entity_owner(ent) == get_glob_type()) break;
825 if ((env) && is_class_type(get_entity_owner(ent))) {
827 dump_entity_node(ent);
829 PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
830 for(i = 0; i < get_entity_n_overwrites(ent); i++)
832 PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
835 } break; /* case k_entity */
838 type *tp = (type *)tore;
839 if (tp == get_glob_type()) break;
840 switch (get_type_tpop_code(tp)) {
843 /* and now the edges */
844 for (i=0; i < get_class_n_supertypes(tp); i++)
846 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
852 break; /* case k_type */
855 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
857 } /* switch kind_or_entity */
860 /************************************************************************/
861 /* open and close vcg file */
862 /************************************************************************/
864 static void vcg_open (ir_graph *irg, char *suffix) {
865 char *fname; /* filename to put the vcg information in */
872 /** open file for vcg graph */
873 ent = get_irg_ent(irg);
874 id = ent->ld_name ? ent->ld_name : ent->name;
875 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
876 len = id_to_strlen (id);
878 if (dump_file_suffix)
879 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
881 fname = malloc (len + 5 + strlen(suffix));
882 strncpy (fname, cp, len); /* copy the filename */
884 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
885 strcat (fname, suffix); /* append file suffix */
886 strcat (fname, ".vcg"); /* append the .vcg suffix */
887 F = fopen (fname, "w"); /* open file for writing */
889 panic ("cannot open %s for writing (%m)", fname); /* not reached */
893 strcpy(label, "yes");
895 strcpy (label, "no");
900 "graph: { title: \"ir graph of %s\"\n"
901 "display_edge_labels: %s\n"
902 "layoutalgorithm: mindepth\n"
903 "manhattan_edges: yes\n"
905 "orientation: bottom_to_top\n"
906 "classname 1: \"Data\"\n"
907 "classname 2: \"Block\"\n"
908 "classname 3: \"Entity type\"\n"
909 "classname 4: \"Entity owner\"\n"
910 "classname 5: \"Method Param\"\n"
911 "classname 6: \"Method Res\"\n"
912 "classname 7: \"Super\"\n"
913 "classname 8: \"Union\"\n"
914 "classname 9: \"Points-to\"\n"
915 "classname 10: \"Array Element Type\"\n"
916 "classname 11: \"Overwrites\"\n"
917 "classname 12: \"Member\"\n"
920 fprintf (F, "\n"); /* a separator */
923 static void vcg_open_name (const char *name) {
924 char *fname; /* filename to put the vcg information in */
928 /** open file for vcg graph */
930 fname = malloc (len + 5);
931 if (dump_file_suffix)
932 fname = malloc (len + 5 + strlen(dump_file_suffix));
934 fname = malloc (len + 5);
935 strcpy (fname, name); /* copy the filename */
936 if (dump_file_suffix) strcat (fname, dump_file_suffix);
937 strcat (fname, ".vcg"); /* append the .vcg suffix */
938 F = fopen (fname, "w"); /* open file for writing */
940 panic ("cannot open %s for writing (%m)", fname); /* not reached */
944 strcpy(label, "yes");
946 strcpy (label, "no");
951 "graph: { title: \"ir graph of %s\"\n"
952 "display_edge_labels: %s\n"
953 "layoutalgorithm: mindepth\n"
954 "manhattan_edges: yes\n"
956 "orientation: bottom_to_top\n"
957 "classname 1: \"Data\"\n"
958 "classname 2: \"Block\"\n"
959 "classname 3: \"Entity type\"\n"
960 "classname 4: \"Entity owner\"\n"
961 "classname 5: \"Method Param\"\n"
962 "classname 6: \"Method Res\"\n"
963 "classname 7: \"Super\"\n"
964 "classname 8: \"Union\"\n"
965 "classname 9: \"Points-to\"\n"
966 "classname 10: \"Array Element Type\"\n"
967 "classname 11: \"Overwrites\"\n"
968 "classname 12: \"Member\"\n"
971 fprintf (F, "\n"); /* a separator */
976 fprintf (F, "}\n"); /* print footer */
977 fclose (F); /* close vcg file */
980 /************************************************************************/
981 /* routines to dump a graph, blocks as conventional nodes. */
982 /************************************************************************/
984 static int node_floats(ir_node *n) {
985 return ((get_op_pinned(get_irn_op(n)) == floats) &&
986 (get_irg_pinned(current_ir_graph) == floats));
990 dump_whole_node (ir_node *n, void* env) {
992 if (!node_floats(n)) dump_ir_block_edge(n);
993 dump_ir_data_edges(n);
997 dump_ir_graph (ir_graph *irg)
1000 rem = current_ir_graph;
1001 current_ir_graph = irg;
1005 /* walk over the graph */
1006 /* dump_whole_node must be called in post visiting predecessors */
1007 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1009 /* dump the out edges in a separate walk */
1010 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1011 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1016 current_ir_graph = rem;
1019 /***********************************************************************/
1020 /* the following routines dump the nodes as attached to the blocks. */
1021 /***********************************************************************/
1024 dump_ir_blocks_nodes (ir_node *n, void *env) {
1025 ir_node *block = (ir_node *)env;
1027 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1029 dump_ir_data_edges(n);
1031 if (get_irn_op(n) == op_Bad)
1036 dump_ir_block (ir_node *block, void *env) {
1037 ir_graph *irg = (ir_graph *)env;
1039 if (get_irn_opcode(block) == iro_Block) {
1041 /* This is a block. So dump the vcg information to make a block. */
1042 fprintf(F, "graph: { title: \"");
1043 PRINT_NODEID(block);
1044 fprintf(F, "\" label: \"");
1045 #ifdef DEBUG_libfirm
1046 fprintf (F, "%ld", get_irn_node_nr(block));
1048 fprintf (F, "%s", get_op_name(get_irn_op(block)));
1050 if (exc_normal != get_Block_exc (block))
1051 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1053 fprintf(F, "\" status:clustered color:%s \n",
1054 get_Block_matured (block) ? "yellow" : "red");
1055 /* dump the blocks edges */
1056 dump_ir_data_edges(block);
1058 /* dump the nodes that go into the block */
1059 irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1061 /* Close the vcg information for the block */
1062 fprintf(F, "}\n\n");
1063 dump_const_node_local(block, NULL);
1069 dump_blockless_nodes (ir_node *n, void *env) {
1070 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1072 dump_ir_data_edges(n);
1073 dump_ir_block_edge(n);
1074 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1077 if (node_floats(n)) {
1079 dump_ir_data_edges(n);
1080 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1084 static void dump_ir_block_graph_2 (ir_graph *irg)
1087 /* walk over the blocks in the graph */
1088 irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1090 /* dump all nodes that are not in a Block */
1091 irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1093 /* dump the Bad node */
1095 dump_node(get_irg_bad(irg), NULL);
1099 dump_ir_block_graph (ir_graph *irg)
1102 rem = current_ir_graph;
1103 current_ir_graph = irg;
1107 dump_ir_block_graph_2 (irg);
1109 if (dump_loop_information_flag) dump_loop_info(irg);
1112 current_ir_graph = rem;
1116 /***********************************************************************/
1117 /* the following routines dump a control flow graph */
1118 /***********************************************************************/
1122 dump_block_to_cfg (ir_node *block, void *env) {
1126 if (get_irn_opcode(block) == iro_Block) {
1127 /* This is a block. Dump a node for the block. */
1128 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1129 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1130 #ifdef DEBUG_libfirm
1131 fprintf (F, "%ld", get_irn_node_nr(block));
1133 fprintf (F, "%p", (void*) block);
1136 if (exc_normal != get_Block_exc (block))
1137 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1140 if (dump_dominator_information_flag)
1141 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1143 /* Dump the edges */
1144 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1145 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1146 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1147 fprintf (F, "edge: { sourcename: \"");
1148 PRINT_NODEID(block);
1149 fprintf (F, "\" targetname: \"");
1151 fprintf (F, "\"}\n");
1154 /* Dump dominator edge */
1155 if (dump_dominator_information_flag && get_Block_idom(block)) {
1156 pred = get_Block_idom(block);
1157 fprintf (F, "edge: { sourcename: \"");
1158 PRINT_NODEID(block);
1159 fprintf (F, "\" targetname: \"");
1161 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1167 dump_cfg (ir_graph *irg)
1169 ir_graph *rem = current_ir_graph;
1170 int ddif = dump_dominator_information_flag;
1171 current_ir_graph = irg;
1172 vcg_open (irg, "-cfg");
1174 if (get_irg_dom_state(irg) != dom_consistent)
1175 dump_dominator_information_flag = 0;
1177 /* walk over the blocks in the graph */
1178 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1179 dump_node (get_irg_bad(irg), NULL);
1181 dump_dominator_information_flag = ddif;
1183 current_ir_graph = rem;
1187 /***********************************************************************/
1188 /* the following routine dumps all type information reachable from an */
1190 /***********************************************************************/
1194 dump_type_graph (ir_graph *irg)
1197 rem = current_ir_graph;
1198 current_ir_graph = irg;
1200 vcg_open (irg, "-type");
1202 /* walk over the blocks in the graph */
1203 type_walk_irg(irg, dump_type_info, NULL, NULL);
1204 /* The walker for the const code can be called several times for the
1205 same (sub) experssion. So that no nodes are dumped several times
1206 we decrease the visited flag of the corresponding graph after each
1207 walk. So now increase it finally. */
1208 inc_irg_visited(get_const_code_irg());
1211 current_ir_graph = rem;
1214 /***********************************************************************/
1215 /* the following routine dumps all type information */
1216 /***********************************************************************/
1220 dump_all_types (void)
1222 vcg_open_name ("All_types");
1223 type_walk(dump_type_info, NULL, NULL);
1224 inc_irg_visited(get_const_code_irg());
1229 dump_class_hierarchy (bool entities)
1231 vcg_open_name ("class_hierarchy");
1233 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1235 type_walk(dump_class_hierarchy_node, NULL, NULL);
1239 /***********************************************************************/
1240 /* dumps a graph with type information */
1241 /***********************************************************************/
1245 dump_ir_graph_w_types (ir_graph *irg)
1248 rem = current_ir_graph;
1249 current_ir_graph = irg;
1251 vcg_open (irg, "-all");
1253 /* dump common ir graph */
1254 irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1255 /* dump type info */
1256 type_walk_irg(irg, dump_type_info, NULL, NULL);
1257 inc_irg_visited(get_const_code_irg());
1258 /* dump edges from graph to type info */
1259 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1262 current_ir_graph = rem;
1266 dump_ir_block_graph_w_types (ir_graph *irg)
1269 rem = current_ir_graph;
1270 current_ir_graph = irg;
1272 vcg_open (irg, "-all");
1274 /* dump common blocked ir graph */
1275 dump_ir_block_graph_2(irg);
1276 /* dump type info */
1277 type_walk_irg(irg, dump_type_info, NULL, NULL);
1278 inc_irg_visited(get_const_code_irg());
1279 /* dump edges from graph to type info */
1280 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1283 current_ir_graph = rem;
1286 /***********************************************************************/
1287 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1289 /* dump_ir_block_graph */
1291 /* dump_type_graph */
1292 /* dump_ir_graph_w_types */
1293 /***********************************************************************/
1294 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1296 for (i=0; i < get_irp_n_irgs(); i++) {
1297 dump_graph(get_irp_irg(i));
1302 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1303 abort with a segmentation fault. */
1304 void turn_off_edge_labels(void) {
1309 void dump_consts_local(bool b) {
1310 dump_const_local = b;
1313 void turn_off_constant_entity_values(void) {
1317 void dump_keepalive_edges(bool b) {
1321 bool get_opt_dump_keepalive_edges(void) {
1322 return dump_keepalive;
1325 void dump_out_edges(void) {
1326 dump_out_edge_flag = 1;
1329 void dump_dominator_information(void) {
1330 dump_dominator_information_flag = 1;
1333 void dump_loop_information(void) {
1334 dump_loop_information_flag = 1;
1337 void dont_dump_loop_information(void) {
1338 dump_loop_information_flag = 0;
1341 static void clear_link(ir_node * node, void * env) {
1342 set_irn_link(node, NULL);
1345 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1346 assert(node); assert(map);
1348 || node_floats(node)
1349 || get_irn_op(node) == op_Bad
1350 || get_irn_op(node) == op_Unknown) {
1351 pmap_entry * entry = pmap_find(map, current_ir_graph);
1357 ARR_APP1(ir_node *, arr , node);
1359 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1362 pmap_insert(map, current_ir_graph, arr);
1365 ir_node * block = get_nodes_Block(node);
1366 set_irn_link(node, get_irn_link(block));
1367 set_irn_link(block, node);
1372 static void dump_cg_ir_block(ir_node * block, void * env) {
1374 pmap *irgmap = (pmap *)env;
1375 assert(is_Block(block));
1376 fprintf(F, "graph: { title: \"");
1377 PRINT_NODEID(block);
1378 fprintf(F, "\" label: \"");
1379 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1380 #ifdef DEBUG_libfirm
1381 fprintf (F, "%ld", get_irn_node_nr(block));
1383 fprintf (F, "%p", (void*) block);
1385 if (exc_normal != get_Block_exc(block)) {
1386 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1389 fprintf(F, "\" status:clustered color:%s \n",
1390 get_Block_matured(block) ? "yellow" : "red");
1392 /* dump the blocks edges */
1393 dump_ir_data_edges(block);
1395 /* dump the nodes that go into the block */
1396 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1397 dump_node(node, irgmap);
1398 dump_ir_data_edges(node);
1401 /* Close the vcg information for the block */
1402 fprintf(F, "}\n\n");
1405 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1408 fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
1409 (void*) irg, id_to_str(get_entity_ident(get_irg_ent(irg))));
1411 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1412 ir_node * node = arr[i];
1413 if (is_Block(node)) {
1414 /* Dumps the block and all the nodes in the block , which are to
1415 be found in Block->link. */
1416 dump_cg_ir_block(node, irgmap);
1418 /* Nodes that are not in a Block. */
1419 dump_node(node, NULL);
1420 dump_ir_data_edges(node);
1423 /* Close the vcg information for the irg */
1424 fprintf(F, "}\n\n");
1427 /* dump interprocedural graph with surrounding methods */
1428 void dump_cg_block_graph(ir_graph * irg) {
1429 pmap * map = pmap_create();
1430 pmap * map2 = pmap_create();
1435 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1436 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1437 pmap_insert(map2, entry->key, entry->value);
1438 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1439 d_cg_block_graph(entry->key, entry->value, map2);
1440 DEL_ARR_F(entry->value);
1446 if (dump_loop_information_flag) dump_loop_info(irg);
1450 static void collect_node(ir_node * node, void *env) {
1452 || node_floats(node)
1453 || get_irn_op(node) == op_Bad
1454 || get_irn_op(node) == op_Unknown) {
1455 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1456 ARR_APP1(ir_node *, arr, node);
1457 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1459 ir_node * block = get_nodes_Block(node);
1460 set_irn_link(node, get_irn_link(block));
1461 set_irn_link(block, node);
1465 /* Links all nodes that have the block field set in the link field of
1466 the block. Adds all blocks and nodes not associated with a block
1467 in a array in irg->link. */
1468 static void collect_nodes(void) {
1470 for (i = 0; i < get_irp_n_irgs(); i++)
1471 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1472 cg_walk(clear_link, collect_node, NULL);
1475 static void dump_graphs(void) {
1477 for (i = 0; i < get_irp_n_irgs(); i++) {
1478 current_ir_graph = get_irp_irg(i);
1479 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1483 /* Dump all irgs in interprocedural view to a single file. */
1484 void dump_all_cg_block_graph(void) {
1486 int rem_view = interprocedural_view;
1487 interprocedural_view = 1;
1488 vcg_open_name ("All_graphs");
1493 if (dump_loop_information_flag)
1494 for (i = 0; i < get_irp_n_irgs(); i++)
1495 dump_loop_info(get_irp_irg(i));
1498 interprocedural_view = rem_view;
1501 /* dump interprocedural block graph with surrounding methods */
1502 void dump_cg_graph(ir_graph * irg) {
1503 pmap * map = pmap_create();
1504 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1508 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1509 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1510 pmap_insert(map2, entry->key, entry->value);
1511 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1512 ir_node ** arr = entry->value;
1514 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1516 fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1517 id_to_str(irg_ident), id_to_str(irg_ident));
1519 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1520 ir_node * node = arr[i];
1521 dump_node(node, map2);
1522 dump_ir_data_edges(node);
1523 if (is_Block(node)) {
1524 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1525 dump_node(node, map2);
1526 dump_ir_block_edge(node);
1527 dump_ir_data_edges(node);
1534 /* Close the vcg information for the irg */
1535 fprintf(F, "}\n\n");