Define functions prototypes
[cacao.git] / typeinfo.c
index 10ee21069e74d30c021decec9435d42f48cf671f..1c7f3328d4166547419d08e15b1dc285fb053d58 100644 (file)
@@ -26,7 +26,7 @@
 
    Authors: Edwin Steiner
 
-   $Id: typeinfo.c 723 2003-12-08 19:51:32Z edwin $
+   $Id: typeinfo.c 922 2004-02-24 13:26:24Z edwin $
 
 */
 
 #include "loader.h"
 #include "toolbox/loging.h"
 #include "toolbox/memory.h"
+#include "jit/jit.h" /* XXX move typeinfo.* into jit/ */
 
 
 #define CLASS_IMPLEMENTS_INTERFACE(cls,index)                   \
     ( ((index) < (cls)->vftbl->interfacetablelength)            \
       && (VFTBLINTERFACETABLE((cls)->vftbl,(index)) != NULL) )
 
+/**********************************************************************/
+/* TYPEVECTOR FUNCTIONS                                               */
+/**********************************************************************/
+
+typevector *
+typevectorset_copy(typevector *src,int k,int size)
+{
+       typevector *dst = DNEW_TYPEVECTOR(size);
+       
+       memcpy(dst,src,TYPEVECTOR_SIZE(size));
+       dst->k = k;
+       if (src->alt)
+               dst->alt = typevectorset_copy(src->alt,k+1,size);
+       return dst;
+}
+
+bool
+typevectorset_checktype(typevector *vec,int index,int type)
+{
+       do {
+               if (vec->td[index].type != type)
+                       return false;
+       } while ((vec = vec->alt) != NULL);
+       return true;
+}
+
+bool
+typevectorset_checkreference(typevector *vec,int index)
+{
+       do {
+               if (!TYPEDESC_IS_REFERENCE(vec->td[index]))
+                       return false;
+       } while ((vec = vec->alt) != NULL);
+       return true;
+}
+
+bool
+typevectorset_checkretaddr(typevector *vec,int index)
+{
+       do {
+               if (!TYPEDESC_IS_RETURNADDRESS(vec->td[index]))
+                       return false;
+       } while ((vec = vec->alt) != NULL);
+       return true;
+}
+
+int
+typevectorset_copymergedtype(typevector *vec,int index,typeinfo *dst)
+{
+       int type;
+       typedescriptor *td;
+
+       td = vec->td + index;
+       type = td->type;
+       TYPEINFO_COPY(td->info,*dst);
+       
+       if (vec->alt) {
+               int primitive;
+               
+               primitive = TYPEINFO_IS_PRIMITIVE(*dst) ? 1 : 0;
+               
+               while ((vec = vec->alt) != NULL) {
+                       td = vec->td + index;
+                       if (type != td->type)
+                               return TYPE_VOID;
+
+                       if (type == TYPE_ADDRESS) {
+                               if ((TYPEINFO_IS_PRIMITIVE(td->info) ? 1 : 0) != primitive)
+                                       return TYPE_VOID;
+                               typeinfo_merge(dst,&(td->info));
+                       }
+               }
+       }
+       return type;
+}
+
+int
+typevectorset_mergedtype(typevector *vec,int index,typeinfo *temp,typeinfo **result)
+{
+       if (vec->alt) {
+               *result = temp;
+               return typevectorset_copymergedtype(vec,index,temp);
+       }
+
+       *result = &(vec->td[index].info);
+       return vec->td[index].type;
+}
+
+typeinfo *
+typevectorset_mergedtypeinfo(typevector *vec,int index,typeinfo *temp)
+{
+       typeinfo *result;
+       int type = typevectorset_mergedtype(vec,index,temp,&result);
+       return (type == TYPE_ADDRESS) ? result : NULL;
+}
+
+void
+typevectorset_store(typevector *vec,int index,int type,typeinfo *info)
+{
+       do {
+               vec->td[index].type = type;
+               if (info)
+                       TYPEINFO_COPY(*info,vec->td[index].info);
+               if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
+                       vec->td[index-1].type = TYPE_VOID;
+       } while ((vec = vec->alt) != NULL);
+}
+
+void
+typevectorset_store_retaddr(typevector *vec,int index,typeinfo *info)
+{
+       typeinfo_retaddr_set *adr;
+       
+       adr = (typeinfo_retaddr_set*) TYPEINFO_RETURNADDRESS(*info);
+       do {
+               vec->td[index].type = TYPE_ADDRESS;
+               TYPEINFO_INIT_RETURNADDRESS(vec->td[index].info,adr->addr);
+               if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
+                       vec->td[index-1].type = TYPE_VOID;
+               adr = adr->alt;
+       } while ((vec = vec->alt) != NULL);
+}
+
+void
+typevectorset_store_twoword(typevector *vec,int index,int type)
+{
+       do {
+               vec->td[index].type = type;
+               vec->td[index+1].type = TYPE_VOID;
+               if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
+                       vec->td[index-1].type = TYPE_VOID;
+       } while ((vec = vec->alt) != NULL);
+}
+
+void
+typevectorset_init_object(typevector *set,void *ins,classinfo *initclass,
+                                                 int size)
+{
+       int i;
+       
+       for (;set; set=set->alt) {
+               for (i=0; i<size; ++i) {
+                       if (set->td[i].type == TYPE_ADR
+                               && TYPEINFO_IS_NEWOBJECT(set->td[i].info)
+                               && TYPEINFO_NEWOBJECT_INSTRUCTION(set->td[i].info) == ins)
+                       {
+                               TYPEINFO_INIT_CLASSINFO(set->td[i].info,initclass);
+                       }
+               }
+       }
+}
+
+bool
+typevector_merge(typevector *dst,typevector *y,int size)
+{
+       bool changed = false;
+       
+       typedescriptor *a = dst->td;
+       typedescriptor *b = y->td;
+       while (size--) {
+               if (a->type != TYPE_VOID && a->type != b->type) {
+                       a->type = TYPE_VOID;
+                       changed = true;
+               }
+               else if (a->type == TYPE_ADDRESS) {
+                       if (TYPEINFO_IS_PRIMITIVE(a->info)) {
+                               /* 'a' is a returnAddress */
+                               if (!TYPEINFO_IS_PRIMITIVE(b->info)
+                                       || (TYPEINFO_RETURNADDRESS(a->info)
+                                               != TYPEINFO_RETURNADDRESS(b->info)))
+                               {
+                                       a->type = TYPE_VOID;
+                                       changed = true;
+                               }
+                       }
+                       else {
+                               /* 'a' is a reference */
+                               if (TYPEINFO_IS_PRIMITIVE(b->info)) {
+                                       a->type = TYPE_VOID;
+                                       changed = true;
+                               }
+                               else {
+                                       changed |= typeinfo_merge(&(a->info),&(b->info));
+                               }
+                       }
+               }
+               a++;
+               b++;
+       }
+       return changed;
+}
+
+bool typevector_separable_from(typevector *a,typevector *b,int size)
+{
+       typedescriptor *tda = a->td;
+       typedescriptor *tdb = b->td;
+       for (;size--; tda++,tdb++) {
+               if (TYPEDESC_IS_RETURNADDRESS(*tda)
+                       && TYPEDESC_IS_RETURNADDRESS(*tdb)
+                       && TYPEINFO_RETURNADDRESS(tda->info)
+                          != TYPEINFO_RETURNADDRESS(tdb->info))
+                       return true;
+       }
+       return false;
+}
+
+void
+typevectorset_add(typevector *dst,typevector *v,int size)
+{
+       while (dst->alt)
+               dst = dst->alt;
+       dst->alt = DNEW_TYPEVECTOR(size);
+       memcpy(dst->alt,v,TYPEVECTOR_SIZE(size));
+       dst->alt->alt = NULL;
+       dst->alt->k = dst->k + 1;
+}
+
+typevector *
+typevectorset_select(typevector **set,int retindex,void *retaddr)
+{
+       typevector *selected;
+
+       if (!*set) return NULL;
+       
+       if (TYPEINFO_RETURNADDRESS((*set)->td[retindex].info) == retaddr) {
+               selected = *set;
+               *set = selected->alt;
+               selected->alt = typevectorset_select(set,retindex,retaddr);
+       }
+       else {
+               selected = typevectorset_select(&((*set)->alt),retindex,retaddr);
+       }
+       return selected;
+}
+
+bool
+typevectorset_separable_with(typevector *set,typevector *add,int size)
+{
+       int i;
+       typevector *v;
+       void *addr;
+       bool separable;
+
+       for (i=0; i<size; ++i) {
+               if (!TYPEDESC_IS_RETURNADDRESS(add->td[i]))
+                       continue;
+               addr = TYPEINFO_RETURNADDRESS(add->td[i].info);
+               
+               v = set;
+               separable = false;
+               do {
+                       if (!TYPEDESC_IS_RETURNADDRESS(v->td[i]))
+                               goto next_index;
+                       if (TYPEINFO_RETURNADDRESS(v->td[i].info) != addr)
+                               separable = true;
+                       v = v->alt;
+                       if (!v && separable) return true;
+               } while (v);
+       next_index:
+               ;
+       }
+       return false;
+}
+
+bool
+typevectorset_collapse(typevector *dst,int size)
+{
+       bool changed = false;
+       
+       while (dst->alt) {
+               typevector_merge(dst,dst->alt,size);
+               dst->alt = dst->alt->alt;
+               changed = true;
+       }
+       return changed;
+}
+
 /**********************************************************************/
 /* READ-ONLY FUNCTIONS                                                */
 /* The following functions don't change typeinfo data.                */
