X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fana2%2Ftypalise.c;h=bced3f0ed0bc5be8dbaebc9d0c1d22252c0df8e5;hb=8ca297d3fa1c84b58d71a9ec102061239159f9a7;hp=42e3e52d687de53c9fdb9cde6bdabf863a14f1b3;hpb=004ad42d8f0f6e3b14d68fb0b51e016f2d0afbf6;p=libfirm diff --git a/ir/ana2/typalise.c b/ir/ana2/typalise.c index 42e3e52d6..bced3f0ed 100644 --- a/ir/ana2/typalise.c +++ b/ir/ana2/typalise.c @@ -1,18 +1,31 @@ /* -*- c -*- */ /* - * Project: libFIRM - * File name: ir/ana2/pto.c - * Purpose: Pto - * Author: Florian - * Modified by: - * Created: Mon 18 Oct 2004 - * CVS-ID: $Id$ - * Copyright: (c) 1999-2004 Universität Karlsruhe - * Licence: This file is protected by GPL - GNU GENERAL PUBLIC LICENSE. + * Copyright (C) 1995-2007 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 Pto + * @author Florian + * @date Mon 18 Oct 2004 + * @version $Id$ + */ # ifdef HAVE_CONFIG_H # include "config.h" # endif @@ -34,6 +47,8 @@ # include "irgwalk.h" # include "xmalloc.h" # include "gnu_ext.h" +# include "irdump.h" +# include "typewalk.h" /* @@ -47,11 +62,47 @@ static long ta_id = 0; */ static typalise_t *typalise_proj (ir_node*); +/* DEBUGGING only */ +static void cough_and_die (ir_node *node) +{ + ir_graph *graph = get_irn_irg (node); + + fprintf (stdout, "%s: %s[%li]\n", + __FUNCTION__, + get_op_name (get_irn_op (node)), + get_irn_node_nr (node)); + dump_ir_block_graph (graph, "-typealise"); + assert (0); +} + +/* + Exception b/d +*/ +static ir_type *java_lang_Throwable_tp = NULL; + +static ir_type *get_java_lang_Throwable (void) +{ + assert (NULL != java_lang_Throwable_tp); + + return (java_lang_Throwable_tp); +} + +static void find_java_lang_Throwable (ir_type *tp, void *_unused) +{ + const char *name = get_type_name (tp); + + if (0 == strcmp (name, "java/lang/Throwable")) { + assert (NULL == java_lang_Throwable_tp); + + java_lang_Throwable_tp = tp; + } +} + /* Ctors, Dtors for typalise_t-s */ -static typalise_t *ta_exact (type *tp) +static typalise_t *ta_exact (ir_type *tp) { typalise_t *ta = xmalloc (sizeof (typalise_t)); ta->kind = type_exact; @@ -73,7 +124,7 @@ static typalise_t *ta_types (lset_t *set) return (ta); } -static typalise_t *ta_type (type *tp) +static typalise_t *ta_type (ir_type *tp) { typalise_t *ta = xmalloc (sizeof (typalise_t)); ta->kind = type_type; @@ -106,7 +157,7 @@ static void ta_delete (typalise_t *ta) Find out whether otype is a subtype of stype. Return non-zero iff otype is a subtype of stype. */ -static int is_subtype (type *otype, type *stype) +static int is_subtype (ir_type *otype, ir_type *stype) { int n_sub = get_class_n_subtypes (stype); int is_sub = FALSE; @@ -117,7 +168,7 @@ static int is_subtype (type *otype, type *stype) } for (i = 0; (!is_sub) && (i < n_sub); i ++) { - type *sub = get_class_subtype (stype, i); + ir_type *sub = get_class_subtype (stype, i); is_sub |= is_subtype (otype, sub); } @@ -131,7 +182,7 @@ static int is_subtype (type *otype, type *stype) Compute the closure of all subtypes of otype (including otype itself) */ -static void _collect_subtypes (type *otype, lset_t *set) +static void _collect_subtypes (ir_type *otype, lset_t *set) { int i, n_sub; @@ -139,13 +190,13 @@ static void _collect_subtypes (type *otype, lset_t *set) n_sub = get_class_n_subtypes (otype); for (i = 0; i < n_sub; i ++) { - type *sub = get_class_subtype (otype, i); + ir_type *sub = get_class_subtype (otype, i); _collect_subtypes (sub, set); } } -static lset_t *subtype_closure (type *otype) +static lset_t *subtype_closure (ir_type *otype) { lset_t *set = lset_create (); @@ -157,7 +208,7 @@ static lset_t *subtype_closure (type *otype) /** Helper method for get_owner_types */ -static void _collect_owner_types (entity *method, ir_graph *graph, lset_t *tps) +static void _collect_owner_types (ir_entity *method, ir_graph *graph, lset_t *tps) { int i, n_over; @@ -180,7 +231,7 @@ static void _collect_owner_types (entity *method, ir_graph *graph, lset_t *tps) n_over = get_entity_n_overwrittenby (method); for (i = 0; i < n_over; i ++) { - entity *ometh = get_entity_overwrittenby (method, i); + ir_entity *ometh = get_entity_overwrittenby (method, i); _collect_owner_types (ometh, graph, tps); } @@ -193,7 +244,7 @@ static void _collect_owner_types (entity *method, ir_graph *graph, lset_t *tps) static lset_t *get_owner_types (ir_graph *graph) { lset_t *tps = lset_create (); - entity *meth = get_irg_entity (graph); + ir_entity *meth = get_irg_entity (graph); _collect_owner_types (meth, graph, tps); @@ -203,9 +254,9 @@ static lset_t *get_owner_types (ir_graph *graph) /** Return a list containing all types of 'set' which are a subtype of 'type'. */ -static lset_t *filter_for_type (lset_t *set, type *stype) +static lset_t *filter_for_type (lset_t *set, ir_type *stype) { - type *curs = (type*) lset_first (set); + ir_type *curs = (ir_type*) lset_first (set); lset_t *lset = lset_create (); while (NULL != curs) { @@ -230,6 +281,15 @@ static typalise_t *ta_join (typalise_t *one, typalise_t *two) { typalise_t *res = NULL; + /* now, one==NULL or two==NULL cannot happen legitimately (if we hit a NULL pointer constant) + if (NULL == one) { + return (two); + } + + if (NULL == two) { + return (one); + } + */ switch (one->kind) { case (type_invalid): { /* shut up, gcc */ } case (type_exact): { @@ -302,8 +362,8 @@ static typalise_t *ta_join (typalise_t *one, typalise_t *two) res = ta_join (two, one); } break; case (type_type): { - type *one_type = one->res.type; - type *two_type = two->res.type; + ir_type *one_type = one->res.type; + ir_type *two_type = two->res.type; if (is_subtype (one_type, two_type)) { ta_delete (one); @@ -350,7 +410,7 @@ static const char *ta_name (typalise_t *ta) case (type_types): { len += sprintf (buf+len, "one_of "); - type *iter = lset_first (ta->res.types); + ir_type *iter = lset_first (ta->res.types); int size = BUF_SIZE - len - 1; while ((NULL != iter) && (0 < size)) { @@ -376,9 +436,9 @@ static const char *ta_name (typalise_t *ta) method. Presumably, this is because clazz inherits the graph as the implementation for a method. */ -static int uses_graph (type *clazz, entity *meth, ir_graph *graph) +static int uses_graph (ir_type *clazz, ir_entity *meth, ir_graph *graph) { - type *g_clazz = get_entity_owner (meth); + ir_type *g_clazz = get_entity_owner (meth); int i, n_over, use = FALSE; if (g_clazz == clazz) { @@ -396,7 +456,7 @@ static int uses_graph (type *clazz, entity *meth, ir_graph *graph) /* else inherited or description */ n_over = get_entity_n_overwrittenby (meth); /* DOWN-wards */ for (i = 0; (i < n_over) && (!use); i ++) { - entity *over = get_entity_overwrittenby (meth, i); + ir_entity *over = get_entity_overwrittenby (meth, i); use |= uses_graph (clazz, over, graph); } @@ -424,8 +484,8 @@ static int ta_supports (typalise_t *ta, ir_graph *graph) return (res); } case (type_type): { - entity *meth = get_irg_entity (graph); - type *tp = get_entity_owner (meth); + ir_entity *meth = get_irg_entity (graph); + ir_type *tp = get_entity_owner (meth); int res = is_subtype (tp, ta->res.type); if (res) { @@ -437,7 +497,7 @@ static int ta_supports (typalise_t *ta, ir_graph *graph) return (res); } case (type_types): { - type *tp = get_entity_owner (get_irg_entity (graph)); + ir_type *tp = get_entity_owner (get_irg_entity (graph)); return (lset_contains (ta->res.types, tp)); } @@ -451,8 +511,104 @@ static int ta_supports (typalise_t *ta, ir_graph *graph) /* =========== WHAT ELSE ? =========== */ /* - Helper to typalise (ir_node*) + Helpers to typalise (ir_node*) +*/ +/** + Find an approximation to the given load node's value's types */ +static typalise_t *typalise_call (ir_node *call) +{ + ir_entity *ent = NULL; + ir_type *tp = NULL; + typalise_t *res = NULL; + ir_node *call_ptr = get_Call_ptr (call); + + if (iro_Sel == get_irn_opcode (call_ptr)) { + ent = get_Sel_entity (call_ptr); + } else if (iro_SymConst == get_irn_opcode (call_ptr)) { + if (get_SymConst_kind (call_ptr) == symconst_addr_ent) { + ent = get_SymConst_entity (call_ptr); + } else if (get_SymConst_kind (call_ptr) == symconst_addr_name) { + ident *id = get_SymConst_name (call_ptr); + const char *name = get_id_str (id); + if (0 == strcmp (name, "iro_Catch")) { + res = ta_type (java_lang_Throwable_tp); + + return (res); + } + + fprintf (stdout, "%s: cannot handle Call[%li] (symconst_addr_name=\"%s\")\n", + __FUNCTION__, get_irn_node_nr (call), + name); + cough_and_die (call_ptr); + } else if (get_SymConst_kind (call_ptr) == symconst_type_tag) { + fprintf (stdout, "%s: cannot handle Call[%li] (symconst_type_tag)\n", + __FUNCTION__, get_irn_node_nr (call)); + cough_and_die (call_ptr); + } else { + fprintf (stdout, "%s: cannot handle Call[%li] (%i)\n", + __FUNCTION__, get_irn_node_nr (call), + get_SymConst_kind (call_ptr)); + cough_and_die (call_ptr); + } + } + + tp = get_entity_type (ent); + assert (is_Method_type (tp)); + + tp = get_method_res_type (tp, 0); + + while (is_Pointer_type (tp)) { + tp = get_pointer_points_to_type (tp); + } + + res = ta_type (tp); + + return (res); +} + + +/** + Find an approximation to the given load node's value's types +*/ +static typalise_t *typalise_load (ir_node *load) +{ + ir_entity *ent = NULL; + ir_type *tp = NULL; + typalise_t *res = NULL; + ir_node *load_ptr = get_Load_ptr (load); + + if (iro_Sel == get_irn_opcode (load_ptr)) { + ent = get_Sel_entity (load_ptr); + } else if (iro_SymConst == get_irn_opcode (load_ptr)) { + if (get_SymConst_kind (load_ptr) == symconst_addr_ent) { + ent = get_SymConst_entity (load_ptr); + } else if (get_SymConst_kind (load_ptr) == symconst_type_tag) { + tp = get_SymConst_type (load_ptr); + } else { + fprintf (stdout, "%s: cannot handle load (%s)\n", + __FUNCTION__, get_op_name (get_irn_op (load_ptr))); + + cough_and_die (load_ptr); + } + } else { + fprintf (stdout, "%s: cannot handle load (%s)\n", + __FUNCTION__, get_op_name (get_irn_op (load_ptr))); + cough_and_die (load_ptr); + } + + tp = get_entity_type (ent); + + while (is_Pointer_type (tp)) { + tp = get_pointer_points_to_type (tp); + } + + res = ta_type (tp); + + return (res); +} + + /** Find an approximation to the given proj node's value's types */ @@ -466,43 +622,32 @@ static typalise_t *typalise_proj (ir_node *proj) proj_in = get_Proj_pred (proj_in); if (iro_Start == get_irn_opcode (proj_in)) { - ir_graph *graph = get_irn_irg (proj); - entity *meth = get_irg_entity (graph); + /* aha, proj arg */ + ir_graph *graph = get_irn_irg (proj); + ir_entity *meth = get_irg_entity (graph); long n = get_Proj_proj (proj); + ir_type *tp = get_method_param_type (get_entity_type (meth), n); + if (is_Pointer_type (tp)) { + tp = get_pointer_points_to_type (tp); + } - if (1 == n) { - /* yay proj this */ - type *tp = get_entity_owner (meth); - - /* res = ta_exact (tp); */ - res = ta_type (tp); /* TODO */ - } else { - /* ugh proj arg */ - type *tp = get_method_param_type (get_entity_type (meth), n); - if (is_Pointer_type (tp)) { - tp = get_pointer_points_to_type (tp); - } + res = ta_type (tp); - res = ta_type (tp); - } } else if (iro_Call == get_irn_opcode (proj_in)) { /* call result ... 'whatever' */ - /* hey, this is redundant (or the check for iro_Call further down) */ - ir_node *call_ptr = get_Call_ptr (proj_in); - - res = typalise (call_ptr); + res = typalise_call (proj_in); } else { fprintf (stdout, "\n Proj (Proj (%s)) not handled\n", get_op_name (get_irn_op (proj_in))); - assert (0); + cough_and_die (proj_in); } } else { - opcode op = get_irn_opcode (proj_in); + ir_opcode op = get_irn_opcode (proj_in); if ((iro_Load != op) && (iro_Alloc != op) && (iro_Call != op)) { fprintf (stdout, "\n Proj (%s) not handled\n", get_op_name (get_irn_op (proj_in))); - assert (0); + cough_and_die (proj_in); } res = typalise (proj_in); /* everything else */ /* Proj (Load), Proj (New), Proj (Call) */ @@ -545,14 +690,14 @@ lset_t *filter_for_ta (lset_t *set, typalise_t *ta) */ typalise_t *typalise (ir_node *node) { - opcode op = get_irn_opcode (node); + ir_opcode op = get_irn_opcode (node); typalise_t *res = NULL; switch (op) { case (iro_Cast): { /* casts always succeed */ typalise_t *ta = NULL; - type *tp = get_Cast_type (node); + ir_type *tp = get_Cast_type (node); if (is_Pointer_type (tp)) { tp = get_pointer_points_to_type (tp); @@ -585,18 +730,18 @@ typalise_t *typalise (ir_node *node) } break; case (iro_Load): { - ir_node *load_ptr = get_Load_ptr (node); - - res = typalise (load_ptr); + res = typalise_load (node); } break; case (iro_Sel): { /* FILTER */ /* it's call (sel (ptr)) or load (sel (ptr)) */ - entity *ent = get_Sel_entity (node); - type *tp = get_entity_type (ent); + ir_entity *ent = get_Sel_entity (node); + ir_type *tp = get_entity_type (ent); if (is_Method_type (tp)) { + /* obsoleted by typalise_call */ + assert (0); tp = get_entity_type (ent); tp = get_method_res_type (tp, 0); @@ -626,25 +771,30 @@ typalise_t *typalise (ir_node *node) int i; ir_node *phi_in = NULL; typalise_t *ta = NULL; - /* assert (0 && "Do we ever get here?"); */ /* apparently, we do. */ for (i = 0; i < n_ins; i ++) { + typalise_t *ta_in; + phi_in = get_irn_n (node, i); - ta = (NULL == ta) ? typalise (phi_in) : ta_join (ta, typalise (phi_in)); + ta_in = typalise (phi_in); + + if (NULL != ta_in) { + ta = (NULL == ta) ? ta_in : ta_join (ta, ta_in); + } } res = ta; } break; case (iro_Alloc): { - type *type = get_Alloc_type (node); + ir_type *type = get_Alloc_type (node); res = ta_exact (type); } break; case (iro_Call): { /* presumably call (sel (proj (call))) */ ir_node *ptr = get_Call_ptr (node); - entity *meth = NULL; + ir_entity *meth = NULL; if (iro_Sel == get_irn_opcode (ptr)) { meth = get_Sel_entity (ptr); } else if (iro_SymConst == get_irn_opcode (ptr)) { @@ -656,7 +806,7 @@ typalise_t *typalise (ir_node *node) } if (NULL != meth) { - type *tp = get_method_res_type ((type*) meth, 0); + ir_type *tp = get_method_res_type ((ir_type*) meth, 0); res = ta_type (tp); } else { /* could be anything */ @@ -664,50 +814,99 @@ typalise_t *typalise (ir_node *node) res = NULL; } - fprintf (stdout, "]\n"); + /* fprintf (stdout, "]\n"); */ } break; case (iro_SymConst): { if (get_SymConst_kind (node) == symconst_type_tag) { - type *tp = get_SymConst_type (node); + ir_type *tp = get_SymConst_type (node); res = ta_type (tp); } else if (get_SymConst_kind (node) == symconst_addr_ent) { - entity *ent = get_SymConst_entity (node); - type *tp = get_entity_type (ent); - tp = get_pointer_points_to_type (tp); + ir_entity *ent = get_SymConst_entity (node); + ir_type *tp = get_entity_owner (ent); + + while (is_Pointer_type (tp)) { + tp = get_pointer_points_to_type (tp); + } + assert (is_Class_type (tp)); res = ta_type (tp); /* can't use ta_exact */ + } else if (get_SymConst_kind (node) == symconst_addr_name) { + /* oh, this is not a real call but a placeholder (exception stuff) */ + fprintf (stdout, "%s (%s:%i): can't handle pseudo-call %s\n", + __FUNCTION__, __FILE__, __LINE__, + get_op_name (get_irn_op (node))); + + res = NULL; } else { - fprintf (stdout, "%s (%s:%i): can't handle SymConst %s?\n", + fprintf (stdout, "%s (%s:%i): can't handle SymConst %s\n", __FUNCTION__, __FILE__, __LINE__, get_op_name (get_irn_op (node))); + res = NULL; } } break; + case (iro_Const): { + /* presumably a NULL constant */ + /* this also means we cannot handle calls against a NULL pointer. */ + res = NULL; + } break; - /* template: - case (iro_Cast): {} - break; - */ + /* template: + case (iro_Cast): {} + break; + */ default: { fprintf (stdout, "what's with %s?\n", get_op_name (get_irn_op (node))); - assert (0); + cough_and_die (node); } break; } return (res); } +/* + Initialise the Typalise module +*/ +void typalise_init (void) +{ + if (NULL == java_lang_Throwable_tp) { + class_walk_super2sub (find_java_lang_Throwable, NULL, NULL); + + /* make sure we have found it */ + get_java_lang_Throwable (); + } +} /* $Log$ + Revision 1.14 2007/01/16 15:45:42 beck + renamed type opcode to ir_opcode + + Revision 1.13 2006/12/13 19:46:47 beck + rename type entity into ir_entity + + Revision 1.12 2006/01/13 21:54:02 beck + renamed all types 'type' to 'ir_type' + + Revision 1.11 2005/05/13 16:35:14 beck + made (void) prototypes + removed unused fprintf arguments + + Revision 1.10 2005/05/06 12:02:34 beck + added missing includes + removed C99 features + + Revision 1.9 2005/03/22 13:56:09 liekweg + "small" fix for exception b/d + Revision 1.8 2005/01/14 14:13:24 liekweg fix gnu extension