+/*
+ * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
+ *
+ * This file is part of libFirm.
+ *
+ * This file may be distributed and/or modified under the terms of the
+ * GNU General Public License version 2 as published by the Free Software
+ * Foundation and appearing in the file LICENSE.GPL included in the
+ * packaging of this file.
+ *
+ * Licensees holding valid libFirm Professional Edition licenses may use
+ * this file in accordance with the libFirm Commercial License.
+ * Agreement provided with the Software.
+ *
+ * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+ * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE.
+ */
+
+/**
+ * @file
+ * @brief Functions for traversing ir graphs
+ * @author Boris Boesler, Goetz Lindenmaier, Michael Beck
+ * @version $Id$
+ * @summary
+ * traverse an ir graph
+ * - execute the pre function before recursion
+ * - execute the post function after recursion
+ */
+#include "config.h"
+
+#include <stdlib.h>
+
+#include "irnode_t.h"
+#include "irgraph_t.h"
+#include "irprog.h"
+#include "irgwalk.h"
+#include "irhooks.h"
+#include "ircgcons.h"
+#include "entity_t.h"
+
+#include "error.h"
+#include "pset_new.h"
+#include "array.h"
+
+#ifdef INTERPROCEDURAL_VIEW
+/**
+ * Walk over an interprocedural graph (callgraph).
+ * Visits only graphs in irg_set.
+ */
+static void irg_walk_cg(ir_node * node, ir_visited_t visited,
+ pset_new_t *irg_set, irg_walk_func *pre,
+ irg_walk_func *post, void * env)
+{
+ int i;
+ ir_graph * rem = current_ir_graph;
+ ir_node * pred;
+
+ assert(node && node->kind == k_ir_node);
+ if (get_irn_visited(node) >= visited) return;
+
+ set_irn_visited(node, visited);
+
+ if (pre) pre(node, env);
+
+ pred = skip_Proj(node);
+ if (is_CallBegin(pred) ||
+ get_irn_op(pred) == op_EndReg ||
+ get_irn_op(pred) == op_EndExcept) {
+ current_ir_graph = get_irn_irg(pred);
+ }
+
+ if (is_no_Block(node)) { /* not block */
+ irg_walk_cg(get_nodes_block(node), visited, irg_set, pre, post, env);
+ }
+
+ if (is_Block(node)) { /* block */
+ for (i = get_irn_arity(node) - 1; i >= 0; --i) {
+ ir_node * exec = get_irn_n(node, i);
+ ir_node * pred = skip_Proj(exec);
+ if ((
+ !is_CallBegin(pred) &&
+ get_irn_op(pred) != op_EndReg &&
+ get_irn_op(pred) != op_EndExcept
+ ) || pset_new_contains(irg_set, get_irn_irg(pred))) {
+ irg_walk_cg(exec, visited, irg_set, pre, post, env);
+ }
+ }
+ } else if (is_Filter(node)) { /* filter */
+ for (i = get_irn_arity(node) - 1; i >= 0; --i) {
+ ir_node * pred = get_irn_n(node, i);
+ if (is_Unknown(pred) || is_Bad(pred)) {
+ irg_walk_cg(pred, visited, irg_set, pre, post, env);
+ } else {
+ ir_node * exec;
+ exec = skip_Proj(get_Block_cfgpred(get_nodes_block(node), i));
+
+ if (is_Bad(exec)) {
+ continue;
+ }
+
+ assert(is_CallBegin(exec) ||
+ get_irn_op(exec) == op_EndReg ||
+ get_irn_op(exec) == op_EndExcept);
+ if (pset_new_contains(irg_set, get_irn_irg(exec))) {
+ current_ir_graph = get_irn_irg(exec);
+ irg_walk_cg(pred, visited, irg_set, pre, post, env);
+ current_ir_graph = rem;
+ }
+ }
+ }
+ } else { /* everything else */
+ for (i = get_irn_arity(node) - 1; i >= 0; --i) {
+ irg_walk_cg(get_irn_n(node, i), visited, irg_set, pre, post, env);
+ }
+ }
+
+ if (post) post(node, env);
+
+ current_ir_graph = rem;
+}