@@ -88,7 +366,6 @@ interface_extends_interface(classinfo *cls,classinfo *interf)
     return false;
 }
 
-/* XXX If really a performance issue, this could become a macro. */
 static
 bool
 classinfo_implements_interface(classinfo *cls,classinfo *interf)
@@ -150,24 +427,35 @@ merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged,
 bool
 typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
 {
-    classinfo *cls;
-
-    cls = value->typeclass;
-
     /* DEBUG CHECK: dest must not have a merged list. */
 #ifdef TYPEINFO_DEBUG
     if (dest->merged)
         panic("Internal error: typeinfo_is_assignable on merged destination.");
 #endif
-    
+
+       return typeinfo_is_assignable_to_classinfo(value,dest->typeclass);
+}
+
+bool
+typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest)
+{
+    classinfo *cls;
+
+    cls = value->typeclass;
+
     /* assignments of primitive values are not checked here. */
-    if (!cls && !dest->typeclass)
+    if (!cls && !dest)
         return true;
 
     /* primitive and reference types are not assignment compatible. */
-    if (!cls || !dest->typeclass)
+    if (!cls || !dest)
         return false;
 
+#ifdef TYPEINFO_DEBUG
+    if (!dest->linked)
+        panic("Internal error: typeinfo_is_assignable_to_classinfo: unlinked class.");
+#endif
+       
     /* the null type can be assigned to any type */
     if (TYPEINFO_IS_NULLTYPE(*value))
         return true;
@@ -176,13 +464,17 @@ typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
     if (TYPEINFO_IS_NEWOBJECT(*value))
         return false;
 
-    if (dest->typeclass->flags & ACC_INTERFACE) {
+    if (dest->flags & ACC_INTERFACE) {
         /* We are assigning to an interface type. */
-        return merged_implements_interface(cls,value->merged,
-                                           dest->typeclass);
+        return merged_implements_interface(cls,value->merged,dest);
     }
 
-    if (TYPEINFO_IS_ARRAY(*dest)) {
+    if (CLASS_IS_ARRAY(dest)) {
+               arraydescriptor *arraydesc = dest->vftbl->arraydesc;
+               int dimension = arraydesc->dimension;
+               classinfo *elementclass = (arraydesc->elementvftbl)
+                       ? arraydesc->elementvftbl->class : NULL;
+                       
         /* We are assigning to an array type. */
         if (!TYPEINFO_IS_ARRAY(*value))
             return false;
@@ -190,27 +482,29 @@ typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
         /* {Both value and dest are array types.} */
 
         /* value must have at least the dimension of dest. */
-        if (value->dimension < dest->dimension)
+        if (value->dimension < dimension)
             return false;
 
-        if (value->dimension > dest->dimension) {
+        if (value->dimension > dimension) {
             /* value has higher dimension so we need to check
              * if its component array can be assigned to the
              * element type of dest */
+
+                       if (!elementclass) return false;
             
-            if (dest->elementclass->flags & ACC_INTERFACE) {
+            if (elementclass->flags & ACC_INTERFACE) {
                 /* We are assigning to an interface type. */
                 return classinfo_implements_interface(pseudo_class_Arraystub,
-                                                      dest->elementclass);
+                                                      elementclass);
             }
 
             /* We are assigning to a class type. */
-            return class_issubclass(pseudo_class_Arraystub,dest->elementclass);
+            return class_issubclass(pseudo_class_Arraystub,elementclass);
         }
 
         /* {value and dest have the same dimension} */
 
-        if (value->elementtype != dest->elementtype)
+        if (value->elementtype != arraydesc->elementtype)
             return false;
 
         if (value->elementclass) {
@@ -218,16 +512,16 @@ typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
              * check if the elements are assignable.
              */
 
-            if (dest->elementclass->flags & ACC_INTERFACE) {
+            if (elementclass->flags & ACC_INTERFACE) {
                 /* We are assigning to an interface type. */
 
                 return merged_implements_interface(value->elementclass,
                                                    value->merged,
-                                                   dest->elementclass);
+                                                   elementclass);
             }
             
             /* We are assigning to a class type. */
-            return class_issubclass(value->elementclass,dest->elementclass);
+            return class_issubclass(value->elementclass,elementclass);
         }
 
         return true;
@@ -239,7 +533,7 @@ typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
     if (cls->flags & ACC_INTERFACE)
         cls = class_java_lang_Object;
     
-    return class_issubclass(cls,dest->typeclass);
+    return class_issubclass(cls,dest);
 }
 
 /**********************************************************************/
@@ -253,7 +547,6 @@ typeinfo_init_from_descriptor(typeinfo *info,char *utf_ptr,char *end_ptr)
     classinfo *cls;
     char *end;
 
-    /* XXX simplify */
     cls = class_from_descriptor(utf_ptr,end_ptr,&end,
                                                                CLASSLOAD_NULLPRIMITIVE
                                                                | CLASSLOAD_NEW
@@ -349,6 +642,61 @@ typeinfo_init_from_method_args(utf *desc,u1 *typebuf,typeinfo *infobuf,
        }
 }
 
+int
+typedescriptors_init_from_method_args(typedescriptor *td,
+                                                                         utf *desc,
+                                                                         int buflen,bool twoword,
+                                                                         typedescriptor *returntype)
+{
+    char *utf_ptr = desc->text;     /* current position in utf text   */
+    char *end_pos = utf_end(desc);  /* points behind utf string       */
+    int args = 0;
+    classinfo *cls;
+
+    /* method descriptor must start with parenthesis */
+    if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
+
+    /* check arguments */
+    while (utf_ptr != end_pos && *utf_ptr != ')') {
+               if (++args > buflen)
+                       panic("Buffer too small for method arguments.");
+               
+        td->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
+                                                                               CLASSLOAD_NEW
+                                                                               | CLASSLOAD_NULLPRIMITIVE
+                                                                               | CLASSLOAD_NOVOID);
+               
+               if (cls)
+                       TYPEINFO_INIT_CLASSINFO(td->info,cls);
+               else {
+                       TYPEINFO_INIT_PRIMITIVE(td->info);
+               }
+               td++;
+
+               if (twoword && (td[-1].type == TYPE_LONG || td[-1].type == TYPE_DOUBLE)) {
+                       if (++args > buflen)
+                               panic("Buffer too small for method arguments.");
+                       td->type = TYPE_VOID;
+                       TYPEINFO_INIT_PRIMITIVE(td->info);
+                       td++;
+               }
+    }
+    utf_ptr++; /* skip ')' */
+
+    /* check returntype */
+    if (returntype) {
+               returntype->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
+                                                                                               CLASSLOAD_NULLPRIMITIVE
+                                                                                               | CLASSLOAD_NEW
+                                                                                               | CLASSLOAD_CHECKEND);
+               if (cls)
+                       TYPEINFO_INIT_CLASSINFO(returntype->info,cls);
+               else
+                       TYPEINFO_INIT_PRIMITIVE(returntype->info);
+       }
+       return args;
+}
+
 void
 typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
 {
@@ -359,7 +707,6 @@ typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
         return;
     }
     
-    /* XXX find component class */
     if (!TYPEINFO_IS_ARRAY(*srcarray))
         panic("Trying to access component of non-array");
 
@@ -370,20 +717,6 @@ typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
     else {
         TYPEINFO_INIT_PRIMITIVE(*dst);
     }
-
-    /* XXX assign directly ? */
-#if 0
-    if ((dst->dimension = srcarray->dimension - 1) == 0) {
-        dst->typeclass = srcarray->elementclass;
-        dst->elementtype = 0;
-        dst->elementclass = NULL;
-    }
-    else {
-        dst->typeclass = srcarray->typeclass;
-        dst->elementtype = srcarray->elementtype;
-        dst->elementclass = srcarray->elementclass;
-    }
-#endif
     
     dst->merged = srcarray->merged;
 }
@@ -404,7 +737,6 @@ typeinfo_clone(typeinfo *src,typeinfo *dest)
         TYPEINFO_ALLOCMERGED(dest->merged,count);
         dest->merged->count = count;
 
-        /* XXX use memcpy? */
         srclist = src->merged->list;
         destlist = dest->merged->list;
         while (count--)
@@ -639,7 +971,7 @@ typeinfo_merge_nonarrays(typeinfo *dest,
     typeinfo_mergedlist *tmerged;
     bool changed;
 
-    /* XXX remove */
+    /* DEBUG */
     /*
 #ifdef TYPEINFO_DEBUG
     typeinfo dbgx,dbgy;
@@ -658,15 +990,14 @@ typeinfo_merge_nonarrays(typeinfo *dest,
     /* (This case is very simple unless *both* x and y really represent
      *  merges of subclasses of clsx==clsy.)
      */
-    /* XXX count this case for statistics */
     if ((clsx == clsy) && (!mergedx || !mergedy)) {
   return_simple_x:
-        /* XXX remove */ /* log_text("return simple x"); */
+        /* DEBUG */ /* log_text("return simple x"); */
         changed = (dest->merged != NULL);
         TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
         dest->merged = NULL;
         *result = clsx;
-        /* XXX remove */ /* log_text("returning"); */
+        /* DEBUG */ /* log_text("returning"); */
         return changed;
     }
     
@@ -684,7 +1015,6 @@ typeinfo_merge_nonarrays(typeinfo *dest,
         if (clsy->flags & ACC_INTERFACE) {
             /* We are merging two interfaces. */
             /* {mergedy == NULL} */
-            /* XXX: should we optimize direct superinterfaces? */
 
             /* {We know that clsx!=clsy (see common case at beginning.)} */
             *result = class_java_lang_Object;
@@ -718,7 +1048,7 @@ typeinfo_merge_nonarrays(typeinfo *dest,
          * by y, too, so we have to add clsx to the mergedlist.
          */
 
-        /* XXX if x has no superinterfaces we could return a simple java.lang.Object */
+        /* if x has no superinterfaces we could return a simple java.lang.Object */
         
         common = class_java_lang_Object;
         goto merge_with_simple_x;
@@ -783,7 +1113,7 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
     int elementtype;
     bool changed;
 
-    /* XXX remove */
+    /* DEBUG */
     /*
 #ifdef TYPEINFO_DEBUG
     typeinfo_print(stdout,dest,4);
@@ -796,10 +1126,16 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
         return false;
 
     /* Merging two returnAddress types is ok. */
-    if (!dest->typeclass && !y->typeclass)
+    if (!dest->typeclass && !y->typeclass) {
+#ifdef TYPEINFO_DEBUG
+               if (TYPEINFO_RETURNADDRESS(*dest) != TYPEINFO_RETURNADDRESS(*y))
+                       panic("Internal error: typeinfo_merge merges different returnAddresses");
+#endif
         return false;
+       }
     
     /* Primitive types cannot be merged with reference types */
+       /* XXX only check this in debug mode? */
     if (!dest->typeclass || !y->typeclass)
         typeinfo_merge_error("Trying to merge primitive types.",dest,y);
 
@@ -820,22 +1156,21 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
         return false;
     }
     
-    /* XXX remove */ /* log_text("Testing common case"); */
+    /* DEBUG */ /* log_text("Testing common case"); */
 
     /* Common case: class dest == class y */
     /* (This case is very simple unless *both* dest and y really represent
      *  merges of subclasses of class dest==class y.)
      */
-    /* XXX count this case for statistics */
     if ((dest->typeclass == y->typeclass) && (!dest->merged || !y->merged)) {
         changed = (dest->merged != NULL);
-        TYPEINFO_FREEMERGED_IF_ANY(dest->merged); /* XXX unify if? */
+        TYPEINFO_FREEMERGED_IF_ANY(dest->merged); /* unify if? */
         dest->merged = NULL;
-        /* XXX remove */ /* log_text("common case handled"); */
+        /* DEBUG */ /* log_text("common case handled"); */
         return changed;
     }
     
-    /* XXX remove */ /* log_text("Handling null types"); */
+    /* DEBUG */ /* log_text("Handling null types"); */
 
     /* Handle null types: */
     if (TYPEINFO_IS_NULLTYPE(*y)) {
@@ -855,7 +1190,7 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
     /* Handle merging of arrays: */
     if (TYPEINFO_IS_ARRAY(*x) && TYPEINFO_IS_ARRAY(*y)) {
         
-        /* XXX remove */ /* log_text("Handling arrays"); */
+        /* DEBUG */ /* log_text("Handling arrays"); */
 
         /* Make x the one with lesser dimension */
         if (x->dimension > y->dimension) {
@@ -904,10 +1239,9 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
                                                     elementclass,
                                                     x->merged,y->merged);
 
-                /* XXX otimize this? */
-                /* XXX remove */ /* log_text("finding resulting array class: "); */
+                /* DEBUG */ /* log_text("finding resulting array class: "); */
                 common = class_multiarray_of(dimension,elementclass);
-                /* XXX remove */ /* utf_display(common->name); printf("\n"); */
+                /* DEBUG */ /* utf_display(common->name); printf("\n"); */
             }
         }
     }
@@ -944,7 +1278,7 @@ typeinfo_merge(typeinfo *dest,typeinfo* y)
         changed = true;
     }
 
-    /* XXX remove */ /* log_text("returning from merge"); */
+    /* DEBUG */ /* log_text("returning from merge"); */
     
     return changed;
 }
@@ -1096,6 +1430,7 @@ typeinfo_testrun(char *filename)
     int maxdim;
     int failed = 0;
     FILE *file = fopen(filename,"rt");
+       int res;
     
     if (!file)
         panic("could not open typeinfo test file");
@@ -1104,7 +1439,7 @@ typeinfo_testrun(char *filename)
         if (buf[0] == '#' || !strlen(buf))
             continue;
         
-        int res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc);
+        res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc);
         if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc))
             panic("Invalid line in typeinfo test file (none of empty, comment or test)");
 
