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 (peculiarity_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)
672 fprintf (F, "node: {title: ");
674 fprintf (F, " label: \"%s %s\"", get_id_str(get_type_tpop_nameid(tp)), get_id_str(get_type_ident(tp)));
675 fprintf (F, " info1: \"");
678 print_typespecific_info(tp);
682 #define X(a) case a: fprintf(F, #a); break
683 void dump_entity_node(entity *ent)
685 fprintf (F, "node: {title: \"");
686 PRINT_ENTID(ent); fprintf(F, "\"");
687 fprintf (F, DEFAULT_TYPE_ATTRIBUTE);
688 fprintf (F, "label: ");
689 fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_id_str(get_entity_ident(ent)));
690 fprintf (F, "\n info1: \"\nid: "); PRINT_ENTID(ent);
692 fprintf (F, "\nallocation: ");
693 switch (get_entity_allocation(ent)) {
694 X(allocation_dynamic);
695 X(allocation_automatic);
696 X(allocation_static);
697 X(allocation_parameter);
700 fprintf (F, "\nvisibility: ");
701 switch (get_entity_visibility(ent)) {
703 X(visibility_external_visible);
704 X(visibility_external_allocated);
707 fprintf (F, "\nvariability: ");
708 switch (get_entity_variability(ent)) {
709 X(variability_uninitialized);
710 X(variability_initialized);
711 X(variability_part_constant);
712 X(variability_constant);
715 fprintf (F, "\nvolatility: ");
716 switch (get_entity_volatility(ent)) {
717 X(volatility_non_volatile);
718 X(volatility_is_volatile);
721 fprintf (F, "\npeculiarity: ");
722 switch (get_entity_peculiarity(ent)) {
723 X(peculiarity_description);
724 X(peculiarity_inherited);
725 X(peculiarity_existent);
727 fprintf(F, "\nname: %s\nld_name: %s",
728 get_id_str(get_entity_ident(ent)),
729 get_id_str(get_entity_ld_ident(ent)));
730 fprintf(F, "\noffset: %d", get_entity_offset(ent));
731 if (is_method_type(get_entity_type(ent))) {
732 if (get_entity_irg(ent)) /* can be null */
733 { fprintf (F, "\nirg = "); PRINT_IRGID(get_entity_irg(ent)); }
735 { fprintf (F, "\nirg = NULL"); }
737 fprintf(F, "\"\n}\n");
741 /* dumps a type or entity and it's edges. */
743 dump_type_info (type_or_ent *tore, void *env) {
744 int i = 0; /* to shutup gcc */
746 /* dump this type or entity */
748 switch (get_kind(tore)) {
751 entity *ent = (entity *)tore;
754 dump_entity_node(ent);
756 /* skip this to reduce graph. Member edge of type is parallel to this edge. *
757 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
758 ENT_OWN_EDGE_ATTR "}\n", ent, get_entity_owner(ent));*/
759 PRINT_ENT_TYPE_EDGE(ent, get_entity_type(ent), ENT_TYPE_EDGE_ATTR);
760 if(is_class_type(get_entity_owner(ent))) {
761 for(i = 0; i < get_entity_n_overwrites(ent); i++){
762 PRINT_ENT_ENT_EDGE(ent, get_entity_overwrites(ent, i), ENT_OVERWRITES_EDGE_ATTR);
765 /* attached subgraphs */
766 if (const_entities && (get_entity_variability(ent) != variability_uninitialized)) {
767 if (is_atomic_entity(ent)) {
768 value = get_atomic_ent_value(ent);
770 PRINT_ENT_NODE_EDGE(ent, value, ENT_VALUE_EDGE_ATTR, i);
771 /* DDMN(value); $$$ */
772 dump_const_expression(value);
775 if (is_compound_entity(ent)) {
776 for (i = 0; i < get_compound_ent_n_values(ent); i++) {
777 value = get_compound_ent_value(ent, i);
779 PRINT_ENT_NODE_EDGE(ent,value,ENT_VALUE_EDGE_ATTR,i);
780 dump_const_expression(value);
781 PRINT_ENT_ENT_EDGE(ent, get_compound_ent_value_member(ent, i), ENT_CORR_EDGE_ATTR, i);
783 fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" "
784 ENT_CORR_EDGE_ATTR "}\n", GET_ENTID(ent),
785 get_compound_ent_value_member(ent, i), i);
794 type *tp = (type *)tore;
796 /* and now the edges */
797 switch (get_type_tpop_code(tp)) {
800 for (i=0; i < get_class_n_supertypes(tp); i++) {
801 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
804 for (i=0; i < get_class_n_members(tp); i++) {
805 PRINT_TYPE_ENT_EDGE(tp,get_class_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
810 for (i=0; i < get_struct_n_members(tp); i++) {
811 PRINT_TYPE_ENT_EDGE(tp,get_struct_member(tp, i),TYPE_MEMBER_EDGE_ATTR);
816 for (i = 0; i < get_method_n_params(tp); i++)
818 PRINT_TYPE_TYPE_EDGE(tp,get_method_param_type(tp, i),METH_PAR_EDGE_ATTR,i);
820 for (i = 0; i < get_method_n_ress(tp); i++)
822 PRINT_TYPE_TYPE_EDGE(tp,get_method_res_type(tp, i),METH_RES_EDGE_ATTR,i);
827 for (i = 0; i < get_union_n_members(tp); i++)
829 PRINT_TYPE_ENT_EDGE(tp,get_union_member(tp, i),UNION_EDGE_ATTR);
834 PRINT_TYPE_TYPE_EDGE(tp,get_array_element_type(tp),ARR_ELT_TYPE_EDGE_ATTR);
835 PRINT_TYPE_ENT_EDGE(tp,get_array_element_entity(tp),ARR_ENT_EDGE_ATTR);
836 for (i = 0; i < get_array_n_dimensions(tp); i++) {
837 ir_node *upper = get_array_upper_bound(tp, i);
838 ir_node *lower = get_array_lower_bound(tp, i);
839 PRINT_NODE_TYPE_EDGE(upper, tp, "label: \"upper %d\"", get_array_order(tp, i));
840 PRINT_NODE_TYPE_EDGE(lower, tp, "label: \"lower %d\"", get_array_order(tp, i));
841 dump_const_expression(upper);
842 dump_const_expression(lower);
846 case tpo_enumeration:
851 PRINT_TYPE_TYPE_EDGE(tp,get_pointer_points_to_type(tp), PTR_PTS_TO_EDGE_ATTR);
859 break; /* case k_type */
862 printf(" *** irdump, dump_type_info(l.%i), faulty type.\n", __LINE__);
864 } /* switch kind_or_entity */
867 /* dumps a class type node and a superclass edge.
868 If env != null dumps entities of classes and overwrites edges. */
870 dump_class_hierarchy_node (type_or_ent *tore, void *env) {
871 int i = 0; /* to shutup gcc */
873 /* dump this type or entity */
874 switch (get_kind(tore)) {
876 entity *ent = (entity *)tore;
877 if (get_entity_owner(ent) == get_glob_type()) break;
878 if ((env) && is_class_type(get_entity_owner(ent))) {
880 dump_entity_node(ent);
882 PRINT_TYPE_ENT_EDGE(get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR);
883 for(i = 0; i < get_entity_n_overwrites(ent); i++)
885 PRINT_ENT_ENT_EDGE(get_entity_overwrites(ent, i),ent, ENT_OVERWRITES_EDGE_ATTR);
888 } break; /* case k_entity */
891 type *tp = (type *)tore;
892 if (tp == get_glob_type()) break;
893 switch (get_type_tpop_code(tp)) {
896 /* and now the edges */
897 for (i=0; i < get_class_n_supertypes(tp); i++)
899 PRINT_TYPE_TYPE_EDGE(tp,get_class_supertype(tp, i),TYPE_SUPER_EDGE_ATTR);
905 break; /* case k_type */
908 printf(" *** irdump, dump_class_hierarchy_node(l.%i), faulty type.\n", __LINE__);
910 } /* switch kind_or_entity */
913 /************************************************************************/
914 /* open and close vcg file */
915 /************************************************************************/
917 static void vcg_open (ir_graph *irg, char *suffix) {
918 char *fname; /* filename to put the vcg information in */
925 /** open file for vcg graph */
926 ent = get_irg_ent(irg);
927 id = ent->ld_name ? ent->ld_name : ent->name;
928 /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
929 len = get_id_strlen (id);
930 cp = get_id_str (id);
931 if (dump_file_suffix)
932 fname = malloc (len + 5 + strlen(suffix) + strlen(dump_file_suffix));
934 fname = malloc (len + 5 + strlen(suffix));
935 strncpy (fname, cp, len); /* copy the filename */
937 if (dump_file_suffix) strcat (fname, dump_file_suffix); /* append file suffix */
938 strcat (fname, suffix); /* append file suffix */
939 strcat (fname, ".vcg"); /* append the .vcg suffix */
940 F = fopen (fname, "w"); /* open file for writing */
942 panic ("cannot open %s for writing (%m)", fname); /* not reached */
946 strcpy(label, "yes");
948 strcpy (label, "no");
953 "graph: { title: \"ir graph of %s\"\n"
954 "display_edge_labels: %s\n"
955 "layoutalgorithm: mindepth\n"
956 "manhattan_edges: yes\n"
958 "orientation: bottom_to_top\n"
959 "classname 1: \"Data\"\n"
960 "classname 2: \"Block\"\n"
961 "classname 3: \"Entity type\"\n"
962 "classname 4: \"Entity owner\"\n"
963 "classname 5: \"Method Param\"\n"
964 "classname 6: \"Method Res\"\n"
965 "classname 7: \"Super\"\n"
966 "classname 8: \"Union\"\n"
967 "classname 9: \"Points-to\"\n"
968 "classname 10: \"Array Element Type\"\n"
969 "classname 11: \"Overwrites\"\n"
970 "classname 12: \"Member\"\n"
973 fprintf (F, "\n"); /* a separator */
976 static void vcg_open_name (const char *name) {
977 char *fname; /* filename to put the vcg information in */
981 /** open file for vcg graph */
983 fname = malloc (len + 5);
984 if (dump_file_suffix)
985 fname = malloc (len + 5 + strlen(dump_file_suffix));
987 fname = malloc (len + 5);
988 strcpy (fname, name); /* copy the filename */
989 if (dump_file_suffix) strcat (fname, dump_file_suffix);
990 strcat (fname, ".vcg"); /* append the .vcg suffix */
991 F = fopen (fname, "w"); /* open file for writing */
993 panic ("cannot open %s for writing (%m)", fname); /* not reached */
997 strcpy(label, "yes");
999 strcpy (label, "no");
1004 "graph: { title: \"ir graph of %s\"\n"
1005 "display_edge_labels: %s\n"
1006 "layoutalgorithm: mindepth\n"
1007 "manhattan_edges: yes\n"
1008 "port_sharing: no\n"
1009 "orientation: bottom_to_top\n"
1010 "classname 1: \"Data\"\n"
1011 "classname 2: \"Block\"\n"
1012 "classname 3: \"Entity type\"\n"
1013 "classname 4: \"Entity owner\"\n"
1014 "classname 5: \"Method Param\"\n"
1015 "classname 6: \"Method Res\"\n"
1016 "classname 7: \"Super\"\n"
1017 "classname 8: \"Union\"\n"
1018 "classname 9: \"Points-to\"\n"
1019 "classname 10: \"Array Element Type\"\n"
1020 "classname 11: \"Overwrites\"\n"
1021 "classname 12: \"Member\"\n"
1024 fprintf (F, "\n"); /* a separator */
1029 fprintf (F, "}\n"); /* print footer */
1030 fclose (F); /* close vcg file */
1033 /************************************************************************/
1034 /* routines to dump a graph, blocks as conventional nodes. */
1035 /************************************************************************/
1037 static int node_floats(ir_node *n) {
1038 return ((get_op_pinned(get_irn_op(n)) == floats) &&
1039 (get_irg_pinned(current_ir_graph) == floats));
1043 dump_whole_node (ir_node *n, void* env) {
1045 if (!node_floats(n)) dump_ir_block_edge(n);
1046 dump_ir_data_edges(n);
1050 dump_ir_graph (ir_graph *irg)
1053 rem = current_ir_graph;
1054 current_ir_graph = irg;
1058 /* walk over the graph */
1059 /* dump_whole_node must be called in post visiting predecessors */
1060 irg_walk(get_irg_end(irg), NULL, dump_whole_node, NULL);
1062 /* dump the out edges in a separate walk */
1063 if ((dump_out_edge_flag) && (get_irg_outs_state(irg) != no_outs)) {
1064 irg_out_walk(get_irg_start(irg), dump_out_edge, NULL, NULL);
1069 current_ir_graph = rem;
1072 /***********************************************************************/
1073 /* the following routines dump the nodes as attached to the blocks. */
1074 /***********************************************************************/
1077 dump_ir_blocks_nodes (ir_node *n, void *env) {
1078 ir_node *block = (ir_node *)env;
1080 if (is_no_Block(n) && get_nodes_Block(n) == block && !node_floats(n)) {
1082 dump_ir_data_edges(n);
1084 if (get_irn_op(n) == op_Bad)
1089 dump_ir_block (ir_node *block, void *env) {
1090 ir_graph *irg = (ir_graph *)env;
1092 if (get_irn_opcode(block) == iro_Block) {
1094 /* This is a block. So dump the vcg information to make a block. */
1095 fprintf(F, "graph: { title: \"");
1096 PRINT_NODEID(block);
1097 fprintf(F, "\" label: \"");
1098 #ifdef DEBUG_libfirm
1099 fprintf (F, "%ld", get_irn_node_nr(block));
1101 fprintf (F, "%s", get_op_name(get_irn_op(block)));
1103 if (exc_normal != get_Block_exc (block))
1104 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1106 fprintf(F, "\" status:clustered color:%s \n",
1107 get_Block_matured (block) ? "yellow" : "red");
1108 /* dump the blocks edges */
1109 dump_ir_data_edges(block);
1111 /* dump the nodes that go into the block */
1112 irg_walk(get_irg_end(irg), dump_ir_blocks_nodes, NULL, block);
1114 /* Close the vcg information for the block */
1115 fprintf(F, "}\n\n");
1116 dump_const_node_local(block, NULL);
1122 dump_blockless_nodes (ir_node *n, void *env) {
1123 if (is_no_Block(n) && get_irn_op(get_nodes_Block(n)) == op_Bad) {
1125 dump_ir_data_edges(n);
1126 dump_ir_block_edge(n);
1127 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1130 if (node_floats(n)) {
1132 dump_ir_data_edges(n);
1133 if (get_irn_op(n) == op_Bad) Bad_dumped = 1;
1137 static void dump_ir_block_graph_2 (ir_graph *irg)
1140 /* walk over the blocks in the graph */
1141 irg_block_walk(get_irg_end(irg), dump_ir_block, NULL, irg);
1143 /* dump all nodes that are not in a Block */
1144 irg_walk(get_irg_end(irg), dump_blockless_nodes, NULL, NULL);
1146 /* dump the Bad node */
1148 dump_node(get_irg_bad(irg), NULL);
1152 dump_ir_block_graph (ir_graph *irg)
1155 rem = current_ir_graph;
1156 current_ir_graph = irg;
1160 dump_ir_block_graph_2 (irg);
1162 if (dump_loop_information_flag) dump_loop_info(irg);
1165 current_ir_graph = rem;
1169 /***********************************************************************/
1170 /* the following routines dump a control flow graph */
1171 /***********************************************************************/
1175 dump_block_to_cfg (ir_node *block, void *env) {
1179 if (get_irn_opcode(block) == iro_Block) {
1180 /* This is a block. Dump a node for the block. */
1181 fprintf (F, "node: {title: \""); PRINT_NODEID(block);
1182 fprintf (F, "\" label: \"%s ", get_op_name(get_irn_op(block)));
1183 #ifdef DEBUG_libfirm
1184 fprintf (F, "%ld", get_irn_node_nr(block));
1186 fprintf (F, "%p", (void*) block);
1189 if (exc_normal != get_Block_exc (block))
1190 fprintf (F, " (%s)", exc_to_string (get_Block_exc (block)));
1193 if (dump_dominator_information_flag)
1194 fprintf(F, "info1:dom depth %d", get_Block_dom_depth(block));
1196 /* Dump the edges */
1197 for ( i = 0; i < get_Block_n_cfgpreds(block); i++)
1198 if (get_irn_op(skip_Proj(get_Block_cfgpred(block, i))) != op_Bad) {
1199 pred = get_nodes_Block(skip_Proj(get_Block_cfgpred(block, i)));
1200 fprintf (F, "edge: { sourcename: \"");
1201 PRINT_NODEID(block);
1202 fprintf (F, "\" targetname: \"");
1204 fprintf (F, "\"}\n");
1207 /* Dump dominator edge */
1208 if (dump_dominator_information_flag && get_Block_idom(block)) {
1209 pred = get_Block_idom(block);
1210 fprintf (F, "edge: { sourcename: \"");
1211 PRINT_NODEID(block);
1212 fprintf (F, "\" targetname: \"");
1214 fprintf (F, "\" " DOMINATOR_EDGE_ATTR "}\n");
1220 dump_cfg (ir_graph *irg)
1222 ir_graph *rem = current_ir_graph;
1223 int ddif = dump_dominator_information_flag;
1224 current_ir_graph = irg;
1225 vcg_open (irg, "-cfg");
1227 if (get_irg_dom_state(irg) != dom_consistent)
1228 dump_dominator_information_flag = 0;
1230 /* walk over the blocks in the graph */
1231 irg_block_walk(get_irg_end(irg), dump_block_to_cfg, NULL, NULL);
1232 dump_node (get_irg_bad(irg), NULL);
1234 dump_dominator_information_flag = ddif;
1236 current_ir_graph = rem;
1240 /***********************************************************************/
1241 /* the following routine dumps all type information reachable from an */
1243 /***********************************************************************/
1247 dump_type_graph (ir_graph *irg)
1250 rem = current_ir_graph;
1251 current_ir_graph = irg;
1253 vcg_open (irg, "-type");
1255 /* walk over the blocks in the graph */
1256 type_walk_irg(irg, dump_type_info, NULL, NULL);
1257 /* The walker for the const code can be called several times for the
1258 same (sub) experssion. So that no nodes are dumped several times
1259 we decrease the visited flag of the corresponding graph after each
1260 walk. So now increase it finally. */
1261 inc_irg_visited(get_const_code_irg());
1264 current_ir_graph = rem;
1267 /***********************************************************************/
1268 /* the following routine dumps all type information */
1269 /***********************************************************************/
1273 dump_all_types (void)
1275 vcg_open_name ("All_types");
1276 type_walk(dump_type_info, NULL, NULL);
1277 inc_irg_visited(get_const_code_irg());
1282 dump_class_hierarchy (bool entities)
1284 vcg_open_name ("class_hierarchy");
1286 type_walk(dump_class_hierarchy_node, NULL, (void *)1);
1288 type_walk(dump_class_hierarchy_node, NULL, NULL);
1292 /***********************************************************************/
1293 /* dumps a graph with type information */
1294 /***********************************************************************/
1298 dump_ir_graph_w_types (ir_graph *irg)
1301 rem = current_ir_graph;
1302 current_ir_graph = irg;
1304 vcg_open (irg, "-all");
1306 /* dump common ir graph */
1307 irg_walk(get_irg_end(irg), dump_whole_node, NULL, NULL);
1308 /* dump type info */
1309 type_walk_irg(irg, dump_type_info, NULL, NULL);
1310 inc_irg_visited(get_const_code_irg());
1311 /* dump edges from graph to type info */
1312 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1315 current_ir_graph = rem;
1319 dump_ir_block_graph_w_types (ir_graph *irg)
1322 rem = current_ir_graph;
1323 current_ir_graph = irg;
1325 vcg_open (irg, "-all");
1327 /* dump common blocked ir graph */
1328 dump_ir_block_graph_2(irg);
1329 /* dump type info */
1330 type_walk_irg(irg, dump_type_info, NULL, NULL);
1331 inc_irg_visited(get_const_code_irg());
1332 /* dump edges from graph to type info */
1333 irg_walk(get_irg_end(irg), dump_node2type_edges, NULL, NULL);
1336 current_ir_graph = rem;
1339 /***********************************************************************/
1340 /* dumps all graphs with the graph-dumper passed. Possible dumpers: */
1342 /* dump_ir_block_graph */
1344 /* dump_type_graph */
1345 /* dump_ir_graph_w_types */
1346 /***********************************************************************/
1347 void dump_all_ir_graphs (dump_graph_func *dump_graph) {
1349 for (i=0; i < get_irp_n_irgs(); i++) {
1350 dump_graph(get_irp_irg(i));
1355 /* To turn off display of edge labels. Edge labels offen cause xvcg to
1356 abort with a segmentation fault. */
1357 void turn_off_edge_labels(void) {
1362 void dump_consts_local(bool b) {
1363 dump_const_local = b;
1366 void turn_off_constant_entity_values(void) {
1370 void dump_keepalive_edges(bool b) {
1374 bool get_opt_dump_keepalive_edges(void) {
1375 return dump_keepalive;
1378 void dump_out_edges(void) {
1379 dump_out_edge_flag = 1;
1382 void dump_dominator_information(void) {
1383 dump_dominator_information_flag = 1;
1386 void dump_loop_information(void) {
1387 dump_loop_information_flag = 1;
1390 void dont_dump_loop_information(void) {
1391 dump_loop_information_flag = 0;
1394 static void clear_link(ir_node * node, void * env) {
1395 set_irn_link(node, NULL);
1398 static void collect_blocks_floats_cg(ir_node * node, pmap * map) {
1399 assert(node); assert(map);
1401 || node_floats(node)
1402 || get_irn_op(node) == op_Bad
1403 || get_irn_op(node) == op_Unknown) {
1404 pmap_entry * entry = pmap_find(map, current_ir_graph);
1410 ARR_APP1(ir_node *, arr , node);
1412 ir_node ** arr = NEW_ARR_F(ir_node *, 1);
1415 pmap_insert(map, current_ir_graph, arr);
1418 ir_node * block = get_nodes_Block(node);
1419 set_irn_link(node, get_irn_link(block));
1420 set_irn_link(block, node);
1425 static void dump_cg_ir_block(ir_node * block, void * env) {
1427 pmap *irgmap = (pmap *)env;
1428 assert(is_Block(block));
1429 fprintf(F, "graph: { title: \"");
1430 PRINT_NODEID(block);
1431 fprintf(F, "\" label: \"");
1432 fprintf (F, "%s ", get_op_name(get_irn_op(block)));
1433 #ifdef DEBUG_libfirm
1434 fprintf (F, "%ld", get_irn_node_nr(block));
1436 fprintf (F, "%p", (void*) block);
1438 if (exc_normal != get_Block_exc(block)) {
1439 fprintf (F, " (%s)", exc_to_string (get_Block_exc(block)));
1442 fprintf(F, "\" status:clustered color:%s \n",
1443 get_Block_matured(block) ? "yellow" : "red");
1445 /* dump the blocks edges */
1446 dump_ir_data_edges(block);
1448 /* dump the nodes that go into the block */
1449 for (node = get_irn_link(block); node; node = get_irn_link(node)) {
1450 dump_node(node, irgmap);
1451 dump_ir_data_edges(node);
1454 /* Close the vcg information for the block */
1455 fprintf(F, "}\n\n");
1458 static void d_cg_block_graph(ir_graph *irg, ir_node **arr, pmap *irgmap) {
1461 fprintf(F, "graph: { title: %p label: %s status:clustered color:white \n",
1462 (void*) irg, get_id_str(get_entity_ident(get_irg_ent(irg))));
1464 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1465 ir_node * node = arr[i];
1466 if (is_Block(node)) {
1467 /* Dumps the block and all the nodes in the block , which are to
1468 be found in Block->link. */
1469 dump_cg_ir_block(node, irgmap);
1471 /* Nodes that are not in a Block. */
1472 dump_node(node, NULL);
1473 dump_ir_data_edges(node);
1476 /* Close the vcg information for the irg */
1477 fprintf(F, "}\n\n");
1480 /* dump interprocedural graph with surrounding methods */
1481 void dump_cg_block_graph(ir_graph * irg) {
1482 pmap * map = pmap_create();
1483 pmap * map2 = pmap_create();
1488 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1489 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1490 pmap_insert(map2, entry->key, entry->value);
1491 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1492 d_cg_block_graph(entry->key, entry->value, map2);
1493 DEL_ARR_F(entry->value);
1499 if (dump_loop_information_flag) dump_loop_info(irg);
1503 static void collect_node(ir_node * node, void *env) {
1505 || node_floats(node)
1506 || get_irn_op(node) == op_Bad
1507 || get_irn_op(node) == op_Unknown) {
1508 ir_node ** arr = (ir_node **) get_irg_link(current_ir_graph);
1509 ARR_APP1(ir_node *, arr, node);
1510 set_irg_link(current_ir_graph, arr); /* arr is an l-value, APP_ARR might change it! */
1512 ir_node * block = get_nodes_Block(node);
1513 set_irn_link(node, get_irn_link(block));
1514 set_irn_link(block, node);
1518 /* Links all nodes that have the block field set in the link field of
1519 the block. Adds all blocks and nodes not associated with a block
1520 in a array in irg->link. */
1521 static void collect_nodes(void) {
1523 for (i = 0; i < get_irp_n_irgs(); i++)
1524 set_irg_link(get_irp_irg(i), NEW_ARR_F(ir_node *, 0));
1525 cg_walk(clear_link, collect_node, NULL);
1528 static void dump_graphs(void) {
1530 for (i = 0; i < get_irp_n_irgs(); i++) {
1531 current_ir_graph = get_irp_irg(i);
1532 d_cg_block_graph(current_ir_graph, get_irg_link(current_ir_graph), NULL);
1536 /* Dump all irgs in interprocedural view to a single file. */
1537 void dump_all_cg_block_graph(void) {
1539 int rem_view = interprocedural_view;
1540 interprocedural_view = 1;
1541 vcg_open_name ("All_graphs");
1546 if (dump_loop_information_flag)
1547 for (i = 0; i < get_irp_n_irgs(); i++)
1548 dump_loop_info(get_irp_irg(i));
1551 interprocedural_view = rem_view;
1554 /* dump interprocedural block graph with surrounding methods */
1555 void dump_cg_graph(ir_graph * irg) {
1556 pmap * map = pmap_create();
1557 pmap * map2 = pmap_create(); /* We can not iterate in the same map twice! */
1561 irg_walk_graph(irg, clear_link, (irg_walk_func *) collect_blocks_floats_cg, map);
1562 for (entry = pmap_first(map); entry; entry = pmap_next(map))
1563 pmap_insert(map2, entry->key, entry->value);
1564 for (entry = pmap_first(map); entry; entry = pmap_next(map)) {
1565 ir_node ** arr = entry->value;
1567 ident * irg_ident = get_entity_ident(get_irg_ent(entry->key));
1569 fprintf(F, "graph: { title: %s label: %s status:clustered color:white \n",
1570 get_id_str(irg_ident), get_id_str(irg_ident));
1572 for (i = ARR_LEN(arr) - 1; i >= 0; --i) {
1573 ir_node * node = arr[i];
1574 dump_node(node, map2);
1575 dump_ir_data_edges(node);
1576 if (is_Block(node)) {
1577 for (node = get_irn_link(node); node; node = get_irn_link(node)) {
1578 dump_node(node, map2);
1579 dump_ir_block_edge(node);
1580 dump_ir_data_edges(node);
1587 /* Close the vcg information for the irg */
1588 fprintf(F, "}\n\n");