X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Ftr%2Ftypewalk.c;h=4dcae5ac653d2f6dabe0e1187dbdbc44618ce32c;hb=5d2f7c6eca2173a427ccf35a4b8ac793706de2e9;hp=ed11560e4d0e6f3af367e34a328b5c15deb406e7;hpb=f548cf8f53f671a577097a3c92f57b3baf16d98b;p=libfirm diff --git a/ir/tr/typewalk.c b/ir/tr/typewalk.c index ed11560e4..4dcae5ac6 100644 --- a/ir/tr/typewalk.c +++ b/ir/tr/typewalk.c @@ -1,41 +1,55 @@ -/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe -** All rights reserved. -** -** Author: Goetz Lindenmaier -** -** traverse the type information. The walker walks the whole ir graph -** to find the distinct type trees in the type graph forest. -** - execute the pre function before recursion -** - execute the post function after recursion -*/ +/* + * Project: libFIRM + * File name: ir/tr/typewalk.c + * Purpose: Traverse the type information. + * Author: Goetz Lindenmaier + * Modified by: + * Created: + * CVS-ID: $Id$ + * Copyright: (c) 1999-2003 Universität Karlsruhe + * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. + */ + +/* + * traverse the type information. The walker walks the whole ir graph + * to find the distinct type trees in the type graph forest. + * - execute the pre function before recursion + * - execute the post function after recursion + */ + #ifdef HAVE_CONFIG_H -# include +# include "config.h" +#endif + +#ifdef HAVE_STDLIB_H +# include #endif -#include #include -#include "irgwalk.h" -#include "irgraph.h" -#include "irnode.h" -#include "irprog.h" -#include "type_or_entity.h" -/* Make types visible to allow most efficient access */ -# include "entity_t.h" +#include "typewalk.h" +#include "entity_t.h" #include "type_t.h" +#include "type_or_entity.h" +#include "typegmod.h" + +#include "irprog_t.h" +#include "irgraph_t.h" +#include "irnode_t.h" +#include "irgwalk.h" typedef struct type_walk_env { - void *pre; - void *post; + type_walk_func *pre; + type_walk_func *post; void *env; } type_walk_env; -void type_walk_2(type_or_ent *tore, - void (pre)(type_or_ent*, void*), - void (post)(type_or_ent*, void*), - void *env) +static void type_walk_2(type_or_ent *tore, + void (*pre) (type_or_ent*, void*), + void (*post)(type_or_ent*, void*), + void *env) { int i; @@ -77,17 +91,17 @@ void type_walk_2(type_or_ent *tore, switch (get_type_tpop_code(tp)) { case tpo_class: { - for (i=0; ipre; - void *post = ((type_walk_env *)env)->post; - void *envi = ((type_walk_env *)env)->env; +/** Check wether node contains types or entities as an attribute. + If so start a walk over that information. */ +static void start_type_walk(ir_node *node, void *env) { + type_walk_func *pre; + type_walk_func *post; + void *envi; + + pre = ((type_walk_env *)env)->pre; + post = ((type_walk_env *)env)->post; + envi = ((type_walk_env *)env)->env; assert(node); switch (get_irn_opcode(node)) { /* node label */ case iro_SymConst: - if ( (get_SymConst_kind(node) == type_tag) - || (get_SymConst_kind(node) == size)) + if ( (get_SymConst_kind(node) ==symconst_type_tag) + || (get_SymConst_kind(node) ==symconst_size)) type_walk_2((type_or_ent *)get_SymConst_type(node), pre, post, envi); break; case iro_Sel: @@ -160,51 +184,66 @@ void start_type_walk(ir_node *node, void *env) { type_walk_2((type_or_ent *)get_Alloc_type(node), pre, post, envi); break; case iro_Free: - printf("here in typewalk\n"); type_walk_2((type_or_ent *)get_Free_type(node), pre, post, envi); break; + case iro_Cast: + type_walk_2((type_or_ent *)get_Cast_type(node), pre, post, envi); + break; default: break; } } -void type_walk(void (pre)(type_or_ent*, void*), - void (post)(type_or_ent*, void*), - void *env) { - int i; +void type_walk(type_walk_func *pre, type_walk_func *post, void *env) { + int i, n_types = get_irp_n_types(); + ++type_visited; - type_walk_2((type_or_ent *)get_glob_type(), pre, post, env); - for (i = 0; i < get_irp_n_types(); i++) { + for (i = 0; i < n_types; i++) { type_walk_2((type_or_ent *)get_irp_type(i), pre, post, env); } + type_walk_2((type_or_ent *)get_glob_type(), pre, post, env); } void type_walk_irg (ir_graph *irg, - void (pre)(type_or_ent*, void*), - void (post)(type_or_ent*, void*), + void (*pre)(type_or_ent*, void*), + void (*post)(type_or_ent*, void*), void *env) { + ir_graph *rem = current_ir_graph; /* this is needed to pass the parameters to the walker that actually walks the type information */ - type_walk_env* type_env; - type_env = (type_walk_env *) malloc (sizeof(type_walk_env)); - type_env->pre = pre; - type_env->post = post; - type_env->env = env; + type_walk_env type_env; + + type_env.pre = pre; + type_env.post = post; + type_env.env = env; + current_ir_graph = irg; + + /* We walk over the irg to find all irnodes that contain an attribute + with type information. If we find one we call a type walker to + touch the reachable type information. + The same type can be referenced by several irnodes. To avoid + repeated visits of the same type node we must decrease the + type visited flag for each walk. This is done in start_type_walk(). + Here we initially increase the flag. We only call type_walk_2 that does + not increase the flag. + */ ++type_visited; - irg_walk(get_irg_end(irg), start_type_walk, NULL, type_env); + irg_walk(get_irg_end(irg), start_type_walk, NULL, &type_env); + + type_walk_2((type_or_ent *)get_irg_entity(irg), pre, post, env); - type_walk_2((type_or_ent *)get_irg_ent(irg), pre, post, env); + type_walk_2((type_or_ent *)get_irg_frame_type(irg), pre, post, env); - free(type_env); + current_ir_graph = rem; return; } -void type_walk_s2s_2(type_or_ent *tore, - void (pre)(type_or_ent*, void*), - void (post)(type_or_ent*, void*), - void *env) +static void type_walk_s2s_2(type_or_ent *tore, + void (*pre)(type_or_ent*, void*), + void (*post)(type_or_ent*, void*), + void *env) { int i; @@ -233,16 +272,109 @@ void type_walk_s2s_2(type_or_ent *tore, switch (get_type_tpop_code(tp)) { case tpo_class: { - for (i=0; ivisit >= type_visited) return; + break; + case k_type: + if(type_id == get_type_tpop((type*)tore)) { + type_walk_super_2((type_or_ent *)skip_tid((type *)tore), pre, post, env); + return; + } + if (((type *)tore)->visit >= type_visited) return; + break; + default: + break; + } + + /* iterate */ + switch (get_kind(tore)) { + case k_type: + { + type *tp = (type *)tore; + mark_type_visited(tp); + switch (get_type_tpop_code(tp)) { + case tpo_class: + { /* execute pre method */ if(pre) pre(tore, env); tp = skip_tid((type*)tore); - for (i=0; ivisit >= type_visited) return; + + assert(is_class_type(tp)); + /* Assure all supertypes are visited before */ + for (i=0; i < get_class_n_supertypes(tp); i++) { + if (get_type_visited(get_class_supertype(tp, i)) < type_visited) + return; + } + + mark_type_visited(tp); + + /* execute pre method */ + if(pre) + pre(tp, env); + + tp = skip_tid((type*)tp); + for (i=0; ivisit < type_visited)) { + assert(!is_frame_type(tp)); + assert(tp != get_glob_type()); + class_walk_s2s_2(tp, pre, post, env); + } + } +} + + +/* Walks over all entities in the type */ +void walk_types_entities( + type *tp, + void (*doit)(entity*, void*), + void *env) +{ + int i; + switch(get_type_tpop_code(tp)) { + case tpo_class: { + for (i=0; i