@@ -1161,6 +1496,7 @@ typeinfo_print(FILE *file,typeinfo *info,int indent)
     int i;
     char ind[TYPEINFO_MAXINDENT + 1];
     instruction *ins;
+       basicblock *bptr;
 
     if (indent > TYPEINFO_MAXINDENT) indent = TYPEINFO_MAXINDENT;
     
@@ -1169,7 +1505,11 @@ typeinfo_print(FILE *file,typeinfo *info,int indent)
     ind[i] = (char) 0;
     
     if (TYPEINFO_IS_PRIMITIVE(*info)) {
-        fprintf(file,"%sprimitive\n",ind);
+               bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
+               if (bptr)
+                       fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->debug_nr);
+               else
+                       fprintf(file,"%sprimitive\n",ind);
         return;
     }
     
@@ -1234,9 +1574,14 @@ typeinfo_print_short(FILE *file,typeinfo *info)
 {
     int i;
     instruction *ins;
+       basicblock *bptr;
 
     if (TYPEINFO_IS_PRIMITIVE(*info)) {
-        fprintf(file,"primitive");
+               bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
+               if (bptr)
+                       fprintf(file,"ret(L%03d)",bptr->debug_nr);
+               else
+                       fprintf(file,"primitive");
         return;
     }
     
@@ -1278,11 +1623,7 @@ typeinfo_print_type(FILE *file,int type,typeinfo *info)
       case TYPE_DOUBLE: fprintf(file,"D"); break;
       case TYPE_LONG:   fprintf(file,"J"); break;
       case TYPE_ADDRESS:
-          if (TYPEINFO_IS_PRIMITIVE(*info))
-              fprintf(file,"R"); /* returnAddress */
-          else {
-              typeinfo_print_short(file,info);
-          }
+                 typeinfo_print_short(file,info);
           break;
           
       default:
@@ -1290,6 +1631,68 @@ typeinfo_print_type(FILE *file,int type,typeinfo *info)
     }
 }
 
