3 * File name: ir/ir/irdump.c
4 * Purpose: Write vcg representation of firm to file.
5 * Author: Martin Trapp, Christian Schaefer
6 * Modified by: Goetz Lindenmaier, Hubert Schmidt
9 * Copyright: (c) 1998-2003 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
21 # include "irnode_t.h"
22 # include "irgraph_t.h"
23 # include "entity_t.h"
25 # include "firm_common_t.h"
30 # include "typewalk.h"
33 # include "type_or_entity.h"
45 /* Attributes of nodes */
46 #define PRINT_DEFAULT_NODE_ATTR
47 #define DEFAULT_NODE_ATTR " "
48 #define DEFAULT_TYPE_ATTRIBUTE " "
50 /* Attributes of edges between Firm nodes */
51 #define BLOCK_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
52 #define CF_EDGE_ATTR "color: red"
53 #define MEM_EDGE_ATTR "color: blue"
54 #define DOMINATOR_EDGE_ATTR "color: red"
56 #define BACK_EDGE_ATTR "linestyle: dashed "
58 /* Attributes of edges between Firm nodes and type/entity nodes */
59 #define NODE2TYPE_EDGE_ATTR "class: 2 priority: 2 linestyle: dotted"
61 /* Attributes of edges in type/entity graphs. */
62 #define TYPE_METH_NODE_ATTR "color: lightyellow"
63 #define TYPE_CLASS_NODE_ATTR "color: green"
64 #define TYPE_DESCRIPTION_NODE_ATTR "color: lightgreen"
65 #define ENTITY_NODE_ATTR "color: yellow"
66 #define ENT_TYPE_EDGE_ATTR "class: 3 label: \"type\" color: red"
67 #define ENT_OWN_EDGE_ATTR "class: 4 label: \"owner\" color: black"
68 #define METH_PAR_EDGE_ATTR "class: 5 label: \"param %d\" color: green"
69 #define METH_RES_EDGE_ATTR "class: 6 label: \"res %d\" color: green"
70 #define TYPE_SUPER_EDGE_ATTR "class: 7 label: \"supertype\" color: red"
71 #define UNION_EDGE_ATTR "class: 8 label: \"component\" color: blue"
72 #define PTR_PTS_TO_EDGE_ATTR "class: 9 label: \"points to\" color:green"
73 #define ARR_ELT_TYPE_EDGE_ATTR "class: 10 label: \"arr elt tp\" color:green"
74 #define ARR_ENT_EDGE_ATTR "class: 10 label: \"arr ent\" color: green"
75 #define ENT_OVERWRITES_EDGE_ATTR "class: 11 label: \"overwrites\" color:red"
76 #define ENT_VALUE_EDGE_ATTR "label: \"value %d\""
77 #define ENT_CORR_EDGE_ATTR "label: \"value %d corresponds to \" "
78 #define TYPE_MEMBER_EDGE_ATTR "class: 12 label: \"member\" color:blue"
81 #if DEBUG_libfirm && NODEID_AS_LABEL
82 #define PRINT_NODEID(X) fprintf(F, "n%ld", get_irn_node_nr(X))
83 #define PRINT_TYPEID(X) fprintf(F, "\"t%ld\"", get_type_nr(X))
84 #define PRINT_ENTID(X) fprintf(F, "e%ld", get_entity_nr(X))
85 #define PRINT_IRGID(X) fprintf(F, "g%ld", get_irg_graph_nr(X))
86 #define PRINT_CONSTID(X,Y) fprintf(F, "\"n%ldn%ld\"", get_irn_node_nr(X),get_irn_node_nr(Y))
89 #define PRINT_NODEID(X) fprintf(F, "n%p", (void*) X)
90 #define PRINT_TYPEID(X) fprintf(F, "\"t%p\"", (void *) X)
91 #define PRINT_ENTID(X) fprintf(F, "e%p", (void*) X)
92 #define PRINT_IRGID(X) fprintf(F, "g%p",(void*) X)
93 #define PRINT_CONSTID(X,Y) fprintf(F, "\"%p%p\"", (void*) X, (void*) Y)
96 #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"); }
97 #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"); }
98 #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"); }
99 #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"); }
100 #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"); }
101 #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"); }
102 #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"); }
105 /* A suffix to manipulate the file name. */
106 char *dump_file_suffix = NULL;
108 /* file to dump to */
111 /* A compiler option to turn off edge labels */
113 /* A compiler option to turn off dumping values of constant entities */
114 int const_entities = 1;
115 /* A compiler option to dump the keep alive edges */
116 int dump_keepalive = 0;
117 /* Compiler options to dump analysis information in dump_ir_graph */
118 int dump_out_edge_flag = 0;
119 int dump_dominator_information_flag = 0;
120 int dump_loop_information_flag = 0;
121 int dump_const_local = 0;
123 INLINE bool get_opt_dump_const_local(void) {
124 if (!dump_out_edge_flag && !dump_loop_information_flag)
125 return dump_const_local;
130 /* A global variable to record output of the Bad node. */
131 static int Bad_dumped;
133 static void dump_ir_blocks_nodes (ir_node *n, void *env);
134 static void dump_whole_node(ir_node *n, void* env);
136 /*******************************************************************/
137 /* routines to dump information about a single node */
138 /*******************************************************************/
143 dump_node_opcode (ir_node *n)
149 if (get_irn_opcode(n) == iro_Const) { res = tarval_snprintf(buf, sizeof(buf), get_Const_tarval(n));
150 assert(res < sizeof(buf) && "buffer to small for tarval_snprintf");
154 } else if (get_irn_opcode(n) == iro_SymConst) {
155 if (get_SymConst_kind(n) == linkage_ptr_info) {
156 /* don't use get_SymConst_ptr_info as it mangles the name. */
157 fprintf (F, "SymC %s", get_id_str(get_SymConst_ptrinfo(n)));
159 assert(get_kind(get_SymConst_type(n)) == k_type);
160 assert(get_type_ident(get_SymConst_type(n)));
161 fprintf (F, "SymC %s ", get_id_str(get_type_ident(get_SymConst_type(n))));
162 if (get_SymConst_kind(n) == type_tag)
169 } else if (get_irn_opcode(n) == iro_Filter && !interprocedural_view) {
174 fprintf (F, "%s", get_id_str(get_irn_opident(n)));
179 dump_node_mode (ir_node *n)
181 switch (get_irn_opcode(n)) {
199 fprintf (F, "%s", get_id_str(get_mode_ident(get_irn_mode(n))));
207 dump_node_nodeattr (ir_node *n)
209 switch (get_irn_opcode(n)) {
211 if (false && interprocedural_view) {
212 fprintf (F, "%s", get_id_str(get_entity_ident(get_irg_ent(current_ir_graph))));
216 if (get_irn_opcode(get_Proj_pred(n)) == iro_Cmp) {
217 fprintf (F, "%s", get_pnc_string(get_Proj_proj(n)));
219 fprintf (F, "%ld", get_Proj_proj(n));
223 fprintf (F, "%ld", get_Filter_proj(n));
226 assert(get_kind(get_Sel_entity(n)) == k_entity);
227 fprintf (F, "%s", get_entity_name(get_Sel_entity(n)));
230 fprintf (F, "to %s", get_type_name(get_Cast_type(n)));
238 dump_node_vcgattr (ir_node *n)
240 switch (get_irn_opcode(n)) {
247 fprintf (F, "color: blue");
250 fprintf (F, "color: lightyellow");
253 fprintf (F, "color: green");
259 fprintf (F, "color: yellow");
262 PRINT_DEFAULT_NODE_ATTR;
267 dump_node_info (ir_node *n) {
269 fprintf (F, " info1: \"");
270 fprintf (F, "visited: %ld \n", get_irn_visited(n));
273 switch(get_irn_opcode(n)) {
275 type *tp = get_entity_type(get_irg_ent(get_Start_irg(n)));
276 fprintf(F, "start of method of type %s \n", get_type_name(tp));
277 for (i = 0; i < get_method_n_params(tp); ++i)
278 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
281 fprintf(F, "allocating entity of type %s \n", get_type_name(get_Alloc_type(n)));
284 fprintf(F, "freeing entity of type %s \n", get_type_name(get_Free_type(n)));
287 fprintf(F, "Selecting entity of type %s \n", get_type_name(get_entity_type(get_Sel_entity(n))));
288 fprintf(F, " from entity of type %s \n", get_type_name(get_entity_owner(get_Sel_entity(n))));
291 type *tp = get_Call_type(n);
292 fprintf(F, "calling method of type %s \n", get_type_name(tp));
293 for (i = 0; i < get_method_n_params(tp); ++i)
294 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
295 for (i = 0; i < get_method_n_ress(tp); ++i)
296 fprintf(F, " resul %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
306 static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
307 ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n);
310 ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) {
311 ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos));
312 if (is_ip_cfop(pred)) {
313 ir_graph *irg = get_ip_cfop_irg(pred);
314 if (pmap_find(irgmap, irg) == NULL) return true;
323 bool is_constlike_node(ir_node *n) {
324 ir_op *op = get_irn_op(n);
325 return (op == op_Const || op == op_Bad || op == op_SymConst);
329 static void dump_const_node_local(ir_node *n, pmap *irgmap) {
331 if (!get_opt_dump_const_local()) return;
332 /* Use visited flag to avoid outputting nodes twice.
333 initialize it first. */
334 for (i = 0; i < get_irn_arity(n); i++) {
335 ir_node *con = get_irn_n(n, i);
336 if (is_constlike_node(con)) {
337 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
338 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
341 for (i = 0; i < get_irn_arity(n); i++) {
342 ir_node *con = get_irn_n(n, i);
343 if (is_constlike_node(con) && irn_not_visited(con)) {
344 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
345 mark_irn_visited(con);
346 /* Generate a new name for the node by appending the names of
348 fprintf (F, "node: {title: "); PRINT_CONSTID(n,con);
349 fprintf(F, " label: \"");
350 dump_node_opcode(con);
351 dump_node_mode (con);
353 dump_node_nodeattr(con);
355 fprintf (F, " %ld", get_irn_node_nr(con));
358 dump_node_vcgattr(con);
366 dump_node (ir_node *n, pmap * map) {
367 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
370 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
375 dump_node_nodeattr(n);
377 fprintf (F, " %ld", get_irn_node_nr(n));
380 dump_node_vcgattr(n);
383 dump_const_node_local(n, map);
386 /* dump the edge to the block this node belongs to */
388 dump_ir_block_edge(ir_node *n) {
389 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
390 if (is_no_Block(n)) {
391 fprintf (F, "edge: { sourcename: \"");
393 fprintf (F, "\" targetname: \"");
394 PRINT_NODEID(get_nodes_Block(n));
395 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
399 static void print_edge_vcgattr(ir_node *from, int to) {
402 if (is_backedge(from, to)) fprintf (F, BACK_EDGE_ATTR);
404 switch (get_irn_opcode(from)) {
406 fprintf (F, CF_EDGE_ATTR);
408 case iro_Start: break;
411 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
412 fprintf (F, CF_EDGE_ATTR);
413 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
414 fprintf (F, MEM_EDGE_ATTR);
417 case iro_EndReg: break;
418 case iro_EndExcept: break;
420 case iro_Break: break;
421 case iro_Cond: break;
424 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
426 case iro_Const: break;
427 case iro_SymConst:break;
430 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
432 case iro_CallBegin: break;
435 case iro_Minus: break;
441 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
449 case iro_Shrs: break;
452 case iro_Conv: break;
454 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
460 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
463 fprintf (F, MEM_EDGE_ATTR);
465 case iro_Tuple: break;
468 switch (get_irn_modecode(from)) {
470 fprintf (F, CF_EDGE_ATTR);
473 fprintf (F, MEM_EDGE_ATTR);
479 case iro_Unknown: break;
486 /* dump edges to our inputs */
488 dump_ir_data_edges(ir_node *n) {
489 int i, visited = get_irn_visited(n);
491 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
494 for (i = 0; i < get_irn_arity(n); i++) {
495 ir_node * pred = get_irn_n(n, i);
497 if ((interprocedural_view && get_irn_visited(pred) < visited))
498 continue; /* pred not dumped */
499 if (is_backedge(n, i))
500 fprintf (F, "backedge: {sourcename: \"");
502 fprintf (F, "edge: {sourcename: \"");
504 fprintf (F, "\" targetname: ");
505 if ((get_opt_dump_const_local()) && is_constlike_node(pred))
507 PRINT_CONSTID(n,pred);
510 {fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
512 fprintf (F, " label: \"%d\" ", i);
513 print_edge_vcgattr(n, i);
520 dump_out_edge (ir_node *n, void* env) {
522 for (i = 0; i < get_irn_n_outs(n); i++) {
523 assert(get_irn_out(n, i));
524 fprintf (F, "edge: {sourcename: \"");
526 fprintf (F, "\" targetname: \"");
527 PRINT_NODEID(get_irn_out(n, i));
528 fprintf (F, "\" color: red linestyle: dashed");
534 dump_loop_node_edge (ir_loop *loop, int i) {
536 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", (void*) loop);
537 PRINT_NODEID(get_loop_node(loop, i));
538 fprintf (F, "\" color: green");
543 void dump_loops (ir_loop *loop) {
545 /* dump this loop node */
546 fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
547 (void*)loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
548 /* dump edges to nodes in loop -- only if it is a real loop */
549 if (get_loop_depth(loop) != 0) {
550 for (i = 0; i < get_loop_n_nodes(loop); i++) {
551 dump_loop_node_edge(loop, i);
554 for (i = 0; i < get_loop_n_sons(loop); i++) {
555 dump_loops(get_loop_son(loop, i));
560 void dump_loop_info(ir_graph *irg) {
561 ir_graph *rem = current_ir_graph;
562 current_ir_graph = irg;
564 if (get_irg_loop(irg))
565 dump_loops(get_irg_loop(irg));
567 current_ir_graph = rem;
571 /* dumps the edges between nodes and their type or entity attributes. */
572 static void dump_node2type_edges (ir_node *n, void *env)
576 switch (get_irn_opcode(n)) {
578 /* @@@ some consts have an entity */
581 if ( (get_SymConst_kind(n) == type_tag)
582 || (get_SymConst_kind(n) == size))
584 PRINT_NODE_TYPE_EDGE(n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
588 PRINT_NODE_ENT_EDGE(n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
591 PRINT_NODE_TYPE_EDGE(n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
594 PRINT_NODE_TYPE_EDGE(n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
597 PRINT_NODE_TYPE_EDGE(n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
600 PRINT_NODE_TYPE_EDGE(n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
608 static void dump_const_expression(ir_node *value) {
609 ir_graph *rem = current_ir_graph;
610 int rem_dump_const_local = dump_const_local;
611 dump_const_local = 0;
612 current_ir_graph = get_const_code_irg();
613 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
614 /* Decrease visited flag so that we walk with the same flag for the next
615 expresssion. This guarantees that we don't dump the same node twice,
616 as for const expressions cse is performed to save memory. */
617 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
618 current_ir_graph = rem;
619 dump_const_local = rem_dump_const_local;
623 static void print_type_info(type *tp) {
624 if (get_type_state(tp) == layout_undefined) {
625 fprintf(F, "state: layout_undefined\n");
627 fprintf(F, "state: layout_fixed,\n");
629 if (get_type_mode(tp))
630 fprintf(F, "mode: %s,\n", get_id_str(get_mode_ident(get_type_mode(tp))));
631 fprintf(F, "size: %dB,\n", get_type_size(tp));
635 static void print_typespecific_info(type *tp) {
636 switch (get_type_tpop_code(tp)) {
639 if(existent == get_class_peculiarity(tp))
640 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
642 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
646 fprintf (F, " " TYPE_METH_NODE_ATTR);
657 case tpo_enumeration:
670 static void print_type_node(type *tp) {
671 fprintf (F, "node: {title: ");
673 fprintf (F, " label: \"%s %s\"", get_id_str(get_type_tpop_nameid(tp)), get_id_str(get_type_ident(tp)));
674 fprintf (F, " info1: \"");
677 print_typespecific_info(tp);
681 void dump_entity_node(entity *ent) {
682 fprintf (F, "node: {title: \"");
683 PRINT_ENTID(ent); fprintf(F, "\"");
684 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
685 fprintf (F, "label: ");
686 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_id_str(get_entity_ident(ent)));
687 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
688 fprintf (F, "\nallocation: ");
689 switch (get_entity_allocation(ent)) {
690 case dynamic_allocated: fprintf (F, "dynamic allocated"); break;
691 case automatic_allocated: fprintf (F, "automatic allocated"); break;
692 case static_allocated: fprintf (F, "static allocated"); break;
693 case parameter_allocated: fprintf (F, "parameter allocated"); break;
695 fprintf (F, "\nvisibility: ");
696 switch (get_entity_visibility(ent)) {
697 case local: fprintf (F, "local"); break;
698 case external_visible: fprintf (F, "external visible"); break;
699 case external_allocated: fprintf (F, "external allocated"); break;
701 fprintf (F, "\nvariability: ");
702 switch (get_entity_variability(ent)) {
703 case uninitialized: fprintf (F, "uninitialized");break;
704 case initialized: fprintf (F, "initialized"); break;
705 case part_constant: fprintf (F, "part_constant");break;
706 case constant: fprintf (F, "constant"); break;
708 fprintf (F, "\nvolatility: ");
709 switch (get_entity_volatility(ent)) {
710 case non_volatile: fprintf (F, "non_volatile"); break;
711 case is_volatile: fprintf (F, "is_volatile"); break;
713 fprintf (F, "\npeculiarity: ");
714 switch (get_entity_peculiarity(ent)) {
715 case description: fprintf (F, "description"); break;
716 case inherited: fprintf (F, "inherited"); break;
717 case existent: fprintf (F, "existent"); break;
719 fprintf(F, "\nname: %s\nld_name: %s",
720 get_id_str(get_entity_ident(ent)),
721 get_id_str(get_entity_ld_ident(ent)));
722 fprintf(F, "\noffset: %d", get_entity_offset(ent));
723 if (is_method_type(get_entity_type(ent))) {
724 if (get_entity_irg(ent)) /* can be null */
725 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
727 { fprintf (F, "\nirg = NULL"); }
729 fprintf(F, "\"\n}\n");
732 /* dumps a type or entity and it's edges. */
734 dump_type_info (type_or_ent *tore, void *env) {
735 int i = 0; /* to shutup gcc */
737 /* dump this type or entity */
739 switch (get_kind(tore)) {
742 entity *ent = (entity *)tore;
745 dump_entity_node(ent);
747 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
748 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
749 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
750 PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
751 if(is_class_type(get_entity_owner(ent))) {
752 for(i = 0; i < get_entity_n_overwrites(ent); i++){
753 PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
756 /* attached subgraphs */
757 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
758 if (is_atomic_entity(ent)) {
759 value = get_atomic_ent_value(ent);
761 PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
762 /* DDMN(value); $$$ */
763 dump_const_expression(value);
766 if (is_compound_entity(ent)) {
767 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
768 value = get_compound_ent_value(ent, i);
770 PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
771 dump_const_expression(value);
772 PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
774 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
775 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
776 get_compound_ent_value_member(ent, i), i);
785 type *tp = (type *)tore;
787 /* and now the edges */
788 switch (get_type_tpop_code(tp)) {
791 for (i=0; i < get_class_n_supertypes(tp); i++) {
792 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
795 for (i=0; i < get_class_n_members(tp); i++) {
796 PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
801 for (i=0; i < get_struct_n_members(tp); i++) {
802 PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
807 for (i = 0; i < get_method_n_params(tp); i++)
809 PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
811 for (i = 0; i < get_method_n_ress(tp); i++)
813 PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
818 for (i = 0; i < get_union_n_members(tp); i++)
820 PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
825 PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
826 PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
827 for (i = 0; i < get_array_n_dimensions(tp); i++) {
828 ir_node *upper = get_array_upper_bound(tp, i);
829 ir_node *lower = get_array_lower_bound(tp, i);
830 PRINT_NODE_TYPE_EDGE(upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
831 PRINT_NODE_TYPE_EDGE(lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
832 dump_const_expression(upper);
833 dump_const_expression(lower);
837 case tpo_enumeration:
842 PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
850 break; /* case k_type */
853 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
855 } /* switch kind_or_entity */
858 /* dumps a class type node and a superclass edge.
859 If env != null dumps entities of classes and overwrites edges. */
861 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
862 int i = 0; /* to shutup gcc */
864 /* dump this type or entity */
865 switch (get_kind(tore)) {
867 entity *ent = (entity *)tore;
868 if (get_entity_owner(ent) == get_glob_type()) break;
869 if ((env) && is_class_type(get_entity_owner(ent))) {
871 dump_entity_node(ent);
873 PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
874 for(i = 0; i < get_entity_n_overwrites(ent); i++)
876 PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
879 } break; /* case k_entity */
882 type *tp = (type *)tore;
883 if (tp == get_glob_type()) break;
884 switch (get_type_tpop_code(tp)) {
887 /* and now the edges */
888 for (i=0; i < get_class_n_supertypes(tp); i++)
890 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
896 break; /* case k_type */
899 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
901 } /* switch kind_or_entity */
904 /************************************************************************/
905 /* open and close vcg file */
906 /************************************************************************/
908 static void vcg_open (ir_graph *irg, char *suffix) {
909 char *fname; /* filename to put the vcg information in */
916 /** open file for vcg graph */
917 ent = get_irg_ent(irg);
918 id = ent->ld_name ? ent->ld_name : ent->name;
919 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
920 len = get_id_strlen (id);
921 cp = get_id_str (id);
922 if (dump_file_suffix)
923 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
925 fname = malloc (len + 5 + strlen(suffix));
926 strncpy (fname, cp, len); /* copy the filename */
928 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
929 strcat (fname, suffix); /* append file suffix */
930 strcat (fname, ".vcg"); /* append the .vcg suffix */
931 F = fopen (fname, "w"); /* open file for writing */
933 panic ("cannot open %s for writing (%m)", fname); /* not reached */
937 strcpy(label, "yes");
939 strcpy (label, "no");
944 "graph: { title: \"ir graph of %s\"\n"
945 "display_edge_labels: %s\n"
946 "layoutalgorithm: mindepth\n"
947 "manhattan_edges: yes\n"
949 "orientation: bottom_to_top\n"
950 "classname 1: \"Data\"\n"
951 "classname 2: \"Block\"\n"
952 "classname 3: \"Entity type\"\n"
953 "classname 4: \"Entity owner\"\n"
954 "classname 5: \"Method Param\"\n"
955 "classname 6: \"Method Res\"\n"
956 "classname 7: \"Super\"\n"
957 "classname 8: \"Union\"\n"
958 "classname 9: \"Points-to\"\n"
959 "classname 10: \"Array Element Type\"\n"
960 "classname 11: \"Overwrites\"\n"
961 "classname 12: \"Member\"\n"
964 fprintf (F, "\n"); /* a separator */
967 static void vcg_open_name (const char *name) {
968 char *fname; /* filename to put the vcg information in */
972 /** open file for vcg graph */
974 fname = malloc (len + 5);
975 if (dump_file_suffix)
976 fname = malloc (len + 5 + strlen(dump_file_suffix));
978 fname = malloc (len + 5);
979 strcpy (fname, name); /* copy the filename */
980 if (dump_file_suffix) strcat (fname, dump_file_suffix);
981 strcat (fname, ".vcg"); /* append the .vcg suffix */
982 F = fopen (fname, "w"); /* open file for writing */
984 panic ("cannot open %s for writing (%m)", fname); /* not reached */
988 strcpy(label, "yes");
990 strcpy (label, "no");
995 "graph: { title: \"ir graph of %s\"\n"
996 "display_edge_labels: %s\n"
997 "layoutalgorithm: mindepth\n"
998 "manhattan_edges: yes\n"
1000 "orientation: bottom_to_top\n"
1001 "classname 1: \"Data\"\n"
1002 "classname 2: \"Block\"\n"
1003 "classname 3: \"Entity type\"\n"
1004 "classname 4: \"Entity owner\"\n"
1005 "classname 5: \"Method Param\"\n"
1006 "classname 6: \"Method Res\"\n"
1007 "classname 7: \"Super\"\n"
1008 "classname 8: \"Union\"\n"
1009 "classname 9: \"Points-to\"\n"
1010 "classname 10: \"Array Element Type\"\n"
1011 "classname 11: \"Overwrites\"\n"
1012 "classname 12: \"Member\"\n"
1015 fprintf (F, "\n"); /* a separator */
1020 fprintf (F, "}\n"); /* print footer */
1021 fclose (F); /* close vcg file */
1024 /************************************************************************/
1025 /* routines to dump a graph, blocks as conventional nodes. */
1026 /************************************************************************/
1028 static int node_floats(ir_node *n) {
1029 return ((get_op_pinned(get_irn_op(n)) == floats) &&
1030 (get_irg_pinned(current_ir_graph) == floats));
1034 dump_whole_node (ir_node *n, void* env) {
1036 if (!node_floats(n)) dump_ir_block_edge(n);
1037 dump_ir_data_edges(n);
1041 dump_ir_graph (ir_graph *irg)
1044 rem = current_ir_graph;
1045 current_ir_graph = irg;
1049 /* walk over the graph */
1050 /* dump_whole_node must be called in post visiting predecessors */
1051 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1053 /* dump the out edges in a separate walk */
1054 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1055 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1060 current_ir_graph = rem;
1063 /***********************************************************************/
1064 /* the following routines dump the nodes as attached to the blocks. */
1065 /***********************************************************************/
1068 dump_ir_blocks_nodes (ir_node *n, void *env) {
1069 ir_node *block = (ir_node *)env;
1071 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1073 dump_ir_data_edges(n);
1075 if (get_irn_op(n) == op_Bad)
1080 dump_ir_block (ir_node *block, void *env) {
1081 ir_graph *irg = (ir_graph *)env;
1083 if (get_irn_opcode(block) == iro_Block) {
1085 /* This is a block. So dump the vcg information to make a block. */
1086 fprintf(F, "graph: { title: \"");
1087 PRINT_NODEID(block);
1088 fprintf(F, "\" label: \"");
1089 #ifdef DEBUG_libfirm
1090 fprintf (F, "%ld", get_irn_node_nr(block));
1092 fprintf (F, "%s", get_op_name(get_irn_op(block)));
1094 if (exc_normal != get_Block_exc (block))
1095 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1097 fprintf(F, "\" status:clustered color:%s \n",
1098 get_Block_matured (block) ? "yellow" : "red");
1099 /* dump the blocks edges */
1100 dump_ir_data_edges(block);
1102 /* dump the nodes that go into the block */
1103 irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1105 /* Close the vcg information for the block */
1106 fprintf(F, "}\n\n");
1107 dump_const_node_local(block, NULL);
1113 dump_blockless_nodes (ir_node *n, void *env) {
1114 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1116 dump_ir_data_edges(n);
1117 dump_ir_block_edge(n);
1118 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1121 if (node_floats(n)) {
1123 dump_ir_data_edges(n);
1124 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1128 static void dump_ir_block_graph_2 (ir_graph *irg)
1131 /* walk over the blocks in the graph */
1132 irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1134 /* dump all nodes that are not in a Block */
1135 irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1137 /* dump the Bad node */
1139 dump_node(get_irg_bad(irg), NULL);
1143 dump_ir_block_graph (ir_graph *irg)
1146 rem = current_ir_graph;
1147 current_ir_graph = irg;
1151 dump_ir_block_graph_2 (irg);
1153 if (dump_loop_information_flag) dump_loop_info(irg);
1156 current_ir_graph = rem;
1160 /***********************************************************************/
1161 /* the following routines dump a control flow graph */
1162 /***********************************************************************/
1166 dump_block_to_cfg (ir_node *block, void *env) {
1170 if (get_irn_opcode(block) == iro_Block) {
1171 /* This is a block. Dump a node for the block. */
1172 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1173 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1174 #ifdef DEBUG_libfirm
1175 fprintf (F, "%ld", get_irn_node_nr(block));
1177 fprintf (F, "%p", (void*) block);
1180 if (exc_normal != get_Block_exc (block))
1181 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1184 if (dump_dominator_information_flag)
1185 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1187 /* Dump the edges */
1188 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1189 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1190 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1191 fprintf (F, "edge: { sourcename: \"");
1192 PRINT_NODEID(block);
1193 fprintf (F, "\" targetname: \"");
1195 fprintf (F, "\"}\n");
1198 /* Dump dominator edge */
1199 if (dump_dominator_information_flag && get_Block_idom(block)) {
1200 pred = get_Block_idom(block);
1201 fprintf (F, "edge: { sourcename: \"");
1202 PRINT_NODEID(block);
1203 fprintf (F, "\" targetname: \"");
1205 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1211 dump_cfg (ir_graph *irg)
1213 ir_graph *rem = current_ir_graph;
1214 int ddif = dump_dominator_information_flag;
1215 current_ir_graph = irg;
1216 vcg_open (irg, "-cfg");
1218 if (get_irg_dom_state(irg) != dom_consistent)
1219 dump_dominator_information_flag = 0;
1221 /* walk over the blocks in the graph */
1222 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1223 dump_node (get_irg_bad(irg), NULL);
1225 dump_dominator_information_flag = ddif;
1227 current_ir_graph = rem;
1231 /***********************************************************************/
1232 /* the following routine dumps all type information reachable from an */
1234 /***********************************************************************/
1238 dump_type_graph (ir_graph *irg)
1241 rem = current_ir_graph;
1242 current_ir_graph = irg;
1244 vcg_open (irg, "-type");
1246 /* walk over the blocks in the graph */
1247 type_walk_irg(irg, dump_type_info, NULL, NULL);
1248 /* The walker for the const code can be called several times for the
1249 same (sub) experssion. So that no nodes are dumped several times
1250 we decrease the visited flag of the corresponding graph after each
1251 walk. So now increase it finally. */
1252 inc_irg_visited(get_const_code_irg());
1255 current_ir_graph = rem;
1258 /***********************************************************************/
1259 /* the following routine dumps all type information */
1260 /***********************************************************************/
1264 dump_all_types (void)
1266 vcg_open_name ("All_types");
1267 type_walk(dump_type_info, NULL, NULL);
1268 inc_irg_visited(get_const_code_irg());
1273 dump_class_hierarchy (bool entities)
1275 vcg_open_name ("class_hierarchy");
1277 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1279 type_walk(dump_class_hierarchy_node, NULL, NULL);
1283 /***********************************************************************/
1284 /* dumps a graph with type information */
1285 /***********************************************************************/
1289 dump_ir_graph_w_types (ir_graph *irg)
1292 rem = current_ir_graph;
1293 current_ir_graph = irg;
1295 vcg_open (irg, "-all");
1297 /* dump common ir graph */
1298 irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1299 /* dump type info */
1300 type_walk_irg(irg, dump_type_info, NULL, NULL);
1301 inc_irg_visited(get_const_code_irg());
1302 /* dump edges from graph to type info */
1303 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1306 current_ir_graph = rem;
1310 dump_ir_block_graph_w_types (ir_graph *irg)
1313 rem = current_ir_graph;
1314 current_ir_graph = irg;
1316 vcg_open (irg, "-all");
1318 /* dump common blocked ir graph */
1319 dump_ir_block_graph_2(irg);
1320 /* dump type info */
1321 type_walk_irg(irg, dump_type_info, NULL, NULL);
1322 inc_irg_visited(get_const_code_irg());
1323 /* dump edges from graph to type info */
1324 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1327 current_ir_graph = rem;
1330 /***********************************************************************/
1331 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1333 /* dump_ir_block_graph */
1335 /* dump_type_graph */
1336 /* dump_ir_graph_w_types */
1337 /***********************************************************************/
1338 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1340 for (i=0; i < get_irp_n_irgs(); i++) {
1341 dump_graph(get_irp_irg(i));
1346 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1347 abort with a segmentation fault. */
1348 void turn_off_edge_labels(void) {
1353 void dump_consts_local(bool b) {
1354 dump_const_local = b;
1357 void turn_off_constant_entity_values(void) {
1361 void dump_keepalive_edges(bool b) {
1365 bool get_opt_dump_keepalive_edges(void) {
1366 return dump_keepalive;
1369 void dump_out_edges(void) {
1370 dump_out_edge_flag = 1;
1373 void dump_dominator_information(void) {
1374 dump_dominator_information_flag = 1;
1377 void dump_loop_information(void) {
1378 dump_loop_information_flag = 1;
1381 void dont_dump_loop_information(void) {
1382 dump_loop_information_flag = 0;
1385 static void clear_link(ir_node * node, void * env) {
1386 set_irn_link(node, NULL);
1389 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1390 assert(node); assert(map);
1392 || node_floats(node)
1393 || get_irn_op(node) == op_Bad
1394 || get_irn_op(node) == op_Unknown) {
1395 pmap_entry * entry = pmap_find(map, current_ir_graph);
1401 ARR_APP1(ir_node *, arr , node);
1403 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1406 pmap_insert(map, current_ir_graph, arr);
1409 ir_node * block = get_nodes_Block(node);
1410 set_irn_link(node, get_irn_link(block));
1411 set_irn_link(block, node);
1416 static void dump_cg_ir_block(ir_node * block, void * env) {
1418 pmap *irgmap = (pmap *)env;
1419 assert(is_Block(block));
1420 fprintf(F, "graph: { title: \"");
1421 PRINT_NODEID(block);
1422 fprintf(F, "\" label: \"");
1423 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1424 #ifdef DEBUG_libfirm
1425 fprintf (F, "%ld", get_irn_node_nr(block));
1427 fprintf (F, "%p", (void*) block);
1429 if (exc_normal != get_Block_exc(block)) {
1430 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1433 fprintf(F, "\" status:clustered color:%s \n",
1434 get_Block_matured(block) ? "yellow" : "red");
1436 /* dump the blocks edges */
1437 dump_ir_data_edges(block);
1439 /* dump the nodes that go into the block */
1440 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1441 dump_node(node, irgmap);
1442 dump_ir_data_edges(node);
1445 /* Close the vcg information for the block */
1446 fprintf(F, "}\n\n");
1449 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1452 fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
1453 (void*) irg, get_id_str(get_entity_ident(get_irg_ent(irg))));
1455 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1456 ir_node * node = arr[i];
1457 if (is_Block(node)) {
1458 /* Dumps the block and all the nodes in the block , which are to
1459 be found in Block->link. */
1460 dump_cg_ir_block(node, irgmap);
1462 /* Nodes that are not in a Block. */
1463 dump_node(node, NULL);
1464 dump_ir_data_edges(node);
1467 /* Close the vcg information for the irg */
1468 fprintf(F, "}\n\n");
1471 /* dump interprocedural graph with surrounding methods */
1472 void dump_cg_block_graph(ir_graph * irg) {
1473 pmap * map = pmap_create();
1474 pmap * map2 = pmap_create();
1479 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1480 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1481 pmap_insert(map2, entry->key, entry->value);
1482 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1483 d_cg_block_graph(entry->key, entry->value, map2);
1484 DEL_ARR_F(entry->value);
1490 if (dump_loop_information_flag) dump_loop_info(irg);
1494 static void collect_node(ir_node * node, void *env) {
1496 || node_floats(node)
1497 || get_irn_op(node) == op_Bad
1498 || get_irn_op(node) == op_Unknown) {
1499 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1500 ARR_APP1(ir_node *, arr, node);
1501 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1503 ir_node * block = get_nodes_Block(node);
1504 set_irn_link(node, get_irn_link(block));
1505 set_irn_link(block, node);
1509 /* Links all nodes that have the block field set in the link field of
1510 the block. Adds all blocks and nodes not associated with a block
1511 in a array in irg->link. */
1512 static void collect_nodes(void) {
1514 for (i = 0; i < get_irp_n_irgs(); i++)
1515 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1516 cg_walk(clear_link, collect_node, NULL);
1519 static void dump_graphs(void) {
1521 for (i = 0; i < get_irp_n_irgs(); i++) {
1522 current_ir_graph = get_irp_irg(i);
1523 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1527 /* Dump all irgs in interprocedural view to a single file. */
1528 void dump_all_cg_block_graph(void) {
1530 int rem_view = interprocedural_view;
1531 interprocedural_view = 1;
1532 vcg_open_name ("All_graphs");
1537 if (dump_loop_information_flag)
1538 for (i = 0; i < get_irp_n_irgs(); i++)
1539 dump_loop_info(get_irp_irg(i));
1542 interprocedural_view = rem_view;
1545 /* dump interprocedural block graph with surrounding methods */
1546 void dump_cg_graph(ir_graph * irg) {
1547 pmap * map = pmap_create();
1548 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1552 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1553 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1554 pmap_insert(map2, entry->key, entry->value);
1555 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1556 ir_node ** arr = entry->value;
1558 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1560 fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1561 get_id_str(irg_ident), get_id_str(irg_ident));
1563 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1564 ir_node * node = arr[i];
1565 dump_node(node, map2);
1566 dump_ir_data_edges(node);
1567 if (is_Block(node)) {
1568 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1569 dump_node(node, map2);
1570 dump_ir_block_edge(node);
1571 dump_ir_data_edges(node);
1578 /* Close the vcg information for the irg */
1579 fprintf(F, "}\n\n");