+++ /dev/null
-/*
- * 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 Walker that touches all Firm data structures
- * @author Sebastian Felis
- * @date 7.2003
- * @version $Id$
- */
-#include "config.h"
-
-#include <string.h>
-
-#include "firmwalk.h"
-
-#include "entity_t.h"
-#include "irnode_t.h"
-#include "irprog_t.h"
-#include "irgwalk.h"
-#include "irtools.h"
-
-#include "array.h"
-#include "obst.h"
-#include "pmap.h"
-
-/** obstack for firm walker */
-static struct obstack fw_obst;
-
-/** This map stores all types of firm */
-static pmap *type_map = NULL;
-/** This map stores all entities of firm */
-static pmap *entity_map = NULL;
-
-/** Internal data structure of firm walker to collect
- * some information of firm ir. The collected data will be stored
- * into the link field of ir node. All graphs have a list of its
- * blocks and all blocks have a list of their nodes. */
-typedef struct {
- ir_node **list; /**< List of blocks or nodes */
- void *link; /**< Public link field. The public link field of firm nodes
- is wrapped by set_firm_walk_link and
- get_firm_walk_link. */
-} fw_data;
-
-/*@{ */
-/** Access macros to fw_data structure */
-#define FW_GET_DATA_LIST(s) ((s)->list)
-#define FW_SET_DATA_LIST(s, t) ((s)->list = (t))
-#define FW_GET_DATA_LINK(s) ((s)->link)
-#define FW_SET_DATA_LINK(s, t) ((s)->link = (t))
-/*@} */
-
-/** Returns own data struct of the firm walker.
- *
- * If no structure defined (firm link is NULL) allocate a new
- * struct to the fgd obstack. Only ir graph and block nodes
- * will allocate this structure.
- * - ir graph collect its block
- * - block collect its nodes
- */
-static
-fw_data *fw_get_data(void *thing)
-{
- fw_data *data = NULL;
-
- assert(thing);
- switch (get_kind(thing)) {
- case k_ir_graph:
- data = get_irg_link(thing);
- /* init block list of graph */
- if (NULL == data)
- {
- /* allocate new firm walk structure */
- data = obstack_alloc(&fw_obst, sizeof(fw_data));
- memset(data, 0, sizeof(fw_data));
- set_irg_link(thing, data);
- /* allocate block list */
- FW_GET_DATA_LIST(data) = NEW_ARR_F(ir_node *, 0);
- }
- break;
- case k_ir_node:
- /* init node list of block */
- if (is_Block(thing))
- {
- data = get_irn_link(thing);
- if (NULL == data)
- {
- /* allocate new firm walk structure */
- data = obstack_alloc(&fw_obst, sizeof(fw_data));
- memset(data, 0, sizeof(fw_data));
- set_irn_link(thing, data);
- /* allocate node list */
- FW_GET_DATA_LIST(data) = NEW_ARR_F(ir_node *, 0);
- }
- }
- break;
- default: {} /* other kinds of firm nodes */
- }
-
- return data;
-}
-
-/** Free all collected data in ir graphs and nodes.
- * An ir graph or an ir block node has a list as a
- * dynamic array, which will be deleted here. */
-static
-void fw_free_data(void *thing)
-{
- fw_data *data = NULL;
-
- assert(thing);
-
- switch (get_kind(thing)) {
- case k_ir_graph:
- data = get_irg_link(thing);
- /* delete block list of graph */
- if (NULL != data)
- {
- DEL_ARR_F(FW_GET_DATA_LIST(data));
- set_irg_link(thing, NULL);
- }
- break;
- case k_ir_node:
- /* delete node list of block */
- if (is_Block(thing))
- {
- data = get_irn_link(thing);
- if (NULL != data)
- {
- DEL_ARR_F(FW_GET_DATA_LIST(data));
- set_irn_link(thing, NULL);
- }
- }
- break;
- default: {} /* other kinds of firm nodes */
- }
-}
-
-/* documentation in header file */
-void set_firm_walk_link(void *thing, void *link)
-{
- fw_data *data;
-
- assert(thing);
- switch (get_kind(thing)) {
- case k_entity:
- set_entity_link(thing, link);
- break;
- case k_type:
- set_type_link(thing, link);
- break;
- case k_ir_graph:
- data = fw_get_data(thing);
- FW_SET_DATA_LINK(data, link);
- break;
- case k_ir_node:
- if (is_Block(thing))
- {
- data = fw_get_data(thing);
- FW_SET_DATA_LINK(data, link);
- }
- else
- set_irn_link(thing, link);
- break;
- case k_ir_mode:
- set_mode_link(thing, link);
- break;
- default: {} /* other kinds of firm nodes */
- }
-}
-
-/* documentation in header file */
-void *get_firm_walk_link(void *thing)
-{
- fw_data *data;
- assert(thing);
- switch (get_kind(thing)) {
- case k_entity:
- return get_entity_link(thing);
- case k_type:
- return get_type_link(thing);
- case k_ir_graph:
- data = fw_get_data(thing);
- return FW_GET_DATA_LINK(data);
- case k_ir_node:
- if (is_Block(thing))
- {
- data = fw_get_data(thing);
- return FW_GET_DATA_LINK(data);
- }
- else
- return get_irn_link(thing);
- case k_ir_mode:
- return get_mode_link(thing);
- default:
- return NULL;
- }
-}
-
-/** Fill maps of type and entity.
- * This function will be called by the firm walk initializer
- * to collect all types and entities of program's firm ir.
- * All types will be collected in the hash table type_map
- * and all entity are stored in entity_map. The mode of an
- * type will be collected as well.
- *
- * @param tore Type or entity
- * @param env Environment pointer (currently unused)
- */
-static
-void fw_collect_tore(type_or_ent tore, void *env)
-{
- ir_type *tp;
- ir_entity *ent;
-
- switch (get_kind(tore.ent)) {
- case k_entity:
- ent = tore.ent;
- /* append entity to list */
- set_entity_link(ent, NULL);
- if (!pmap_contains(entity_map, ent))
- pmap_insert(entity_map, ent, env);
- break;
- case k_type:
- tp = tore.typ;
-
- /* append type to list */
- set_type_link(tp, NULL);
- if (!pmap_contains(type_map, tp))
- pmap_insert(type_map, tp, env);
- break;
- default: break;
- }
-}
-
-/** Collect all data from nodes. Block appends itself to
- * the corresponding ir graph and other nodes appends itself
- * to block list. Collects also the modes of each node to get
- * non-type modes.
- *
- * @param irn IR node pointer.
- * @param env Environment pointer (currently unused)
- */
-static
-void fw_collect_irn(ir_node *irn, void *env)
-{
- fw_data *data;
- (void) env;
-
- /* block nodes. */
- if (is_Block(irn)) {
- /* add this block to ir graph's block list */
- data = fw_get_data(get_current_ir_graph());
- ARR_APP1(ir_node *, FW_GET_DATA_LIST(data), irn);
- }
- /* non block nodes */
- else {
- /* add this node to block's node list */
- ir_node *block = get_nodes_block(irn);
- data = fw_get_data(block);
- ARR_APP1(ir_node *, FW_GET_DATA_LIST(data), irn);
- }
-}
-
-/** Irg walker function to free all collected data from nodes */
-static
-void fw_free_colleted_data(ir_node *irn, void *env)
-{
- (void) env;
- /* Free node list from blocks */
- if (is_Block(irn))
- {
- fw_free_data(irn);
- }
-}
-
-/** Initialize all walking data.
- *
- * Collect all specific data like types, entities, ir graphs, blocks, nodes
- * from current firm structures.
- */
-void firm_walk_init(firm_walk_flags flags)
-{
- int i;
-
- /* init obstack */
- obstack_init(&fw_obst);
-
- /* Init map of type and entity. If map or list
- already exists, free it. */
- if (type_map)
- pmap_destroy(type_map);
- type_map = pmap_create();
-
- if (entity_map)
- pmap_destroy(entity_map);
- entity_map = pmap_create();
-
- /* Collect all types (also unused types) if flag is set */
- if (FW_WITH_ALL_TYPES & flags)
- type_walk(fw_collect_tore, NULL, NULL);
-
- /* for each ir graph */
- for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
- ir_graph *irg = get_irp_irg(i);
- set_irg_link(irg, NULL);
-
- type_walk_irg(irg, fw_collect_tore, NULL, NULL);
-
- irg_walk_graph(irg, firm_clear_link, fw_collect_irn, NULL);
- }
-}
-
-/** This function should call after using the firm walker to free
- * all collected data and frees the used obstack */
-void firm_walk_finalize(void)
-{
- int i;
-
- /* free all used maps and lists */
- pmap_destroy(type_map);
- type_map = NULL;
- pmap_destroy(entity_map);
- entity_map = NULL;
-
- /* free all collected data from ir graphs and nodes */
- for (i = 0; i < get_irp_n_irgs(); i++)
- {
- ir_graph *irg = get_irp_irg(i);
- fw_free_data(irg);
- irg_walk_graph(get_irp_irg(i), NULL, fw_free_colleted_data, NULL);
- }
-
- /* free obstack */
- obstack_free(&fw_obst, NULL);
-}
-
-/** Dumps the firm ir.
- *
- * After initializing the firm walker by calling firm_walk_init()
- * the firm structure could be accessed by defining the firm walk interface
- * wif. This function could be called several times to customize the
- * walk order or definitions.
- *
- * @param wif Walk interface which contains the callback function
- *
- * @see firm_walk_interface */
-void firm_walk(firm_walk_interface *wif)
-{
- int mode_i, irg_i, block_i, block_list_len, irn_i, irn_list_len;
- pmap_entry *entry;
- fw_data *data;
- ir_node *block, **block_list, **irn_list;
- ir_graph *saved_irg = current_ir_graph;
-
- assert(wif && "firm_walk() in firmwalk.c: No walking interface defined!");
-
- /* walk over all modes */
- if (wif->do_mode_init) wif->do_mode_init(wif->env);
- if (wif->do_mode)
- {
- for (mode_i = get_irp_n_modes() - 1; mode_i >= 0; --mode_i)
- wif->do_mode(get_irp_mode(mode_i), wif->env);
- }
- if (wif->do_mode_finalize) wif->do_mode_finalize(wif->env);
-
- /* walk over all types */
- if (wif->do_type_init) wif->do_type_init(wif->env);
- if (wif->do_type)
- {
- for (entry = pmap_first(type_map); entry; entry = pmap_next(type_map))
- wif->do_type((ir_type *)entry->key, wif->env);
- }
- if (wif->do_type_finalize) wif->do_type_finalize(wif->env);
-
- /* walk over all entities */
- if (wif->do_entity_init) wif->do_entity_init(wif->env);
- if (wif->do_entity)
- {
- for (entry = pmap_first(entity_map); entry; entry = pmap_next(entity_map))
- wif->do_entity((ir_entity *)entry->key, wif->env);
- }
- if (wif->do_entity_finalize) wif->do_entity_finalize(wif->env);
-
-
- /* Dump graphs ================================================= */
- if (wif->do_graph_init) wif->do_graph_init(wif->env);
-
- for (irg_i = 0; irg_i < get_irp_n_irgs(); irg_i++)
- {
- current_ir_graph = get_irp_irg(irg_i);
-
- /* walk over all ir graph */
- if (wif->do_graph) wif->do_graph(current_ir_graph, wif->env);
-
- /* walk over all irg's block nested ========================== */
- data = fw_get_data(current_ir_graph);
- block_list = FW_GET_DATA_LIST(data);
- block_list_len = ARR_LEN(block_list);
- for (block_i = 0; block_i < block_list_len; block_i++)
- {
- if (wif->do_block_init) wif->do_block_init(current_ir_graph, wif->env);
-
- block = (ir_node *)block_list[block_i];
- if (wif->do_block) wif->do_block(block, wif->env);
-
- /* walk over all block's ir nodes nested =================== */
- data = fw_get_data(block);
- irn_list = FW_GET_DATA_LIST(data);
- irn_list_len = ARR_LEN(irn_list);
-
- /* call block as prefix ir node */
- if ((wif->do_node) &&
- (wif->flags & (FW_DUMP_BLOCK_AS_IRN | FW_DUMP_IRN_IN_PREFIX)))
- wif->do_node(block, wif->env);
-
- /* do ir nodes in prefix or postfix order? */
- if (wif->flags & FW_DUMP_IRN_IN_PREFIX)
- irn_i = irn_list_len-1;
- else
- irn_i = 0;
-
- while (irn_i >= 0 && irn_i < irn_list_len)
- {
- if (wif->do_node) wif->do_node((ir_node *)irn_list[irn_i], wif->env);
-
- /* do ir nodes in prefix or postfix order? */
- if (wif->flags & FW_DUMP_IRN_IN_PREFIX)
- irn_i--;
- else
- irn_i++;
- }
- /* call block as postfix ir node */
- if ((wif->do_node) &&
- ((wif->flags & (FW_DUMP_BLOCK_AS_IRN | FW_DUMP_IRN_IN_PREFIX))
- == FW_DUMP_BLOCK_AS_IRN))
- wif->do_node(block, wif->env);
-
- /* wall over all block's ir nodes nested end =============== */
-
- if(wif->do_block_post)
- wif->do_block_post(block, wif->env);
-
- } /* for each block */
-
- if (wif->do_block_finalize)
- wif->do_block_finalize(current_ir_graph, wif->env);
-
- /* walk over all irg's block nested end ====================== */
- if(wif->do_graph_post)
- wif->do_graph_post(current_ir_graph, wif->env);
-
- } /* for each ir graph irg */
-
- if(wif->do_graph_finalize)
- wif->do_graph_finalize(wif->env);
-
- /** ### ToDo: Dump const_code_irg ?? No! Dump const code with entities, types etc. */
-
- /* restore the state of current_ir_graph */
- current_ir_graph = saved_irg;
-}
+++ /dev/null
-/*
- * 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
- * @biref Walker that touches all Firm data structures
- * @author Sebastian Felis
- * @date 7.2003
- * @version $Id$
- * @summary
- * Firm walker over intermediate representation.
- *
- * To initialize the walker, call firm_walk_init(). This function
- * collects all specific data from the firm represenation. After
- * building the walker information firm_walk() could be called
- * serveral times with different flags (options) from specific walker
- * or dumper. At least firm_walk_finalizer() should be called to free
- * the stored data.
- *
- * This walker could be used for a dumper e.g. a vcg or xml dumper.
- *
- * @note If a specific walker or dumper which uses the link field
- * of any firm node, the the wrapper functions set_firm_walk_link()
- * and get_firm_walk_link() should be used, because the firm walker
- * make use of the link field to store its own data.
- * @note Deprecated, better use the stuff in irgwalk.h, typewalk.h
- */
-#ifndef FIRM_COMMON_FIRM_WALK_H
-#define FIRM_COMMON_FIRM_WALK_H
-
-#include "firm_types.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-/** Returns the link of a firm node.
- * Possible firm structures are: entity, type, ir_graph, ir_node and
- * ir_mode. Otherwise this function has no effect
- *
- * Derived walker or dumper have to call this function to store data
- * to a firm structure. The real link field of firm structure is used
- * by this firm walker to collect walking data.
- *
- * @param thing Pointer to a firm structure
- * @return Link pointer
- *
- * @note After calling firm_walk_finalize() the stored link
- * information may be invalid. */
-void *get_firm_walk_link(void *thing);
-
-/** Set the link field of a firm structure.
- * Possible firm structures are: entity, type, ir_graph, ir_node and
- * ir_mode. Otherwise this function has no effect
- *
- * Derived walker or dumper have to call this function to store data
- * to a firm structure. The real link field of firm structure is used
- * by this firm walker to collect walking data.
- *
- * @param thing firm structure
- * @param link Pointer to link field
- *
- * @note After calling firm_walk_finalize() the stored link
- * information may be invalid. */
-void set_firm_walk_link(void *thing, void *link);
-
-/** Initialisation function for firm walker callbacks */
-typedef void firm_walk_init_func(void *env);
-/** Finalisation function for firm walker callbacks */
-typedef void firm_walk_finalize_func(void *env);
-
-/** Mode callback function definition */
-typedef void firm_walk_mode_func(ir_mode *mode, void *env);
-/** Type callback function definition */
-typedef void firm_walk_type_func(ir_type *tp, void *env);
-/** Entity callback function definition */
-typedef void firm_walk_entity_func(ir_entity *ent, void *env);
-/** Graph callback function definition */
-typedef void firm_walk_graph_func(ir_graph *irg, void *env);
-/* @{ */
-/** Block callback function definition */
-typedef void firm_walk_block_init_func(ir_graph *irg, void *env);
-typedef void firm_walk_block_func(ir_node *block, void *env);
-typedef void firm_walk_block_finalize_func(ir_graph *irg, void *env);
-/* @} */
-/** Node callback function definition */
-typedef void firm_walk_node_func (ir_node *irn, void *env);
-
-/** @enum firm_walk_flags
- *
- * Flags for the firm walker to modify some dumping behavior
- */
-typedef enum
-{
- FW_WITH_ALL_TYPES = 1<<0, /**< Collect and dump all types, especially
- unused types.
- @note This flag could be set in
- firm_dumper_init() and is unused in
- firm_dump() */
- FW_WITH_DOMINATOR = 1<<1, /**< nyi */
- FW_WITH_OUTEDGES = 1<<2, /**< nyi */
- FW_WITH_LOOPS = 1<<3, /**< nyi */
- FW_DUMP_BLOCK_AS_IRN = 1<<4, /**< Dump all block nodes as irn nodes
- additionally */
- FW_DUMP_IRN_IN_PREFIX = 1<<5 /**< Dumps all ir nodes in prefix order
- according to the internal firm graph
- structure */
-} firm_walk_flags;
-
-/** Interface of the firm walker */
-typedef struct
-{
- /* @{ */
- /** Interface function to dump all used and internal modes.
- Internal modes are: BB, X, M and T */
- firm_walk_init_func *do_mode_init;
- firm_walk_mode_func *do_mode;
- firm_walk_finalize_func *do_mode_finalize;
- /* @} */
-
- /* @{ */
- /** Interface to dump all collected types.
- *
- * @note To dump all (not only used types by default) a special walk
- * flag must be set for the walker initializer */
- firm_walk_init_func *do_type_init;
- firm_walk_type_func *do_type;
- firm_walk_finalize_func *do_type_finalize;
- /* @} */
-
- /* @{ */
- /** Dumping interface for entities */
- firm_walk_init_func *do_entity_init;
- firm_walk_entity_func *do_entity;
- firm_walk_finalize_func *do_entity_finalize;
- /* @} */
-
- /** Dumps all graphs and subnodes.
- *
- * The firm walker dump a graph with its blocks and nodes nested.
- * Fist do_graph_init will be called (if defined). For each graph
- * do_graph will be call in a loop.
- * After all blocks in a graph are dumped, do_graph_post() is called.
- * After dumped all graphs, do_graph_finalize will be called.
- *
- * Within do_graph each block will be dumped. First do_block_init,
- * for each block do_block and after all dumped blocks
- * do_block_finalize.
- *
- * The ir nodes are dumped nested in their blocks as well. Within
- * do_block, for each ir node do_node is called in postfix order
- * according to the internal firm representation. By changing the
- * walking flag, a prefix order is also possible. */
- firm_walk_init_func *do_graph_init;
- firm_walk_graph_func *do_graph;
- firm_walk_graph_func *do_graph_post;
- firm_walk_finalize_func *do_graph_finalize;
-
- /* @{ */
- /** Dumping interface for blocks. If blocks should be handled like
- * like a normal ir node, a special walker flag could be set.
- * @see do_graph */
- firm_walk_block_init_func *do_block_init;
- firm_walk_block_func *do_block;
- firm_walk_block_func *do_block_post;
- firm_walk_block_finalize_func *do_block_finalize;
- /* @} */
-
- /** Dumping interface for ir nodes
- * @see do_graph */
- firm_walk_node_func *do_node;
- /* dominator */
- /* procedures */
- /* loop */
- firm_walk_flags flags;
- /* pointer to environment of interface */
- void *env;
-} firm_walk_interface;
-
-
-/** Initialize the dumper und collect all data from the firm intermediate
- * representation
- *
- * @param flags flags */
-void firm_walk_init(firm_walk_flags flags);
-
-/** Walker of the firm intermediate representation.
- *
- * The callback functions of the interface will be called nested, e.g. for
- * each block: init function of block, do_block, nested function of nodes,
- * finalize function of block.
- *
- * - modes
- * - types
- * - entities
- * - ir graphs
- * - procedures
- * - blocks
- * - nodes. Options: dominator, outedges
- *
- * @param wif Stucture of walker interface. In this struct the used callback
- * functions are defined.
- */
-void firm_walk(firm_walk_interface *wif);
-
-/** Finalize the walker and frees all stored data for dumping */
-void firm_walk_finalize(void);
-
-#ifdef __cplusplus
-}
-#endif
-
-
-#endif