From: Götz Lindenmaier Date: Thu, 2 Sep 2004 14:09:49 +0000 (+0000) Subject: added test dumper X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=992ae79a29430a9cebce74cbb3eaa8eacfac98fe;p=libfirm added test dumper [r3813] --- diff --git a/ir/ir/Makefile.in b/ir/ir/Makefile.in index 68c591602..efbc7bd0b 100644 --- a/ir/ir/Makefile.in +++ b/ir/ir/Makefile.in @@ -22,8 +22,8 @@ INSTALL_HEADERS = irprog.h irgraph.h irnode.h irmode.h irop.h ircons.h \ SOURCES = $(INSTALL_HEADERS) SOURCES += Makefile.in \ - ircons.c ircons_t.h irgmod.c irgraph_t.h irnode.c iropt.c irvrfy.c \ - irgwalk.c irgwalk_blk.c irdump.c irgopt.c irnode_t.h iropt_t.h \ + ircons.c ircons_t.h irgmod.c irgraph_t.h irnode.c iropt.c iropt_t.h irvrfy.c \ + irgwalk.c irgwalk_blk.c irdump.c irdumptxt.c irgopt.c irnode_t.h \ irmode.c irop.c irprog.c irflag.c irflag_t.h irgraph.c \ irmode_t.h irop_t.h irprog_t.h ircgcons.c ircgopt.c diff --git a/ir/ir/irdump.c b/ir/ir/irdump.c index f75115d99..62b2da5bb 100644 --- a/ir/ir/irdump.c +++ b/ir/ir/irdump.c @@ -11,20 +11,17 @@ */ -#ifdef HAVE_CONFIG_H -# include -#endif - #include #include #include +#include "firm_common_t.h" + #include "irnode_t.h" #include "irgraph_t.h" #include "irprog_t.h" #include "entity_t.h" #include "irop_t.h" -#include "firm_common_t.h" #include "irdump.h" @@ -113,7 +110,9 @@ SeqNo get_Block_seqno(ir_node *n); #endif -int my_special_flag = 0; +/* basis for a color range for vcg */ +static int n_colors = 0; +static int base_color = 0; static const char *get_mode_name_ex(ir_mode *mode, int *bad) { @@ -236,10 +235,6 @@ static void print_enum_item_edge(FILE *F, type *E, int item, const char *fmt, .. /* global and ahead declarations */ /*******************************************************************/ -/* A suffix to manipulate the file name. */ - -char *dump_file_filter = ""; - static void dump_whole_node(ir_node *n, void *env); static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg); @@ -360,6 +355,8 @@ static ir_node ** construct_block_lists(ir_graph *irg) { /* flags to steer output */ /*******************************************************************/ +const char *dump_file_filter = ""; + /* A compiler option to turn off edge labels */ int edge_label = 1; /* A compiler option to turn off dumping values of constant entities */ @@ -384,6 +381,11 @@ INLINE bool get_opt_dump_const_local(void) { return false; } +void only_dump_method_with_name(ident *name) { + dump_file_filter = get_id_str(name); +} + + /* To turn off display of edge labels. Edge labels offen cause xvcg to abort with a segmentation fault. */ void turn_off_edge_labels(void) { @@ -1338,16 +1340,20 @@ static int print_type_node(FILE *F, type *tp) } #define X(a) case a: fprintf(F, #a); break -void dump_entity_node(FILE *F, entity *ent) +void dump_entity_node(FILE *F, entity *ent, int color) { fprintf (F, "node: {title: \""); PRINT_ENTID(ent); fprintf(F, "\""); fprintf (F, DEFAULT_TYPE_ATTRIBUTE); fprintf (F, "label: "); - fprintf (F, "\"ent %s\" " ENTITY_NODE_ATTR , get_ent_dump_name(ent)); + fprintf (F, "\"ent %s\" ", get_ent_dump_name(ent)); + if (color) + fprintf(F, "color: %d", color); + else + fprintf (F, ENTITY_NODE_ATTR); fprintf (F, "\n info1: \""); - dump_entity_to_file(F, ent); + dump_entity_to_file(F, ent, dump_verbosity_max); fprintf(F, "\"\n}\n"); } @@ -1382,7 +1388,7 @@ dump_type_info(type_or_ent *tore, void *env) { entity *ent = (entity *)tore; ir_node *value; /* The node */ - dump_entity_node(F, ent); + dump_entity_node(F, ent, 0); /* The Edges */ /* skip this to reduce graph. Member edge of type is parallel to this edge. * fprintf (F, "edge: { sourcename: \"%p\" targetname: \"%p\" " @@ -1511,7 +1517,7 @@ dump_class_hierarchy_node (type_or_ent *tore, void *ctx) { if (!is_method_type(get_entity_type(ent))) break; /* GL */ if (env->dump_ent && is_class_type(get_entity_owner(ent))) { /* The node */ - dump_entity_node(F, ent); + dump_entity_node(F, ent, 0); /* The edges */ print_type_ent_edge(F,get_entity_owner(ent),ent,TYPE_MEMBER_EDGE_ATTR); for(i = 0; i < get_entity_n_overwrites(ent); i++) @@ -1684,6 +1690,39 @@ dump_vcg_header(FILE *F, const char *name, const char *orientation) { "infoname 2: \"Verification errors\"\n", name, label, orientation); + /* don't use all, the range is too whith/black. */ + n_colors = 18; + base_color = 105; + fprintf (F, + "colorentry 100: 0 0 0\n" + "colorentry 101: 20 0 0\n" + "colorentry 102: 40 0 0\n" + "colorentry 103: 60 0 0\n" + "colorentry 104: 80 0 0\n" + "colorentry 105: 100 0 0\n" + "colorentry 106: 120 0 0\n" + "colorentry 107: 140 0 0\n" + "colorentry 108: 150 0 0\n" + "colorentry 109: 180 0 0\n" + "colorentry 110: 200 0 0\n" + "colorentry 111: 220 0 0\n" + "colorentry 112: 240 0 0\n" + "colorentry 113: 255 0 0\n" + "colorentry 113: 255 20 20\n" + "colorentry 114: 255 40 40\n" + "colorentry 115: 255 60 60\n" + "colorentry 116: 255 80 80\n" + "colorentry 117: 255 100 100\n" + "colorentry 118: 255 120 120\n" + "colorentry 119: 255 140 140\n" + "colorentry 120: 255 150 150\n" + "colorentry 121: 255 180 180\n" + "colorentry 122: 255 200 200\n" + "colorentry 123: 255 220 220\n" + "colorentry 124: 255 240 240\n" + "colorentry 125: 255 250 250\n" + ); + fprintf (F, "\n"); /* a separator */ } @@ -1804,7 +1843,7 @@ dump_ir_graph (ir_graph *irg, const char *suffix ) char *suffix1; rem = current_ir_graph; - if(strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter))!=0) return; + if (strncmp(get_entity_name(get_irg_entity(irg)), dump_file_filter, strlen(dump_file_filter)) != 0) return; current_ir_graph = irg; if (interprocedural_view) suffix1 = "-pure-ip"; else suffix1 = "-pure"; @@ -2001,13 +2040,51 @@ dump_cfg (ir_graph *irg, const char *suffix) current_ir_graph = rem; } +static int weight_overall(int rec, int loop) { + return 2*rec + loop; +} + +static int compute_color (int my, int max) { + int color; + if (!max) { + color = 0; + } else { + /* if small, scale to the full color range. */ + if (max < n_colors) + my = my * (n_colors/max); + + int step = 1 + (max / n_colors); + + color = my/step; + } + return base_color + n_colors - color; +} + +static int get_entity_color(entity *ent) { + assert(get_entity_irg(ent)); + ir_graph *irg = get_entity_irg(ent); + + int rec_depth = get_irg_recursion_depth(irg); + int loop_depth = get_irg_loop_depth(irg); + int overall_depth = weight_overall(rec_depth, loop_depth); + + int max_rec_depth = irp->max_callgraph_recursion_depth; + int max_loop_depth = irp->max_callgraph_loop_depth; + int max_overall_depth = weight_overall(max_rec_depth, max_loop_depth); + + int my_rec_color = compute_color(rec_depth, max_rec_depth); + int my_loop_color = compute_color(loop_depth, max_loop_depth); + int my_overall_color = compute_color(overall_depth, max_overall_depth);; + + return my_overall_color; +} + void dump_callgraph(const char *suffix) { FILE *F; int i, n_irgs = get_irp_n_irgs(); int rem = edge_label; edge_label = 1; - - my_special_flag = 1; + //ident *prefix = new_id_from_str("java/"); F = vcg_open_name("Callgraph", suffix); dump_vcg_header(F, "Callgraph", NULL); @@ -2017,19 +2094,22 @@ void dump_callgraph(const char *suffix) { entity *ent = get_irg_entity(irg); int j, n_callees = get_irg_n_callees(irg); - dump_entity_node(F, ent); + /* Do not dump runtime system. */ + //if (id_is_prefix(prefix, get_entity_ld_ident(ent))) continue; + + dump_entity_node(F, ent, get_entity_color(ent)); for (j = 0; j < n_callees; ++j) { entity *c = get_irg_entity(get_irg_callee(irg, j)); + //if (id_is_prefix(prefix, get_entity_ld_ident(c))) continue; int be = is_irg_callee_backedge(irg, j); char *attr; attr = (be) ? - "label:\"recursion %d\" color:red" : - "label:\"calls %d\""; - print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j)); + "label:\"recursion %d\" color: %d" : + "label:\"calls %d\" color: %d"; + print_ent_ent_edge(F, ent, c, be, attr, get_irg_callee_loop_depth(irg, j), get_entity_color(ent)); } } - my_special_flag = 0; edge_label = rem; vcg_close(F); } @@ -2247,7 +2327,7 @@ void dump_loop_tree(ir_graph *irg, const char *suffix) current_ir_graph = rem; } -void dump_callgraph_loop_tree(char *suffix) { +void dump_callgraph_loop_tree(const char *suffix) { FILE *F; F = vcg_open_name("Callgraph_looptree", suffix); dump_vcg_header(F, "callgraph looptree", "top_to_bottom"); diff --git a/ir/ir/irdump.h b/ir/ir/irdump.h index d19bda549..8d92ad40c 100644 --- a/ir/ir/irdump.h +++ b/ir/ir/irdump.h @@ -38,11 +38,11 @@ # include "irloop.h" -/** Set this to the name (not the ld_name) of the method to be dumped. */ -extern char *dump_file_filter; +/* **************************************************************************** */ +/* GRAPH DUMPERS */ +/* **************************************************************************** */ -/** - * Dump a firm graph. +/** Dump a firm graph. * * @param irg The firm graph to be dumped. * @@ -59,10 +59,8 @@ extern char *dump_file_filter; * @see turn_off_edge_labels() */ void dump_ir_graph (ir_graph *irg, const char *suffix); -#define dump_cg_graph dump_ir_graph -/** - * Dump a firm graph without explicit block nodes. +/** Dump a firm graph without explicit block nodes. * * @param irg The firm graph to be dumped. * @@ -79,14 +77,12 @@ void dump_ir_graph (ir_graph *irg, const char *suffix); * @see turn_off_edge_labels() */ void dump_ir_block_graph (ir_graph *irg, const char *suffix); -#define dump_cg_block_graph dump_ir_block_graph /** Dumps all graphs in interprocedural view to a file named All_graphs.vcg. */ void dump_all_cg_block_graph(const char *suffix); -/** - * Dumps a firm graph and all the type information needed for Calls, +/** Dumps a firm graph and all the type information needed for Calls, * Sels, ... in this graph. * * @param irg The firm graph to be dumped with its type information. @@ -102,8 +98,7 @@ void dump_all_cg_block_graph(const char *suffix); */ void dump_ir_graph_w_types (ir_graph *irg, const char *suffix); -/** - * Dumps a firm graph and all the type information needed for Calls, +/** Dumps a firm graph and all the type information needed for Calls, * Sels, ... in this graph. * * @param irg The firm graph to be dumped with its type information. @@ -120,15 +115,13 @@ void dump_ir_graph_w_types (ir_graph *irg, const char *suffix); */ void dump_ir_block_graph_w_types (ir_graph *irg, const char *suffix); -/** - * The type of a walker function that is called for each graph. +/** The type of a walker function that is called for each graph. * - * @param irg current visited graph + * @param irg current visited graph */ typedef void dump_graph_func(ir_graph *irg, const char *suffix); -/** - * A walker that calls a dumper for each graph. +/** A walker that calls a dumper for each graph. * * @param dump_graph The dumper to be used for dumping. * @@ -148,8 +141,7 @@ typedef void dump_graph_func(ir_graph *irg, const char *suffix); void dump_all_ir_graphs (dump_graph_func *dump_graph, const char *suffix); -/** - * Dump the control flow graph of a procedure. +/** Dump the control flow graph of a procedure. * * @param irg The firm graph whose CFG shall be dumped. * @@ -166,12 +158,21 @@ void dump_all_ir_graphs (dump_graph_func *dump_graph, const char *suffix); void dump_cfg (ir_graph *irg, const char *suffix); +/* **************************************************************************** */ +/* CALLGRAPH DUMPERS */ +/* **************************************************************************** */ + + /** Dump the call graph. * * Dumps the callgraph to a file "Callgraph"".vcg". */ void dump_callgraph(const char *suffix); +/* **************************************************************************** */ +/* TYPEGRAPH DUMPERS */ +/* **************************************************************************** */ + /** * Dumps all the type information needed for Calls, Sels, ... in this graph. * Does not dump the graph! @@ -188,8 +189,7 @@ void dump_callgraph(const char *suffix); */ void dump_type_graph (ir_graph *irg, const char *suffix); -/** - * Dumps all type information. +/** Dumps all type information. * * @return * A file containing all type information for the program in standard @@ -203,8 +203,7 @@ void dump_type_graph (ir_graph *irg, const char *suffix); */ void dump_all_types (const char *suffix); -/** - * Dumps the class hierarchy with or without entities. +/** Dumps the class hierarchy with or without entities. * * @param entities Flag whether to dump the entities. * @@ -221,6 +220,9 @@ void dump_all_types (const char *suffix); */ void dump_class_hierarchy (bool entities, const char *suffix); +/* **************************************************************************** */ +/* LOOPTREE DUMPERS */ +/* **************************************************************************** */ /** * Dump a standalone loop tree, which contains the loop nodes and the firm nodes @@ -236,8 +238,8 @@ void dump_class_hierarchy (bool entities, const char *suffix); void dump_loop_tree(ir_graph *irg, const char *suffix); /** Dumps the firm nodes in the sub-loop-tree of loop to a graph. - * Dumps the loop nodes if dump_loop_information() is set. * + * Dumps the loop nodes if dump_loop_information() is set. * The name of the file is loop_.vcg. * * @arg loop Dump the loop tree for this loop. @@ -252,7 +254,90 @@ void dump_loop (ir_loop *l, const char *suffix); * * @arg suffix Suffix to filename. */ -void dump_callgraph_loop_tree(char *suffix); +void dump_callgraph_loop_tree(const char *suffix); + + +/* **************************************************************************** */ +/* TEXT DUMPERS */ +/* **************************************************************************** */ + +/** Verbosity for text dumpers */ +typedef enum { + dump_verbosity_onlynames = 0x00000001, /**< only dump type names. turns off all other + flags up to 0x00010000. */ + dump_verbosity_fields = 0x00000002, /**< dump types and fields (like a type declaration) */ + dump_verbosity_methods = 0x00000004, /**< dump types and methods (like a type declaration) */ + dump_verbosity_typeattrs = 0x00000008, /**< dump all type attributes */ + dump_verbosity_entattrs = 0x00000010, /**< dump all entity attributes */ + dump_verbosity_entconsts = 0x00000020, /**< dump entity constants */ + + dump_verbosity_noClassTypes = 0x00001000, /**< dump no class types */ + dump_verbosity_noStructTypes = 0x00002000, /**< dump no struct types */ + dump_verbosity_noUnionTypes = 0x00004000, /**< dump no union types */ + dump_verbosity_noArrayTypes = 0x00008000, /**< dump no array types */ + dump_verbosity_noPointerTypes = 0x00010000, /**< dump no pointer types */ + dump_verbosity_noMethodTypes = 0x00020000, /**< dump no method types */ + dump_verbosity_noPrimitiveTypes = 0x00040000, /**< dump no primitive types */ + dump_verbosity_noEnumerationTypes= 0x00080000, /**< dump no enumeration types */ + + dump_verbosity_onlyClassTypes = 0x000FE000, /**< dump only class types */ + dump_verbosity_onlyStructTypes = 0x000FD000, /**< dump only struct types */ + dump_verbosity_onlyUnionTypes = 0x000FB000, /**< dump only union types */ + dump_verbosity_onlyArrayTypes = 0x000F8000, /**< dump only array types */ + dump_verbosity_onlyPointerTypes = 0x000EF000, /**< dump only pointer types */ + dump_verbosity_onlyMethodTypes = 0x000DF000, /**< dump only method types */ + dump_verbosity_onlyPrimitiveTypes = 0x000BF000, /**< dump only primitive types */ + dump_verbosity_onlyEnumerationTypes=0x0008F000, /**< dump only enumeration types */ + + dump_verbosity_max = 0x48888888, /**< turn on all verbosity. */ +} dump_verbosity; + + +/** Write the entity and all its attributes to the passed file. + * */ +void dump_entity_to_file (FILE *F, entity *ent, unsigned verbosity); + +/** Write the entity and all its attributes to the stdout. + * + * Calls dump_entity_to_file(). */ +void dump_entity (entity *ent); + +/** Write the type and all its attributes to the file passed. + * */ +void dump_type_to_file (FILE *f, type *tp, unsigned verbosity); + +/** Write the type and all its attributes to stdout. + * */ +void dump_type (type *tp); + + +/** Dump type information as text. + * + * Often type graphs are unhandy in their vcg representation. The text + * dumper represents the information for a single type more compact, but + * the relations between the types only implicitly. + * Dumps only 'real' types, i.e., those in the type list. Does not dump + * the global type nor frame types or the like. + * + * The file name is the program name (get_irp_name()), or 'TextTypes' + * if the program name is not set appended by -types.txt. + */ +void dump_types_as_text(unsigned verbosity, const char *suffix); + +/* **************************************************************************** */ +/* FLAGS */ +/* **************************************************************************** */ + +/** Output a selected graph. + * + * All graph dumpers check this name. If the name is != "" and + * not a prefix of the graph to be dumped, the dumper does not + * dump the graph. + * + * @param name The prefix of the name (not the ld_name) of the method + * entity to be dumped. + */ +void only_dump_method_with_name(ident *name); /** Sets the vcg flag "display_edge_labels" to no. * @@ -263,7 +348,7 @@ void turn_off_edge_labels(void); /** * If set to true constants will be replicated for every use. In non - * blocked view edges from constant to block are scipped. Vcg then + * blocked view edges from constant to block are skipped. Vcg then * layouts the graphs more compact, this makes them better readable. * The flag is automatically and temporarily set to false if other * edges are dumped, as outs, loop, ... @@ -277,35 +362,33 @@ void dump_consts_local(bool b); */ bool get_opt_dump_const_local(void); -/** - * Turns off dumping the values of constant entities. Makes type graphs +/** Turns off dumping the values of constant entities. Makes type graphs * better readable. */ void turn_off_constant_entity_values(void); -/** - * Turns on dumping the edges from the End node to nodes to be kept - * alive +/** Turns on dumping the edges from the End node to nodes to be kept + * alive. */ void dump_keepalive_edges(bool b); bool get_opt_dump_keepalive_edges(void); -/** - * Turns on dumping the out edges starting from the Start block in - * dump_ir_graph. To test the consistency of the out datastructure. +/** Turns on dumping the out edges starting from the Start block in + * dump_ir_graph. + * + * To test the consistency of the out datastructure. */ void dump_out_edges(void); -/** - * If this flag is set the dumper dumps edges to immediate dominator in cfg. +/** If this flag is set the dumper dumps edges to immediate dominator in cfg. */ void dump_dominator_information(void); -/** - * If this flag is set the dumper dumps loop nodes and edges from - * these nodes to the contained ir nodes. - * Can be turned off with dont_dump_loop_information(). - * If the loops are interprocedural nodes can be missing. +/** If this flag is set the dumper dumps loop nodes and edges from + * these nodes to the contained ir nodes. + * + * Can be turned off with dont_dump_loop_information(). + * If the loops are interprocedural nodes can be missing. */ void dump_loop_information(void); @@ -314,23 +397,24 @@ void dump_loop_information(void); */ void dont_dump_loop_information(void); -/** - * If set and backedge info is computed, backedges are dumped dashed - * and as vcg 'backedge' construct. Default: set. +/** If set and backedge info is computed, backedges are dumped dashed + * and as vcg 'backedge' construct. + * + * Default: set. */ void dump_backedge_information(bool b); -/** - * Dump the information of type field specified in ana/irtypeinfo.h. +/** Dump the information of type field specified in ana/irtypeinfo.h. + * * If the flag is set, the type name is output in [] in the node label, * else it is output as info. */ void dump_analysed_type_info(bool b); -/** - * Write the address of a node into the vcg info. - * This is off per default for automatic comparisons of - * vcg graphs -- these will differ in the pointer values! +/** Write the address of a node into the vcg info. + * + * This is off per default for automatic comparisons of + * vcg graphs -- these will differ in the pointer values! */ void dump_pointer_values_to_info(bool b); diff --git a/ir/ir/irdumptxt.c b/ir/ir/irdumptxt.c new file mode 100644 index 000000000..39be89f62 --- /dev/null +++ b/ir/ir/irdumptxt.c @@ -0,0 +1,294 @@ +/* + * Project: libFIRM + * File name: ir/ir/irdump.c + * Purpose: Write vcg representation of firm to file. + * Author: Martin Trapp, Christian Schaefer + * Modified by: Goetz Lindenmaier, Hubert Schmidt + * Created: + * CVS-ID: $Id$ + * Copyright: (c) 1998-2003 Universität Karlsruhe + * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + */ + +#include +#include +#include + +#include "irdump.h" + +#include "firm_common_t.h" + +#include "irgraph_t.h" +#include "irprog_t.h" +#include "entity_t.h" + +int dump_node_opcode(FILE *F, ir_node *n); /* from irdump.c */ + + + +#define X(a) case a: fprintf(F, #a); break +void dump_entity_to_file_prefix (FILE *F, entity *ent, char *prefix, unsigned verbosity) { + int i, j; + assert(ent && ent->kind == k_entity); + type *owner = get_entity_owner(ent); + type *type = get_entity_type(ent); + + if (verbosity & dump_verbosity_onlynames) { + fprintf(F, "%sentity %s (%ld)\n", prefix, get_entity_name(ent), get_entity_nr(ent)); + return; + } + + if (verbosity & dump_verbosity_entattrs) { + fprintf(F, "%sentity %s (%ld)\n", prefix, get_entity_name(ent), get_entity_nr(ent)); + fprintf(F, "%s type: %s (%ld)\n", prefix, get_type_name(type), get_type_nr(type)); + fprintf(F, "%s owner: %s (%ld)\n", prefix, get_type_name(owner), get_type_nr(owner)); + + if (is_class_type(get_entity_owner(ent))) { + if (get_entity_n_overwrites(ent) > 0) { + fprintf(F, "%s overwrites:\n", prefix); + for (i = 0; i < get_entity_n_overwrites(ent); ++i) { + entity *ov = get_entity_overwrites(ent, i); + fprintf(F, "%s %d: %s of class %s\n", prefix, i, get_entity_name(ov), + get_type_name(get_entity_owner(ov))); + } + } else { + fprintf(F, "%s Does not overwrite other entities. \n", prefix); + } + if (get_entity_n_overwrittenby(ent) > 0) { + fprintf(F, "%s overwritten by:\n", prefix); + for (i = 0; i < get_entity_n_overwrittenby(ent); ++i) { + entity *ov = get_entity_overwrittenby(ent, i); + fprintf(F, "%s %d: %s of class %s\n", prefix, i, get_entity_name(ov), + get_type_name(get_entity_owner(ov))); + } + } else { + fprintf(F, "%s Is not overwriten by other entities. \n", prefix); + } + } + + fprintf(F, "%s allocation: ", prefix); + switch (get_entity_allocation(ent)) { + X(allocation_dynamic); + X(allocation_automatic); + X(allocation_static); + X(allocation_parameter); + } + + fprintf(F, "\n%s visibility: ", prefix); + switch (get_entity_visibility(ent)) { + X(visibility_local); + X(visibility_external_visible); + X(visibility_external_allocated); + } + + fprintf(F, "\n%s variability: ", prefix); + switch (get_entity_variability(ent)) { + X(variability_uninitialized); + X(variability_initialized); + X(variability_part_constant); + X(variability_constant); + } + fprintf(F, "\n"); + } else { /* no entityattrs */ + fprintf(F, "%s(%3d) %*s: %s", prefix, + get_entity_offset_bits(ent), -40, get_type_name(get_entity_type(ent)), get_entity_name(ent)); + if (is_method_type(get_entity_type(ent))) fprintf(F, "(...)"); + fprintf(F, "\n"); + } + + if (verbosity & dump_verbosity_entconsts) { + if (get_entity_variability(ent) != variability_uninitialized) { + if (is_atomic_entity(ent)) { + fprintf(F, "%s atomic value: ", prefix); + dump_node_opcode(F, get_atomic_ent_value(ent)); + } else { + fprintf(F, "%s compound values:", prefix); + for (i = 0; i < get_compound_ent_n_values(ent); ++i) { + compound_graph_path *path = get_compound_ent_value_path(ent, i); + entity *ent0 = get_compound_graph_path_node(path, 0); + fprintf(F, "\n%s %3d ", prefix, get_entity_offset_bits(ent0)); + if (get_type_state(type) == layout_fixed) + fprintf(F, "(%3d) ", get_compound_ent_value_offset_bits(ent, i)); + fprintf(F, "%s", get_entity_name(ent0)); + for (j = 0; j < get_compound_graph_path_length(path); ++j) { + entity *node = get_compound_graph_path_node(path, j); + fprintf(F, ".%s", get_entity_name(node)); + if (is_array_type(get_entity_owner(node))) + fprintf(F, "[%d]", get_compound_graph_path_array_index(path, j)); + } + fprintf(F, "\t = "); + dump_node_opcode(F, get_compound_ent_value(ent, i)); + } + } + fprintf(F, "\n"); + } + } + + + if (verbosity & dump_verbosity_entattrs) { + fprintf(F, "%s volatility: ", prefix); + switch (get_entity_volatility(ent)) { + X(volatility_non_volatile); + X(volatility_is_volatile); + } + + fprintf(F, "\n%s peculiarity: %s", prefix, get_peculiarity_string(get_entity_peculiarity(ent))); + fprintf(F, "\n%s ld_name: %s", prefix, ent->ld_name ? get_entity_ld_name(ent) : "no yet set"); + fprintf(F, "\n%s offset: %d", prefix, get_entity_offset_bits(ent)); + if (is_method_type(get_entity_type(ent))) { + if (get_entity_irg(ent)) /* can be null */ { + fprintf(F, "\n%s irg = %ld", prefix, get_irg_graph_nr(get_entity_irg(ent))); + if (get_irp_callgraph_state() == irp_callgraph_and_calltree_consistent) { + fprintf(F, "\n%s recursion depth %d", prefix, get_irg_recursion_depth(get_entity_irg(ent))); + fprintf(F, "\n%s loop depth %d", prefix, get_irg_loop_depth(get_entity_irg(ent))); + } + } else { + fprintf(F, "\n%s irg = NULL", prefix); + } + } + fprintf(F, "\n"); + } +} +#undef X + +void dump_entity_to_file (FILE *F, entity *ent, unsigned verbosity) { + dump_entity_to_file_prefix (F, ent, "", verbosity); + fprintf(F, "\n"); +} + +void dump_entity (entity *ent) { + dump_entity_to_file(stdout, ent, dump_verbosity_max); +} + +void dump_type_to_file (FILE *F, type *tp, dump_verbosity verbosity) { + int i; + + if ((is_class_type(tp)) && (verbosity & dump_verbosity_noClassTypes)) return; + if ((is_struct_type(tp)) && (verbosity & dump_verbosity_noStructTypes)) return; + if ((is_union_type(tp)) && (verbosity & dump_verbosity_noUnionTypes)) return; + if ((is_array_type(tp)) && (verbosity & dump_verbosity_noArrayTypes)) return; + if ((is_pointer_type(tp)) && (verbosity & dump_verbosity_noPointerTypes)) return; + if ((is_method_type(tp)) && (verbosity & dump_verbosity_noMethodTypes)) return; + if ((is_primitive_type(tp)) && (verbosity & dump_verbosity_noPrimitiveTypes)) return; + if ((is_enumeration_type(tp)) && (verbosity & dump_verbosity_noEnumerationTypes)) return; + + fprintf(F, "%s type %s (%ld)", get_tpop_name(get_type_tpop(tp)), get_type_name(tp), get_type_nr(tp)); + if (verbosity & dump_verbosity_onlynames) { fprintf(F, "\n"); return; } + + switch (get_type_tpop_code(tp)) { + + case tpo_class: + if ((verbosity & dump_verbosity_methods) || (verbosity & dump_verbosity_fields)) { + fprintf(F, "\n members: \n"); + } + for (i = 0; i < get_class_n_members(tp); ++i) { + entity *mem = get_class_member(tp, i); + if (((verbosity & dump_verbosity_methods) && is_method_type(get_entity_type(mem))) || + ((verbosity & dump_verbosity_fields) && !is_method_type(get_entity_type(mem))) ) { + dump_entity_to_file_prefix(F, mem, " ", verbosity); + } + } + if (verbosity & dump_verbosity_typeattrs) { + fprintf(F, " supertypes: "); + for (i = 0; i < get_class_n_supertypes(tp); ++i) { + type *stp = get_class_supertype(tp, i); + fprintf(F, "\n %s", get_type_name(stp)); + } + fprintf(F, "\n subtypes: "); + for (i = 0; i < get_class_n_subtypes(tp); ++i) { + type *stp = get_class_subtype(tp, i); + fprintf(F, "\n %s", get_type_name(stp)); + } + + fprintf(F, "\n peculiarity: %s", get_peculiarity_string(get_class_peculiarity(tp))); + } + break; + + case tpo_union: + case tpo_struct: + if (verbosity & dump_verbosity_fields) fprintf(F, "\n members: "); + for (i = 0; i < get_compound_n_members(tp); ++i) { + entity *mem = get_compound_member(tp, i); + if (verbosity & dump_verbosity_fields) { + dump_entity_to_file_prefix(F, mem, " ", verbosity); + } + } + break; + + case tpo_pointer: { + if (verbosity & dump_verbosity_typeattrs) { + type *tt = get_pointer_points_to_type(tp); + fprintf(F, "\n points to %s (%ld)", get_type_name(tt), get_type_nr(tt)); + } + + } break; + + default: + if (verbosity & dump_verbosity_typeattrs) { + fprintf(F, ": details not implemented\n"); + } + } + fprintf(F, "\n\n"); +} + +void dump_type(type *tp) { + dump_type_to_file (stdout, tp, dump_verbosity_max); +} + + + +static FILE *text_open (const char *basename, const char * suffix1, const char *suffix2) { + FILE *F; + int len = strlen(basename), i, j; + char *fname; /* filename to put the vcg information in */ + + if (!basename) assert(basename); + if (!suffix1) suffix1 = ""; + if (!suffix2) suffix2 = ""; + + /* open file for vcg graph */ + fname = malloc (strlen(basename)*2 + strlen(suffix1) + strlen(suffix2) + 5); /* *2: space for excapes. */ + + j = 0; + for (i = 0; i < len; ++i) { /* replase '/' in the name: escape by @. */ + if (basename[i] == '/') { + fname[j] = '@'; j++; fname[j] = '1'; j++; + } else if (basename[i] == '@') { + fname[j] = '@'; j++; fname[j] = '2'; j++; + } else { + fname[j] = basename[i]; j++; + } + } + fname[j] = '\0'; + strcat (fname, suffix1); /* append file suffix */ + strcat (fname, suffix2); /* append file suffix */ + strcat (fname, ".txt"); /* append the .txt suffix */ + + F = fopen (fname, "w"); /* open file for writing */ + if (!F) { + assert(0); + } + free(fname); + + return F; +} + +void dump_types_as_text(unsigned verbosity, const char *suffix) { + const char *basename; + FILE *F; + int i, n_types = get_irp_n_types(); + + if (get_irp_prog_ident() == new_id_from_str("no_name_set")) { + basename = "TextTypes"; + } else { + basename = get_irp_prog_name(); + } + F = text_open (basename, suffix, "-types"); + + for (i = 0; i < n_types; ++i) { + type *t = get_irp_type(i); + dump_type_to_file(F, t, verbosity); + } + + fclose (F); +}