+void
+typeinfo_print_stacktype(FILE *file,int type,typeinfo *info)
+{
+       if (type == TYPE_ADDRESS && TYPEINFO_IS_PRIMITIVE(*info)) {     
+               typeinfo_retaddr_set *set = (typeinfo_retaddr_set*)
+                       TYPEINFO_RETURNADDRESS(*info);
+               fprintf(file,"ret(L%03d",((basicblock*)(set->addr))->debug_nr);
+               set = set->alt;
+               while (set) {
+                       fprintf(file,"|L%03d",((basicblock*)(set->addr))->debug_nr);
+                       set = set->alt;
+               }
+               fprintf(file,")");
+       }
+       else
+               typeinfo_print_type(file,type,info);
+}
+
+void
+typedescriptor_print(FILE *file,typedescriptor *td)
+{
+       typeinfo_print_type(file,td->type,&(td->info));
+}
+
+void
+typevector_print(FILE *file,typevector *vec,int size)
+{
+    int i;
+
+       fprintf(file,"[%d]",vec->k);
+    for (i=0; i<size; ++i) {
+               fprintf(file," %d=",i);
+        typedescriptor_print(file,vec->td + i);
+    }
+}
+
+void
+typevectorset_print(FILE *file,typevector *set,int size)
+{
+    int i;
+       typevector *vec;
+
+       fprintf(file,"[%d",set->k);
+       vec = set->alt;
+       while (vec) {
+               fprintf(file,"|%d",vec->k);
+               vec = vec->alt;
+       }
+       fprintf(file,"]");
+       
+    for (i=0; i<size; ++i) {
+               fprintf(file," %d=",i);
+        typedescriptor_print(file,set->td + i);
+               vec = set->alt;
+               while (vec) {
+                       fprintf(file,"|");
+                       typedescriptor_print(file,vec->td + i);
+                       vec = vec->alt;
+               }
+    }
+}
+
 #endif /* TYPEINFO_DEBUG */