+/*-----------------------------------------------------------------*/
+/* global and ahead declarations */
+/*-----------------------------------------------------------------*/
+
+static void dump_whole_node(ir_node *n, void *env);
+static INLINE void dump_loop_nodes_into_graph(FILE *F, ir_graph *irg);
+
+/*-----------------------------------------------------------------*/
+/* Helper functions. */
+/*-----------------------------------------------------------------*/
+
+/**
+ * This map is used as a private link attr to be able to call dumper
+ * anywhere without destroying link fields.
+ */
+static pmap *irdump_link_map = NULL;
+
+/** NOT A STANDARD LIBFIRM INIT METHOD
+ *
+ * We do not want to integrate dumping into libfirm, i.e., if the dumpers
+ * are off, we want to have as few interferences as possible. Therefore the
+ * initialization is performed lazily and not called from within init_firm.
+ *
+ * Creates the link attribute map. */
+static void init_irdump(void) {
+ /* We need a new, empty map. */
+ if (irdump_link_map) pmap_destroy(irdump_link_map);
+ irdump_link_map = pmap_create();
+ if (!dump_file_filter_id)
+ dump_file_filter_id = new_id_from_str("");
+}
+
+/**
+ * Returns the private link field.
+ */
+static void *ird_get_irn_link(ir_node *n) {
+ void *res = NULL;
+ if (!irdump_link_map) return NULL;
+
+ if (pmap_contains(irdump_link_map, (void *)n))
+ res = pmap_get(irdump_link_map, (void *)n);
+ return res;
+}
+
+/**
+ * Sets the private link field.
+ */
+static void ird_set_irn_link(ir_node *n, void *x) {
+ if (!irdump_link_map)
+ init_irdump();
+ pmap_insert(irdump_link_map, (void *)n, x);
+}
+
+/**
+ * Gets the private link field of an irg.
+ */
+static void *ird_get_irg_link(ir_graph *irg) {
+ void *res = NULL;
+ if (!irdump_link_map) return NULL;
+
+ if (pmap_contains(irdump_link_map, (void *)irg))
+ res = pmap_get(irdump_link_map, (void *)irg);
+ return res;
+}
+
+/**
+ * Sets the private link field of an irg.
+ */
+static void ird_set_irg_link(ir_graph *irg, void *x) {
+ if (!irdump_link_map) init_irdump();
+ pmap_insert(irdump_link_map, (void *)irg, x);
+}
+
+/**
+ * Walker, clears the private link field.
+ */
+static void clear_link(ir_node * node, void * env) {
+ (void) env;
+ ird_set_irn_link(node, NULL);
+}
+
+/**
+ * If the entity has a ld_name, returns it if the dump_ld_name is set,
+ * else returns the name of the entity.
+ */
+static const char *_get_ent_dump_name(ir_entity *ent, int dump_ld_name) {
+ if (!ent)
+ return "<NULL entity>";
+ if (dump_ld_name) {
+ /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
+ if (ent->ld_name) return get_id_str(ent->ld_name);
+ }
+ return get_id_str(ent->name);
+}
+
+/**
+ * If the entity has a ld_name, returns it if the option dump_ld_name is set,
+ * else returns the name of the entity.
+ */
+const char *get_ent_dump_name(ir_entity *ent) {
+ return _get_ent_dump_name(ent, dump_ld_name);
+}
+
+/* Returns the name of an IRG. */
+const char *get_irg_dump_name(ir_graph *irg) {
+ /* Don't use get_entity_ld_ident (ent) as it computes the mangled name! */
+ return _get_ent_dump_name(get_irg_entity(irg), 1);
+}
+
+/**
+ * Returns non-zero if a node is in floating state.
+ */
+static int node_floats(ir_node *n) {
+ return ((get_irn_pinned(n) == op_pin_state_floats) &&
+ (get_irg_pinned(current_ir_graph) == op_pin_state_floats));
+}
+
+/**
+ * Walker that visits the anchors
+ */
+static void ird_walk_graph(ir_graph *irg, irg_walk_func *pre, irg_walk_func *post, void *env) {
+ if (dump_anchors) {
+ irg_walk_anchors(irg, pre, post, env);
+ } else {
+ irg_walk_graph(irg, pre, post, env);
+ }
+}
+
+/**
+ * Walker, allocates an array for all blocks and puts it's nodes non-floating nodes into this array.
+ */
+static void collect_node(ir_node * node, void *env) {
+ (void) env;
+ if (is_Block(node)
+ || node_floats(node)
+ || get_irn_op(node) == op_Bad
+ || get_irn_op(node) == op_Unknown
+ || get_irn_op(node) == op_NoMem) {
+ ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
+ if (!arr) arr = NEW_ARR_F(ir_node *, 0);
+ ARR_APP1(ir_node *, arr, node);
+ ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
+ } else {
+ ir_node * block = get_nodes_block(node);
+
+ if (is_Bad(block)) {
+ /* this node is in a Bad block, so we must place it into the graph's list */
+ ir_node ** arr = (ir_node **) ird_get_irg_link(get_irn_irg(node));
+ if (!arr) arr = NEW_ARR_F(ir_node *, 0);
+ ARR_APP1(ir_node *, arr, node);
+ ird_set_irg_link(get_irn_irg(node), arr); /* arr is an l-value, APP_ARR might change it! */
+ } else {
+ ird_set_irn_link(node, ird_get_irn_link(block));
+ ird_set_irn_link(block, node);
+ }
+ }
+}
+
+/** Construct lists to walk ir block-wise.
+ *
+ * Collects all blocks, nodes not op_pin_state_pinned,
+ * Bad, NoMem and Unknown into a flexible array in link field of
+ * irg they belong to. Sets the irg link field to NULL in all
+ * graphs not visited.
+ * Free the list with DEL_ARR_F().
+ */
+static ir_node **construct_block_lists(ir_graph *irg) {
+ int i;
+ int rem_view = get_interprocedural_view();
+ int walk_flag = using_visited(irg);
+ ir_graph *rem = current_ir_graph;
+
+ current_ir_graph = irg;
+
+ if(walk_flag)
+ clear_using_visited(current_ir_graph);
+
+ for (i = get_irp_n_irgs() - 1; i >= 0; --i)
+ ird_set_irg_link(get_irp_irg(i), NULL);
+
+ ird_walk_graph(current_ir_graph, clear_link, collect_node, current_ir_graph);
+
+ /* Collect also EndReg and EndExcept. We do not want to change the walker. */
+ set_interprocedural_view(0);
+
+ set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
+ irg_walk(get_irg_end_reg(current_ir_graph), clear_link, collect_node, current_ir_graph);
+ set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
+ irg_walk(get_irg_end_except(current_ir_graph), clear_link, collect_node, current_ir_graph);
+
+ set_interprocedural_view(rem_view);
+
+ if(walk_flag)
+ set_using_visited(current_ir_graph);
+
+ current_ir_graph = rem;
+ return ird_get_irg_link(irg);
+}
+
+typedef struct _list_tuple {
+ ir_node **blk_list;
+ ir_extblk **extbb_list;
+} list_tuple;
+
+/** Construct lists to walk IR extended block-wise.
+ * Free the lists in the tuple with DEL_ARR_F().
+ * Sets the irg link field to NULL in all
+ * graphs not visited.
+ */
+static list_tuple *construct_extblock_lists(ir_graph *irg) {
+ ir_node **blk_list = construct_block_lists(irg);
+ int i;
+ ir_graph *rem = current_ir_graph;
+ list_tuple *lists = xmalloc(sizeof(*lists));
+
+ current_ir_graph = irg;
+
+ lists->blk_list = NEW_ARR_F(ir_node *, 0);
+ lists->extbb_list = NEW_ARR_F(ir_extblk *, 0);
+
+ inc_irg_block_visited(irg);
+ for (i = ARR_LEN(blk_list) - 1; i >= 0; --i) {
+ ir_extblk *ext;
+
+ if (is_Block(blk_list[i])) {
+ ext = get_Block_extbb(blk_list[i]);
+
+ if (extbb_not_visited(ext)) {
+ ARR_APP1(ir_extblk *, lists->extbb_list, ext);
+ mark_extbb_visited(ext);
+ }
+ } else
+ ARR_APP1(ir_node *, lists->blk_list, blk_list[i]);
+ }
+ DEL_ARR_F(blk_list);
+
+ current_ir_graph = rem;
+ ird_set_irg_link(irg, lists);
+ return lists;
+}
+
+/*-----------------------------------------------------------------*/