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", get_id_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 ", get_id_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", get_id_str(get_irn_opident(n)));
176 dump_node_mode (ir_node *n)
178 switch (get_irn_opcode(n)) {
196 fprintf (F, "%s", get_id_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", get_id_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) {
266 fprintf (F, " info1: \"");
267 fprintf (F, "visited: %ld \n", get_irn_visited(n));
270 switch(get_irn_opcode(n)) {
272 type *tp = get_entity_type(get_irg_ent(get_Start_irg(n)));
273 fprintf(F, "start of method of type %s \n", get_type_name(tp));
274 for (i = 0; i < get_method_n_params(tp); ++i)
275 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
278 fprintf(F, "allocating entity of type %s \n", get_type_name(get_Alloc_type(n)));
281 fprintf(F, "freeing entity of type %s \n", get_type_name(get_Free_type(n)));
284 fprintf(F, "Selecting entity of type %s \n", get_type_name(get_entity_type(get_Sel_entity(n))));
285 fprintf(F, " from entity of type %s \n", get_type_name(get_entity_owner(get_Sel_entity(n))));
288 type *tp = get_Call_type(n);
289 fprintf(F, "calling method of type %s \n", get_type_name(tp));
290 for (i = 0; i < get_method_n_params(tp); ++i)
291 fprintf(F, " param %d type: %s \n", i, get_type_name(get_method_param_type(tp, i)));
292 for (i = 0; i < get_method_n_ress(tp); ++i)
293 fprintf(F, " resul %d type: %s \n", i, get_type_name(get_method_res_type(tp, i)));
303 static bool pred_in_wrong_graph(ir_node *n, int pos, pmap *irgmap) {
304 ir_node *block = (is_Block(n)) ? n : get_nodes_Block(n);
307 ((get_irn_op(n) == op_Filter) || (get_irn_op(n) == op_Block))) {
308 ir_node *pred = skip_Proj(get_Block_cfgpred(block, pos));
309 if (is_ip_cfop(pred)) {
310 ir_graph *irg = get_ip_cfop_irg(pred);
311 if (pmap_find(irgmap, irg) == NULL) return true;
320 bool is_constlike_node(ir_node *n) {
321 ir_op *op = get_irn_op(n);
322 return (op == op_Const || op == op_Bad || op == op_SymConst);
326 static void dump_const_node_local(ir_node *n, pmap *irgmap) {
328 if (!get_opt_dump_const_local()) return;
329 /* Use visited flag to avoid outputting nodes twice.
330 initialize it first. */
331 for (i = 0; i < get_irn_arity(n); i++) {
332 ir_node *con = get_irn_n(n, i);
333 if (is_constlike_node(con)) {
334 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
335 set_irn_visited(con, get_irg_visited(current_ir_graph)-1);
338 for (i = 0; i < get_irn_arity(n); i++) {
339 ir_node *con = get_irn_n(n, i);
340 if (is_constlike_node(con) && irn_not_visited(con)) {
341 if (pred_in_wrong_graph(n, i, irgmap)) continue; /* pred not dumped */
342 mark_irn_visited(con);
343 /* Generate a new name for the node by appending the names of
345 fprintf (F, "node: {title: "); PRINT_CONSTID(n,con);
346 fprintf(F, " label: \"");
347 dump_node_opcode(con);
348 dump_node_mode (con);
350 dump_node_nodeattr(con);
352 fprintf (F, " %ld", get_irn_node_nr(con));
355 dump_node_vcgattr(con);
363 dump_node (ir_node *n, pmap * map) {
364 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
367 fprintf (F, "node: {title: \""); PRINT_NODEID(n); fprintf(F, "\" label: \"");
372 dump_node_nodeattr(n);
374 fprintf (F, " %ld", get_irn_node_nr(n));
377 dump_node_vcgattr(n);
380 dump_const_node_local(n, map);
383 /* dump the edge to the block this node belongs to */
385 dump_ir_block_edge(ir_node *n) {
386 if (get_opt_dump_const_local() && is_constlike_node(n)) return;
387 if (is_no_Block(n)) {
388 fprintf (F, "edge: { sourcename: \"");
390 fprintf (F, "\" targetname: \"");
391 PRINT_NODEID(get_nodes_Block(n));
392 fprintf (F, "\" " BLOCK_EDGE_ATTR "}\n");
396 static void print_edge_vcgattr(ir_node *from, int to) {
399 if (is_backedge(from, to)) fprintf (F, BACK_EDGE_ATTR);
401 switch (get_irn_opcode(from)) {
403 fprintf (F, CF_EDGE_ATTR);
405 case iro_Start: break;
408 if (get_irn_mode(get_End_keepalive(from, to)) == mode_BB)
409 fprintf (F, CF_EDGE_ATTR);
410 if (get_irn_mode(get_End_keepalive(from, to)) == mode_X)
411 fprintf (F, MEM_EDGE_ATTR);
414 case iro_EndReg: break;
415 case iro_EndExcept: break;
417 case iro_Break: break;
418 case iro_Cond: break;
421 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
423 case iro_Const: break;
424 case iro_SymConst:break;
427 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
429 case iro_CallBegin: break;
432 case iro_Minus: break;
438 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
446 case iro_Shrs: break;
449 case iro_Conv: break;
451 if (get_irn_modecode(from) == irm_M) fprintf (F, MEM_EDGE_ATTR);
457 if (to == 0) fprintf (F, MEM_EDGE_ATTR);
460 fprintf (F, MEM_EDGE_ATTR);
462 case iro_Tuple: break;
465 switch (get_irn_modecode(from)) {
467 fprintf (F, CF_EDGE_ATTR);
470 fprintf (F, MEM_EDGE_ATTR);
476 case iro_Unknown: break;
483 /* dump edges to our inputs */
485 dump_ir_data_edges(ir_node *n) {
486 int i, visited = get_irn_visited(n);
488 if ((get_irn_op(n) == op_End) && (!dump_keepalive))
491 for (i = 0; i < get_irn_arity(n); i++) {
492 ir_node * pred = get_irn_n(n, i);
494 if ((interprocedural_view && get_irn_visited(pred) < visited))
495 continue; /* pred not dumped */
496 if (is_backedge(n, i))
497 fprintf (F, "backedge: {sourcename: \"");
499 fprintf (F, "edge: {sourcename: \"");
501 fprintf (F, "\" targetname: ");
502 if ((get_opt_dump_const_local()) && is_constlike_node(pred))
504 PRINT_CONSTID(n,pred);
507 {fprintf(F, "\""); PRINT_NODEID(pred); fprintf(F, "\"");
509 fprintf (F, " label: \"%d\" ", i);
510 print_edge_vcgattr(n, i);
517 dump_out_edge (ir_node *n, void* env) {
519 for (i = 0; i < get_irn_n_outs(n); i++) {
520 assert(get_irn_out(n, i));
521 fprintf (F, "edge: {sourcename: \"");
523 fprintf (F, "\" targetname: \"");
524 PRINT_NODEID(get_irn_out(n, i));
525 fprintf (F, "\" color: red linestyle: dashed");
531 dump_loop_node_edge (ir_loop *loop, int i) {
533 fprintf (F, "edge: {sourcename: \"%p\" targetname: \"", (void*) loop);
534 PRINT_NODEID(get_loop_node(loop, i));
535 fprintf (F, "\" color: green");
540 void dump_loops (ir_loop *loop) {
542 /* dump this loop node */
543 fprintf (F, "node: {title: \"%p\" label: \"loop %d, %d sons, %d nodes\" }\n",
544 (void*)loop, get_loop_depth(loop), get_loop_n_sons(loop), get_loop_n_nodes(loop));
545 /* dump edges to nodes in loop -- only if it is a real loop */
546 if (get_loop_depth(loop) != 0) {
547 for (i = 0; i < get_loop_n_nodes(loop); i++) {
548 dump_loop_node_edge(loop, i);
551 for (i = 0; i < get_loop_n_sons(loop); i++) {
552 dump_loops(get_loop_son(loop, i));
557 void dump_loop_info(ir_graph *irg) {
558 ir_graph *rem = current_ir_graph;
559 current_ir_graph = irg;
561 if (get_irg_loop(irg))
562 dump_loops(get_irg_loop(irg));
564 current_ir_graph = rem;
568 /* dumps the edges between nodes and their type or entity attributes. */
569 static void dump_node2type_edges (ir_node *n, void *env)
573 switch (get_irn_opcode(n)) {
575 /* @@@ some consts have an entity */
578 if ( (get_SymConst_kind(n) == type_tag)
579 || (get_SymConst_kind(n) == size))
581 PRINT_NODE_TYPE_EDGE(n,get_SymConst_type(n),NODE2TYPE_EDGE_ATTR);
585 PRINT_NODE_ENT_EDGE(n,get_Sel_entity(n),NODE2TYPE_EDGE_ATTR);
588 PRINT_NODE_TYPE_EDGE(n,get_Call_type(n),NODE2TYPE_EDGE_ATTR);
591 PRINT_NODE_TYPE_EDGE(n,get_Alloc_type(n),NODE2TYPE_EDGE_ATTR);
594 PRINT_NODE_TYPE_EDGE(n,get_Free_type(n),NODE2TYPE_EDGE_ATTR);
597 PRINT_NODE_TYPE_EDGE(n,get_Cast_type(n),NODE2TYPE_EDGE_ATTR);
605 static void dump_const_expression(ir_node *value) {
606 ir_graph *rem = current_ir_graph;
607 int rem_dump_const_local = dump_const_local;
608 dump_const_local = 0;
609 current_ir_graph = get_const_code_irg();
610 irg_walk(value, dump_ir_blocks_nodes, NULL, get_nodes_Block(value));
611 /* Decrease visited flag so that we walk with the same flag for the next
612 expresssion. This guarantees that we don't dump the same node twice,
613 as for const expressions cse is performed to save memory. */
614 set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph) -1);
615 current_ir_graph = rem;
616 dump_const_local = rem_dump_const_local;
620 static void print_type_info(type *tp) {
621 if (get_type_state(tp) == layout_undefined) {
622 fprintf(F, "state: layout_undefined\n");
624 fprintf(F, "state: layout_fixed,\n");
626 if (get_type_mode(tp))
627 fprintf(F, "mode: %s,\n", get_id_str(get_mode_ident(get_type_mode(tp))));
628 fprintf(F, "size: %dB,\n", get_type_size(tp));
632 static void print_typespecific_info(type *tp) {
633 switch (get_type_tpop_code(tp)) {
636 if(existent == get_class_peculiarity(tp))
637 fprintf (F, " " TYPE_CLASS_NODE_ATTR);
639 fprintf (F, " " TYPE_DESCRIPTION_NODE_ATTR);
643 fprintf (F, " " TYPE_METH_NODE_ATTR);
654 case tpo_enumeration:
667 static void print_type_node(type *tp) {
668 fprintf (F, "node: {title: ");
670 fprintf (F, " label: \"%s %s\"", get_id_str(get_type_tpop_nameid(tp)), get_id_str(get_type_ident(tp)));
671 fprintf (F, " info1: \"");
674 print_typespecific_info(tp);
678 void dump_entity_node(entity *ent) {
679 fprintf (F, "node: {title: \"");
680 PRINT_ENTID(ent); fprintf(F, "\"");
681 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
682 fprintf (F, "label: ");
683 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_id_str(get_entity_ident(ent)));
684 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
685 fprintf (F, "\nallocation: ");
686 switch (get_entity_allocation(ent)) {
687 case dynamic_allocated: fprintf (F, "dynamic allocated"); break;
688 case automatic_allocated: fprintf (F, "automatic allocated"); break;
689 case static_allocated: fprintf (F, "static allocated"); break;
690 case parameter_allocated: fprintf (F, "parameter allocated"); break;
692 fprintf (F, "\nvisibility: ");
693 switch (get_entity_visibility(ent)) {
694 case local: fprintf (F, "local"); break;
695 case external_visible: fprintf (F, "external visible"); break;
696 case external_allocated: fprintf (F, "external allocated"); break;
698 fprintf (F, "\nvariability: ");
699 switch (get_entity_variability(ent)) {
700 case uninitialized: fprintf (F, "uninitialized");break;
701 case initialized: fprintf (F, "initialized"); break;
702 case part_constant: fprintf (F, "part_constant");break;
703 case constant: fprintf (F, "constant"); break;
705 fprintf (F, "\nvolatility: ");
706 switch (get_entity_volatility(ent)) {
707 case non_volatile: fprintf (F, "non_volatile"); break;
708 case is_volatile: fprintf (F, "is_volatile"); break;
710 fprintf (F, "\npeculiarity: ");
711 switch (get_entity_peculiarity(ent)) {
712 case description: fprintf (F, "description"); break;
713 case inherited: fprintf (F, "inherited"); break;
714 case existent: fprintf (F, "existent"); break;
716 fprintf(F, "\nname: %s\nld_name: %s",
717 get_id_str(get_entity_ident(ent)),
718 get_id_str(get_entity_ld_ident(ent)));
719 fprintf(F, "\noffset: %d", get_entity_offset(ent));
720 if (is_method_type(get_entity_type(ent))) {
721 if (get_entity_irg(ent)) /* can be null */
722 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
724 { fprintf (F, "\nirg = NULL"); }
726 fprintf(F, "\"\n}\n");
729 /* dumps a type or entity and it's edges. */
731 dump_type_info (type_or_ent *tore, void *env) {
732 int i = 0; /* to shutup gcc */
734 /* dump this type or entity */
736 switch (get_kind(tore)) {
739 entity *ent = (entity *)tore;
742 dump_entity_node(ent);
744 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
745 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
746 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
747 PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
748 if(is_class_type(get_entity_owner(ent))) {
749 for(i = 0; i < get_entity_n_overwrites(ent); i++){
750 PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
753 /* attached subgraphs */
754 if (const_entities && (get_entity_variability(ent) != uninitialized)) {
755 if (is_atomic_entity(ent)) {
756 value = get_atomic_ent_value(ent);
758 PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
759 /* DDMN(value); $$$ */
760 dump_const_expression(value);
763 if (is_compound_entity(ent)) {
764 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
765 value = get_compound_ent_value(ent, i);
767 PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
768 dump_const_expression(value);
769 PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
771 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
772 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
773 get_compound_ent_value_member(ent, i), i);
782 type *tp = (type *)tore;
784 /* and now the edges */
785 switch (get_type_tpop_code(tp)) {
788 for (i=0; i < get_class_n_supertypes(tp); i++) {
789 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
792 for (i=0; i < get_class_n_members(tp); i++) {
793 PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
798 for (i=0; i < get_struct_n_members(tp); i++) {
799 PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
804 for (i = 0; i < get_method_n_params(tp); i++)
806 PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
808 for (i = 0; i < get_method_n_ress(tp); i++)
810 PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
815 for (i = 0; i < get_union_n_members(tp); i++)
817 PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
822 PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
823 PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
824 for (i = 0; i < get_array_n_dimensions(tp); i++) {
825 ir_node *upper = get_array_upper_bound(tp, i);
826 ir_node *lower = get_array_lower_bound(tp, i);
827 PRINT_NODE_TYPE_EDGE(upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
828 PRINT_NODE_TYPE_EDGE(lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
829 dump_const_expression(upper);
830 dump_const_expression(lower);
834 case tpo_enumeration:
839 PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
847 break; /* case k_type */
850 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
852 } /* switch kind_or_entity */
855 /* dumps a class type node and a superclass edge.
856 If env != null dumps entities of classes and overwrites edges. */
858 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
859 int i = 0; /* to shutup gcc */
861 /* dump this type or entity */
862 switch (get_kind(tore)) {
864 entity *ent = (entity *)tore;
865 if (get_entity_owner(ent) == get_glob_type()) break;
866 if ((env) && is_class_type(get_entity_owner(ent))) {
868 dump_entity_node(ent);
870 PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
871 for(i = 0; i < get_entity_n_overwrites(ent); i++)
873 PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
876 } break; /* case k_entity */
879 type *tp = (type *)tore;
880 if (tp == get_glob_type()) break;
881 switch (get_type_tpop_code(tp)) {
884 /* and now the edges */
885 for (i=0; i < get_class_n_supertypes(tp); i++)
887 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
893 break; /* case k_type */
896 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
898 } /* switch kind_or_entity */
901 /************************************************************************/
902 /* open and close vcg file */
903 /************************************************************************/
905 static void vcg_open (ir_graph *irg, char *suffix) {
906 char *fname; /* filename to put the vcg information in */
913 /** open file for vcg graph */
914 ent = get_irg_ent(irg);
915 id = ent->ld_name ? ent->ld_name : ent->name;
916 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
917 len = get_id_strlen (id);
918 cp = get_id_str (id);
919 if (dump_file_suffix)
920 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
922 fname = malloc (len + 5 + strlen(suffix));
923 strncpy (fname, cp, len); /* copy the filename */
925 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
926 strcat (fname, suffix); /* append file suffix */
927 strcat (fname, ".vcg"); /* append the .vcg suffix */
928 F = fopen (fname, "w"); /* open file for writing */
930 panic ("cannot open %s for writing (%m)", fname); /* not reached */
934 strcpy(label, "yes");
936 strcpy (label, "no");
941 "graph: { title: \"ir graph of %s\"\n"
942 "display_edge_labels: %s\n"
943 "layoutalgorithm: mindepth\n"
944 "manhattan_edges: yes\n"
946 "orientation: bottom_to_top\n"
947 "classname 1: \"Data\"\n"
948 "classname 2: \"Block\"\n"
949 "classname 3: \"Entity type\"\n"
950 "classname 4: \"Entity owner\"\n"
951 "classname 5: \"Method Param\"\n"
952 "classname 6: \"Method Res\"\n"
953 "classname 7: \"Super\"\n"
954 "classname 8: \"Union\"\n"
955 "classname 9: \"Points-to\"\n"
956 "classname 10: \"Array Element Type\"\n"
957 "classname 11: \"Overwrites\"\n"
958 "classname 12: \"Member\"\n"
961 fprintf (F, "\n"); /* a separator */
964 static void vcg_open_name (const char *name) {
965 char *fname; /* filename to put the vcg information in */
969 /** open file for vcg graph */
971 fname = malloc (len + 5);
972 if (dump_file_suffix)
973 fname = malloc (len + 5 + strlen(dump_file_suffix));
975 fname = malloc (len + 5);
976 strcpy (fname, name); /* copy the filename */
977 if (dump_file_suffix) strcat (fname, dump_file_suffix);
978 strcat (fname, ".vcg"); /* append the .vcg suffix */
979 F = fopen (fname, "w"); /* open file for writing */
981 panic ("cannot open %s for writing (%m)", fname); /* not reached */
985 strcpy(label, "yes");
987 strcpy (label, "no");
992 "graph: { title: \"ir graph of %s\"\n"
993 "display_edge_labels: %s\n"
994 "layoutalgorithm: mindepth\n"
995 "manhattan_edges: yes\n"
997 "orientation: bottom_to_top\n"
998 "classname 1: \"Data\"\n"
999 "classname 2: \"Block\"\n"
1000 "classname 3: \"Entity type\"\n"
1001 "classname 4: \"Entity owner\"\n"
1002 "classname 5: \"Method Param\"\n"
1003 "classname 6: \"Method Res\"\n"
1004 "classname 7: \"Super\"\n"
1005 "classname 8: \"Union\"\n"
1006 "classname 9: \"Points-to\"\n"
1007 "classname 10: \"Array Element Type\"\n"
1008 "classname 11: \"Overwrites\"\n"
1009 "classname 12: \"Member\"\n"
1012 fprintf (F, "\n"); /* a separator */
1017 fprintf (F, "}\n"); /* print footer */
1018 fclose (F); /* close vcg file */
1021 /************************************************************************/
1022 /* routines to dump a graph, blocks as conventional nodes. */
1023 /************************************************************************/
1025 static int node_floats(ir_node *n) {
1026 return ((get_op_pinned(get_irn_op(n)) == floats) &&
1027 (get_irg_pinned(current_ir_graph) == floats));
1031 dump_whole_node (ir_node *n, void* env) {
1033 if (!node_floats(n)) dump_ir_block_edge(n);
1034 dump_ir_data_edges(n);
1038 dump_ir_graph (ir_graph *irg)
1041 rem = current_ir_graph;
1042 current_ir_graph = irg;
1046 /* walk over the graph */
1047 /* dump_whole_node must be called in post visiting predecessors */
1048 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1050 /* dump the out edges in a separate walk */
1051 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1052 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1057 current_ir_graph = rem;
1060 /***********************************************************************/
1061 /* the following routines dump the nodes as attached to the blocks. */
1062 /***********************************************************************/
1065 dump_ir_blocks_nodes (ir_node *n, void *env) {
1066 ir_node *block = (ir_node *)env;
1068 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1070 dump_ir_data_edges(n);
1072 if (get_irn_op(n) == op_Bad)
1077 dump_ir_block (ir_node *block, void *env) {
1078 ir_graph *irg = (ir_graph *)env;
1080 if (get_irn_opcode(block) == iro_Block) {
1082 /* This is a block. So dump the vcg information to make a block. */
1083 fprintf(F, "graph: { title: \"");
1084 PRINT_NODEID(block);
1085 fprintf(F, "\" label: \"");
1086 #ifdef DEBUG_libfirm
1087 fprintf (F, "%ld", get_irn_node_nr(block));
1089 fprintf (F, "%s", get_op_name(get_irn_op(block)));
1091 if (exc_normal != get_Block_exc (block))
1092 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1094 fprintf(F, "\" status:clustered color:%s \n",
1095 get_Block_matured (block) ? "yellow" : "red");
1096 /* dump the blocks edges */
1097 dump_ir_data_edges(block);
1099 /* dump the nodes that go into the block */
1100 irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1102 /* Close the vcg information for the block */
1103 fprintf(F, "}\n\n");
1104 dump_const_node_local(block, NULL);
1110 dump_blockless_nodes (ir_node *n, void *env) {
1111 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1113 dump_ir_data_edges(n);
1114 dump_ir_block_edge(n);
1115 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1118 if (node_floats(n)) {
1120 dump_ir_data_edges(n);
1121 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1125 static void dump_ir_block_graph_2 (ir_graph *irg)
1128 /* walk over the blocks in the graph */
1129 irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1131 /* dump all nodes that are not in a Block */
1132 irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1134 /* dump the Bad node */
1136 dump_node(get_irg_bad(irg), NULL);
1140 dump_ir_block_graph (ir_graph *irg)
1143 rem = current_ir_graph;
1144 current_ir_graph = irg;
1148 dump_ir_block_graph_2 (irg);
1150 if (dump_loop_information_flag) dump_loop_info(irg);
1153 current_ir_graph = rem;
1157 /***********************************************************************/
1158 /* the following routines dump a control flow graph */
1159 /***********************************************************************/
1163 dump_block_to_cfg (ir_node *block, void *env) {
1167 if (get_irn_opcode(block) == iro_Block) {
1168 /* This is a block. Dump a node for the block. */
1169 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1170 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1171 #ifdef DEBUG_libfirm
1172 fprintf (F, "%ld", get_irn_node_nr(block));
1174 fprintf (F, "%p", (void*) block);
1177 if (exc_normal != get_Block_exc (block))
1178 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1181 if (dump_dominator_information_flag)
1182 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1184 /* Dump the edges */
1185 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1186 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1187 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1188 fprintf (F, "edge: { sourcename: \"");
1189 PRINT_NODEID(block);
1190 fprintf (F, "\" targetname: \"");
1192 fprintf (F, "\"}\n");
1195 /* Dump dominator edge */
1196 if (dump_dominator_information_flag && get_Block_idom(block)) {
1197 pred = get_Block_idom(block);
1198 fprintf (F, "edge: { sourcename: \"");
1199 PRINT_NODEID(block);
1200 fprintf (F, "\" targetname: \"");
1202 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1208 dump_cfg (ir_graph *irg)
1210 ir_graph *rem = current_ir_graph;
1211 int ddif = dump_dominator_information_flag;
1212 current_ir_graph = irg;
1213 vcg_open (irg, "-cfg");
1215 if (get_irg_dom_state(irg) != dom_consistent)
1216 dump_dominator_information_flag = 0;
1218 /* walk over the blocks in the graph */
1219 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1220 dump_node (get_irg_bad(irg), NULL);
1222 dump_dominator_information_flag = ddif;
1224 current_ir_graph = rem;
1228 /***********************************************************************/
1229 /* the following routine dumps all type information reachable from an */
1231 /***********************************************************************/
1235 dump_type_graph (ir_graph *irg)
1238 rem = current_ir_graph;
1239 current_ir_graph = irg;
1241 vcg_open (irg, "-type");
1243 /* walk over the blocks in the graph */
1244 type_walk_irg(irg, dump_type_info, NULL, NULL);
1245 /* The walker for the const code can be called several times for the
1246 same (sub) experssion. So that no nodes are dumped several times
1247 we decrease the visited flag of the corresponding graph after each
1248 walk. So now increase it finally. */
1249 inc_irg_visited(get_const_code_irg());
1252 current_ir_graph = rem;
1255 /***********************************************************************/
1256 /* the following routine dumps all type information */
1257 /***********************************************************************/
1261 dump_all_types (void)
1263 vcg_open_name ("All_types");
1264 type_walk(dump_type_info, NULL, NULL);
1265 inc_irg_visited(get_const_code_irg());
1270 dump_class_hierarchy (bool entities)
1272 vcg_open_name ("class_hierarchy");
1274 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1276 type_walk(dump_class_hierarchy_node, NULL, NULL);
1280 /***********************************************************************/
1281 /* dumps a graph with type information */
1282 /***********************************************************************/
1286 dump_ir_graph_w_types (ir_graph *irg)
1289 rem = current_ir_graph;
1290 current_ir_graph = irg;
1292 vcg_open (irg, "-all");
1294 /* dump common ir graph */
1295 irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1296 /* dump type info */
1297 type_walk_irg(irg, dump_type_info, NULL, NULL);
1298 inc_irg_visited(get_const_code_irg());
1299 /* dump edges from graph to type info */
1300 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1303 current_ir_graph = rem;
1307 dump_ir_block_graph_w_types (ir_graph *irg)
1310 rem = current_ir_graph;
1311 current_ir_graph = irg;
1313 vcg_open (irg, "-all");
1315 /* dump common blocked ir graph */
1316 dump_ir_block_graph_2(irg);
1317 /* dump type info */
1318 type_walk_irg(irg, dump_type_info, NULL, NULL);
1319 inc_irg_visited(get_const_code_irg());
1320 /* dump edges from graph to type info */
1321 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1324 current_ir_graph = rem;
1327 /***********************************************************************/
1328 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1330 /* dump_ir_block_graph */
1332 /* dump_type_graph */
1333 /* dump_ir_graph_w_types */
1334 /***********************************************************************/
1335 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1337 for (i=0; i < get_irp_n_irgs(); i++) {
1338 dump_graph(get_irp_irg(i));
1343 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1344 abort with a segmentation fault. */
1345 void turn_off_edge_labels(void) {
1350 void dump_consts_local(bool b) {
1351 dump_const_local = b;
1354 void turn_off_constant_entity_values(void) {
1358 void dump_keepalive_edges(bool b) {
1362 bool get_opt_dump_keepalive_edges(void) {
1363 return dump_keepalive;
1366 void dump_out_edges(void) {
1367 dump_out_edge_flag = 1;
1370 void dump_dominator_information(void) {
1371 dump_dominator_information_flag = 1;
1374 void dump_loop_information(void) {
1375 dump_loop_information_flag = 1;
1378 void dont_dump_loop_information(void) {
1379 dump_loop_information_flag = 0;
1382 static void clear_link(ir_node * node, void * env) {
1383 set_irn_link(node, NULL);
1386 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1387 assert(node); assert(map);
1389 || node_floats(node)
1390 || get_irn_op(node) == op_Bad
1391 || get_irn_op(node) == op_Unknown) {
1392 pmap_entry * entry = pmap_find(map, current_ir_graph);
1398 ARR_APP1(ir_node *, arr , node);
1400 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1403 pmap_insert(map, current_ir_graph, arr);
1406 ir_node * block = get_nodes_Block(node);
1407 set_irn_link(node, get_irn_link(block));
1408 set_irn_link(block, node);
1413 static void dump_cg_ir_block(ir_node * block, void * env) {
1415 pmap *irgmap = (pmap *)env;
1416 assert(is_Block(block));
1417 fprintf(F, "graph: { title: \"");
1418 PRINT_NODEID(block);
1419 fprintf(F, "\" label: \"");
1420 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1421 #ifdef DEBUG_libfirm
1422 fprintf (F, "%ld", get_irn_node_nr(block));
1424 fprintf (F, "%p", (void*) block);
1426 if (exc_normal != get_Block_exc(block)) {
1427 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1430 fprintf(F, "\" status:clustered color:%s \n",
1431 get_Block_matured(block) ? "yellow" : "red");
1433 /* dump the blocks edges */
1434 dump_ir_data_edges(block);
1436 /* dump the nodes that go into the block */
1437 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1438 dump_node(node, irgmap);
1439 dump_ir_data_edges(node);
1442 /* Close the vcg information for the block */
1443 fprintf(F, "}\n\n");
1446 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1449 fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
1450 (void*) irg, get_id_str(get_entity_ident(get_irg_ent(irg))));
1452 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1453 ir_node * node = arr[i];
1454 if (is_Block(node)) {
1455 /* Dumps the block and all the nodes in the block , which are to
1456 be found in Block->link. */
1457 dump_cg_ir_block(node, irgmap);
1459 /* Nodes that are not in a Block. */
1460 dump_node(node, NULL);
1461 dump_ir_data_edges(node);
1464 /* Close the vcg information for the irg */
1465 fprintf(F, "}\n\n");
1468 /* dump interprocedural graph with surrounding methods */
1469 void dump_cg_block_graph(ir_graph * irg) {
1470 pmap * map = pmap_create();
1471 pmap * map2 = pmap_create();
1476 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1477 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1478 pmap_insert(map2, entry->key, entry->value);
1479 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1480 d_cg_block_graph(entry->key, entry->value, map2);
1481 DEL_ARR_F(entry->value);
1487 if (dump_loop_information_flag) dump_loop_info(irg);
1491 static void collect_node(ir_node * node, void *env) {
1493 || node_floats(node)
1494 || get_irn_op(node) == op_Bad
1495 || get_irn_op(node) == op_Unknown) {
1496 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1497 ARR_APP1(ir_node *, arr, node);
1498 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1500 ir_node * block = get_nodes_Block(node);
1501 set_irn_link(node, get_irn_link(block));
1502 set_irn_link(block, node);
1506 /* Links all nodes that have the block field set in the link field of
1507 the block. Adds all blocks and nodes not associated with a block
1508 in a array in irg->link. */
1509 static void collect_nodes(void) {
1511 for (i = 0; i < get_irp_n_irgs(); i++)
1512 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1513 cg_walk(clear_link, collect_node, NULL);
1516 static void dump_graphs(void) {
1518 for (i = 0; i < get_irp_n_irgs(); i++) {
1519 current_ir_graph = get_irp_irg(i);
1520 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1524 /* Dump all irgs in interprocedural view to a single file. */
1525 void dump_all_cg_block_graph(void) {
1527 int rem_view = interprocedural_view;
1528 interprocedural_view = 1;
1529 vcg_open_name ("All_graphs");
1534 if (dump_loop_information_flag)
1535 for (i = 0; i < get_irp_n_irgs(); i++)
1536 dump_loop_info(get_irp_irg(i));
1539 interprocedural_view = rem_view;
1542 /* dump interprocedural block graph with surrounding methods */
1543 void dump_cg_graph(ir_graph * irg) {
1544 pmap * map = pmap_create();
1545 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1549 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1550 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1551 pmap_insert(map2, entry->key, entry->value);
1552 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1553 ir_node ** arr = entry->value;
1555 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1557 fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1558 get_id_str(irg_ident), get_id_str(irg_ident));
1560 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1561 ir_node * node = arr[i];
1562 dump_node(node, map2);
1563 dump_ir_data_edges(node);
1564 if (is_Block(node)) {
1565 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1566 dump_node(node, map2);
1567 dump_ir_block_edge(node);
1568 dump_ir_data_edges(node);
1575 /* Close the vcg information for the irg */
1576 fprintf(F, "}\n\n");