# include "irnode_t.h"
# include "irgwalk.h"
# include "xmalloc.h"
+# include "gnu_ext.h"
+# include "irdump.h"
+# include "typewalk.h"
/*
*/
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 = (typalise_t*) xmalloc (sizeof (typalise_t));
+ typalise_t *ta = xmalloc (sizeof (typalise_t));
ta->kind = type_exact;
ta->res.type = tp;
ta->id = ta_id ++;
- assert (is_class_type (tp));
+ assert (is_Class_type (tp));
return (ta);
}
static typalise_t *ta_types (lset_t *set)
{
- typalise_t *ta = (typalise_t*) xmalloc (sizeof (typalise_t));
+ typalise_t *ta = xmalloc (sizeof (typalise_t));
ta->kind = type_types;
ta->res.types = set;
ta->id = ta_id ++;
return (ta);
}
-static typalise_t *ta_type (type *tp)
+static typalise_t *ta_type (ir_type *tp)
{
- typalise_t *ta = (typalise_t*) xmalloc (sizeof (typalise_t));
+ typalise_t *ta = xmalloc (sizeof (typalise_t));
ta->kind = type_type;
ta->res.type = tp;
ta->id = ta_id ++;
- assert (is_class_type (tp));
+ assert (is_Class_type (tp));
return (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;
}
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);
}
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;
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 ();
/**
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) {
{
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): {
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);
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)) {
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, 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) {
}
case (type_type): {
entity *meth = get_irg_entity (graph);
- type *tp = get_entity_owner (meth);
+ ir_type *tp = get_entity_owner (meth);
int res = is_subtype (tp, ta->res.type);
if (res) {
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));
}
/* =========== 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)
+{
+ 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)
+{
+ 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
*/
proj_in = get_Proj_pred (proj_in);
if (iro_Start == get_irn_opcode (proj_in)) {
+ /* aha, proj arg */
ir_graph *graph = get_irn_irg (proj);
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);
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) */
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)) {
+ if (is_Pointer_type (tp)) {
tp = get_pointer_points_to_type (tp);
}
- assert (is_class_type (tp));
+ assert (is_Class_type (tp));
ta = typalise (get_Cast_op (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_type *tp = get_entity_type (ent);
- if (is_method_type (tp)) {
+ if (is_Method_type (tp)) {
+ /* obsoleted by typalise_call */
+ assert (0);
tp = get_entity_type (ent);
tp = get_method_res_type (tp, 0);
- if (is_pointer_type (tp)) {
+ if (is_Pointer_type (tp)) {
tp = get_pointer_points_to_type (tp);
}
res = ta_type (tp);
- } else if (is_class_type (tp)) {
+ } else if (is_Class_type (tp)) {
tp = get_entity_type (ent);
- if (is_pointer_type (tp)) {
+ if (is_Pointer_type (tp)) {
tp = get_pointer_points_to_type (tp);
}
res = ta_type (tp);
- } else if (is_pointer_type (tp)) {
+ } else if (is_Pointer_type (tp)) {
tp = get_pointer_points_to_type (tp);
res = ta_type (tp);
} else {
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;
}
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 */
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);
- assert (is_class_type (tp));
+ 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, "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 ();
+ }
+}
\f
/*
$Log$
+ 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
+
+ Revision 1.7 2005/01/10 17:26:34 liekweg
+ fixup printfs, don't put environments on the stack
+
+ Revision 1.6 2005/01/05 14:25:54 beck
+ renames all is_x*_type() functions to is_X*_type() to prevent name clash with EDG fronten
+
+ Revision 1.5 2004/12/22 14:43:14 beck
+ made allocations C-like
+
Revision 1.4 2004/12/21 15:50:18 beck
removed C99 constructs