cleanup
[cacao.git] / typeinfo.c
1 /* typeinfo.c - type system used by the type checker
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4    R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5    M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6    P. Tomsich, J. Wenninger
7
8    This file is part of CACAO.
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2, or (at
13    your option) any later version.
14
15    This program is distributed in the hope that it will be useful, but
16    WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Edwin Steiner
28
29    $Id: typeinfo.c 887 2004-01-19 12:14:39Z edwin $
30
31 */
32
33
34 #include <stdlib.h>
35 #include <string.h>
36 #include "typeinfo.h"
37 #include "tables.h"
38 #include "loader.h"
39 #include "toolbox/loging.h"
40 #include "toolbox/memory.h"
41 #include "jit/jit.h" /* XXX move typeinfo.* into jit/ */
42
43
44 #define CLASS_IMPLEMENTS_INTERFACE(cls,index)                   \
45     ( ((index) < (cls)->vftbl->interfacetablelength)            \
46       && (VFTBLINTERFACETABLE((cls)->vftbl,(index)) != NULL) )
47
48 /**********************************************************************/
49 /* TYPEVECTOR FUNCTIONS                                               */
50 /**********************************************************************/
51
52 typevector *
53 typevectorset_copy(typevector *src,int k,int size)
54 {
55         typevector *dst = DNEW_TYPEVECTOR(size);
56         
57         memcpy(dst,src,TYPEVECTOR_SIZE(size));
58         dst->k = k;
59         if (src->alt)
60                 dst->alt = typevectorset_copy(src->alt,k+1,size);
61         return dst;
62 }
63
64 bool
65 typevectorset_checktype(typevector *vec,int index,int type)
66 {
67         do {
68                 if (vec->td[index].type != type)
69                         return false;
70         } while ((vec = vec->alt) != NULL);
71         return true;
72 }
73
74 bool
75 typevectorset_checkreference(typevector *vec,int index)
76 {
77         do {
78                 if (!TYPEDESC_IS_REFERENCE(vec->td[index]))
79                         return false;
80         } while ((vec = vec->alt) != NULL);
81         return true;
82 }
83
84 bool
85 typevectorset_checkretaddr(typevector *vec,int index)
86 {
87         do {
88                 if (!TYPEDESC_IS_RETURNADDRESS(vec->td[index]))
89                         return false;
90         } while ((vec = vec->alt) != NULL);
91         return true;
92 }
93
94 int
95 typevectorset_copymergedtype(typevector *vec,int index,typeinfo *dst)
96 {
97         int type;
98         typedescriptor *td;
99
100         td = vec->td + index;
101         type = td->type;
102         TYPEINFO_COPY(td->info,*dst);
103         
104         if (vec->alt) {
105                 int primitive;
106                 
107                 primitive = TYPEINFO_IS_PRIMITIVE(*dst) ? 1 : 0;
108                 
109                 while ((vec = vec->alt) != NULL) {
110                         td = vec->td + index;
111                         if (type != td->type)
112                                 return TYPE_VOID;
113
114                         if (type == TYPE_ADDRESS) {
115                                 if ((TYPEINFO_IS_PRIMITIVE(td->info) ? 1 : 0) != primitive)
116                                         return TYPE_VOID;
117                                 typeinfo_merge(dst,&(td->info));
118                         }
119                 }
120         }
121         return type;
122 }
123
124 int
125 typevectorset_mergedtype(typevector *vec,int index,typeinfo *temp,typeinfo **result)
126 {
127         if (vec->alt) {
128                 *result = temp;
129                 return typevectorset_copymergedtype(vec,index,temp);
130         }
131
132         *result = &(vec->td[index].info);
133         return vec->td[index].type;
134 }
135
136 typeinfo *
137 typevectorset_mergedtypeinfo(typevector *vec,int index,typeinfo *temp)
138 {
139         typeinfo *result;
140         int type = typevectorset_mergedtype(vec,index,temp,&result);
141         return (type == TYPE_ADDRESS) ? result : NULL;
142 }
143
144 void
145 typevectorset_store(typevector *vec,int index,int type,typeinfo *info)
146 {
147         do {
148                 vec->td[index].type = type;
149                 if (info)
150                         TYPEINFO_COPY(*info,vec->td[index].info);
151                 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
152                         vec->td[index-1].type = TYPE_VOID;
153         } while ((vec = vec->alt) != NULL);
154 }
155
156 void
157 typevectorset_store_retaddr(typevector *vec,int index,typeinfo *info)
158 {
159         typeinfo_retaddr_set *adr;
160         
161         adr = (typeinfo_retaddr_set*) TYPEINFO_RETURNADDRESS(*info);
162         do {
163                 vec->td[index].type = TYPE_ADDRESS;
164                 TYPEINFO_INIT_RETURNADDRESS(vec->td[index].info,adr->addr);
165                 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
166                         vec->td[index-1].type = TYPE_VOID;
167                 adr = adr->alt;
168         } while ((vec = vec->alt) != NULL);
169 }
170
171 void
172 typevectorset_store_twoword(typevector *vec,int index,int type)
173 {
174         do {
175                 vec->td[index].type = type;
176                 vec->td[index+1].type = TYPE_VOID;
177                 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
178                         vec->td[index-1].type = TYPE_VOID;
179         } while ((vec = vec->alt) != NULL);
180 }
181
182 void
183 typevectorset_init_object(typevector *set,void *ins,classinfo *initclass,
184                                                   int size)
185 {
186         int i;
187         
188         for (;set; set=set->alt) {
189                 for (i=0; i<size; ++i) {
190                         if (set->td[i].type == TYPE_ADR
191                                 && TYPEINFO_IS_NEWOBJECT(set->td[i].info)
192                                 && TYPEINFO_NEWOBJECT_INSTRUCTION(set->td[i].info) == ins)
193                         {
194                                 TYPEINFO_INIT_CLASSINFO(set->td[i].info,initclass);
195                         }
196                 }
197         }
198 }
199
200 bool
201 typevector_merge(typevector *dst,typevector *y,int size)
202 {
203         bool changed = false;
204         
205         typedescriptor *a = dst->td;
206         typedescriptor *b = y->td;
207         while (size--) {
208                 if (a->type != TYPE_VOID && a->type != b->type) {
209                         a->type = TYPE_VOID;
210                         changed = true;
211                 }
212                 else if (a->type == TYPE_ADDRESS) {
213                         if (TYPEINFO_IS_PRIMITIVE(a->info)) {
214                                 /* 'a' is a returnAddress */
215                                 if (!TYPEINFO_IS_PRIMITIVE(b->info)
216                                         || (TYPEINFO_RETURNADDRESS(a->info)
217                                                 != TYPEINFO_RETURNADDRESS(b->info)))
218                                 {
219                                         a->type = TYPE_VOID;
220                                         changed = true;
221                                 }
222                         }
223                         else {
224                                 /* 'a' is a reference */
225                                 if (TYPEINFO_IS_PRIMITIVE(b->info)) {
226                                         a->type = TYPE_VOID;
227                                         changed = true;
228                                 }
229                                 else {
230                                         changed |= typeinfo_merge(&(a->info),&(b->info));
231                                 }
232                         }
233                 }
234                 a++;
235                 b++;
236         }
237         return changed;
238 }
239
240 bool typevector_separable_from(typevector *a,typevector *b,int size)
241 {
242         typedescriptor *tda = a->td;
243         typedescriptor *tdb = b->td;
244         for (;size--; tda++,tdb++) {
245                 if (TYPEDESC_IS_RETURNADDRESS(*tda)
246                         && TYPEDESC_IS_RETURNADDRESS(*tdb)
247                         && TYPEINFO_RETURNADDRESS(tda->info)
248                            != TYPEINFO_RETURNADDRESS(tdb->info))
249                         return true;
250         }
251         return false;
252 }
253
254 void
255 typevectorset_add(typevector *dst,typevector *v,int size)
256 {
257         while (dst->alt)
258                 dst = dst->alt;
259         dst->alt = DNEW_TYPEVECTOR(size);
260         memcpy(dst->alt,v,TYPEVECTOR_SIZE(size));
261         dst->alt->alt = NULL;
262         dst->alt->k = dst->k + 1;
263 }
264
265 typevector *
266 typevectorset_select(typevector **set,int retindex,void *retaddr)
267 {
268         typevector *selected;
269
270         if (!*set) return NULL;
271         
272         if (TYPEINFO_RETURNADDRESS((*set)->td[retindex].info) == retaddr) {
273                 selected = *set;
274                 *set = selected->alt;
275                 selected->alt = typevectorset_select(set,retindex,retaddr);
276         }
277         else {
278                 selected = typevectorset_select(&((*set)->alt),retindex,retaddr);
279         }
280         return selected;
281 }
282
283 bool
284 typevectorset_separable_with(typevector *set,typevector *add,int size)
285 {
286         int i;
287         typevector *v;
288         void *addr;
289         bool separable;
290
291         for (i=0; i<size; ++i) {
292                 if (!TYPEDESC_IS_RETURNADDRESS(add->td[i]))
293                         continue;
294                 addr = TYPEINFO_RETURNADDRESS(add->td[i].info);
295                 
296                 v = set;
297                 separable = false;
298                 do {
299                         if (!TYPEDESC_IS_RETURNADDRESS(v->td[i]))
300                                 goto next_index;
301                         if (TYPEINFO_RETURNADDRESS(v->td[i].info) != addr)
302                                 separable = true;
303                         v = v->alt;
304                         if (!v && separable) return true;
305                 } while (v);
306         next_index:
307         }
308         return false;
309 }
310
311 bool
312 typevectorset_collapse(typevector *dst,int size)
313 {
314         bool changed = false;
315         
316         while (dst->alt) {
317                 typevector_merge(dst,dst->alt,size);
318                 dst->alt = dst->alt->alt;
319                 changed = true;
320         }
321         return changed;
322 }
323
324 /**********************************************************************/
325 /* READ-ONLY FUNCTIONS                                                */
326 /* The following functions don't change typeinfo data.                */
327 /**********************************************************************/
328
329 bool
330 typeinfo_is_array(typeinfo *info)
331 {
332     return TYPEINFO_IS_ARRAY(*info);
333 }
334
335 bool
336 typeinfo_is_primitive_array(typeinfo *info,int arraytype)
337 {
338     return TYPEINFO_IS_PRIMITIVE_ARRAY(*info,arraytype);
339 }
340
341 bool
342 typeinfo_is_array_of_refs(typeinfo *info)
343 {
344     return TYPEINFO_IS_ARRAY_OF_REFS(*info);
345 }
346
347 static
348 bool
349 interface_extends_interface(classinfo *cls,classinfo *interf)
350 {
351     int i;
352     
353     /* first check direct superinterfaces */
354     for (i=0; i<cls->interfacescount; ++i) {
355         if (cls->interfaces[i] == interf)
356             return true;
357     }
358     
359     /* check indirect superinterfaces */
360     for (i=0; i<cls->interfacescount; ++i) {
361         if (interface_extends_interface(cls->interfaces[i],interf))
362             return true;
363     }
364     
365     return false;
366 }
367
368 static
369 bool
370 classinfo_implements_interface(classinfo *cls,classinfo *interf)
371 {
372     if (cls->flags & ACC_INTERFACE) {
373         /* cls is an interface */
374         if (cls == interf)
375             return true;
376
377         /* check superinterfaces */
378         return interface_extends_interface(cls,interf);
379     }
380
381     return CLASS_IMPLEMENTS_INTERFACE(cls,interf->index);
382 }
383
384 bool mergedlist_implements_interface(typeinfo_mergedlist *merged,
385                                      classinfo *interf)
386 {
387     int i;
388     classinfo **mlist;
389     
390     /* Check if there is an non-empty mergedlist. */
391     if (!merged)
392         return false;
393
394     /* If all classinfos in the (non-empty) merged array implement the
395      * interface return true, otherwise false.
396      */
397     mlist = merged->list;
398     i = merged->count;
399     while (i--) {
400         if (!classinfo_implements_interface(*mlist++,interf))
401             return false;
402     }
403     return true;
404 }
405
406 bool
407 merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged,
408                             classinfo *interf)
409 {
410     /* primitive types don't support interfaces. */
411     if (!typeclass)
412         return false;
413
414     /* the null type can be cast to any interface type. */
415     if (typeclass == pseudo_class_Null)
416         return true;
417
418     /* check if typeclass implements the interface. */
419     if (classinfo_implements_interface(typeclass,interf))
420         return true;
421
422     /* check the mergedlist */
423     return (merged && mergedlist_implements_interface(merged,interf));
424 }
425
426 bool
427 typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
428 {
429     /* DEBUG CHECK: dest must not have a merged list. */
430 #ifdef TYPEINFO_DEBUG
431     if (dest->merged)
432         panic("Internal error: typeinfo_is_assignable on merged destination.");
433 #endif
434
435         return typeinfo_is_assignable_to_classinfo(value,dest->typeclass);
436 }
437
438 bool
439 typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest)
440 {
441     classinfo *cls;
442
443     cls = value->typeclass;
444
445     /* assignments of primitive values are not checked here. */
446     if (!cls && !dest)
447         return true;
448
449     /* primitive and reference types are not assignment compatible. */
450     if (!cls || !dest)
451         return false;
452
453 #ifdef TYPEINFO_DEBUG
454     if (!dest->linked)
455         panic("Internal error: typeinfo_is_assignable_to_classinfo: unlinked class.");
456 #endif
457         
458     /* the null type can be assigned to any type */
459     if (TYPEINFO_IS_NULLTYPE(*value))
460         return true;
461
462     /* uninitialized objects are not assignable */
463     if (TYPEINFO_IS_NEWOBJECT(*value))
464         return false;
465
466     if (dest->flags & ACC_INTERFACE) {
467         /* We are assigning to an interface type. */
468         return merged_implements_interface(cls,value->merged,dest);
469     }
470
471     if (CLASS_IS_ARRAY(dest)) {
472                 arraydescriptor *arraydesc = dest->vftbl->arraydesc;
473                 int dimension = arraydesc->dimension;
474                 classinfo *elementclass = (arraydesc->elementvftbl)
475                         ? arraydesc->elementvftbl->class : NULL;
476                         
477         /* We are assigning to an array type. */
478         if (!TYPEINFO_IS_ARRAY(*value))
479             return false;
480
481         /* {Both value and dest are array types.} */
482
483         /* value must have at least the dimension of dest. */
484         if (value->dimension < dimension)
485             return false;
486
487         if (value->dimension > dimension) {
488             /* value has higher dimension so we need to check
489              * if its component array can be assigned to the
490              * element type of dest */
491
492                         if (!elementclass) return false;
493             
494             if (elementclass->flags & ACC_INTERFACE) {
495                 /* We are assigning to an interface type. */
496                 return classinfo_implements_interface(pseudo_class_Arraystub,
497                                                       elementclass);
498             }
499
500             /* We are assigning to a class type. */
501             return class_issubclass(pseudo_class_Arraystub,elementclass);
502         }
503
504         /* {value and dest have the same dimension} */
505
506         if (value->elementtype != arraydesc->elementtype)
507             return false;
508
509         if (value->elementclass) {
510             /* We are assigning an array of objects so we have to
511              * check if the elements are assignable.
512              */
513
514             if (elementclass->flags & ACC_INTERFACE) {
515                 /* We are assigning to an interface type. */
516
517                 return merged_implements_interface(value->elementclass,
518                                                    value->merged,
519                                                    elementclass);
520             }
521             
522             /* We are assigning to a class type. */
523             return class_issubclass(value->elementclass,elementclass);
524         }
525
526         return true;
527     }
528
529     /* {dest is not an array} */
530         
531     /* We are assigning to a class type */
532     if (cls->flags & ACC_INTERFACE)
533         cls = class_java_lang_Object;
534     
535     return class_issubclass(cls,dest);
536 }
537
538 /**********************************************************************/
539 /* INITIALIZATION FUNCTIONS                                           */
540 /* The following functions fill in uninitialized typeinfo structures. */
541 /**********************************************************************/
542
543 void
544 typeinfo_init_from_descriptor(typeinfo *info,char *utf_ptr,char *end_ptr)
545 {
546     classinfo *cls;
547     char *end;
548
549     cls = class_from_descriptor(utf_ptr,end_ptr,&end,
550                                                                 CLASSLOAD_NULLPRIMITIVE
551                                                                 | CLASSLOAD_NEW
552                                                                 | CLASSLOAD_NOVOID
553                                                                 | CLASSLOAD_CHECKEND);
554
555         if (cls)
556                 /* a class, interface or array descriptor */
557                 TYPEINFO_INIT_CLASSINFO(*info,cls);
558         else
559                 /* a primitive type */
560                 TYPEINFO_INIT_PRIMITIVE(*info);
561 }
562
563 int
564 typeinfo_count_method_args(utf *d,bool twoword)
565 {
566     int args = 0;
567     char *utf_ptr = d->text;
568     char *end_pos = utf_end(d);
569     char c;
570
571     /* method descriptor must start with parenthesis */
572     if (*utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
573
574         
575     /* check arguments */
576     while ((c = *utf_ptr) != ')') {
577                 class_from_descriptor(utf_ptr,end_pos,&utf_ptr,
578                                                           CLASSLOAD_SKIP | CLASSLOAD_NOVOID
579                                                           | CLASSLOAD_NULLPRIMITIVE);
580                 args++;
581                 if (twoword && (c == 'J' || c == 'D'))
582                         /* primitive two-word type */
583                         args++;
584     }
585
586     return args;
587 }
588
589 void
590 typeinfo_init_from_method_args(utf *desc,u1 *typebuf,typeinfo *infobuf,
591                                int buflen,bool twoword,
592                                int *returntype,typeinfo *returntypeinfo)
593 {
594     char *utf_ptr = desc->text;     /* current position in utf text   */
595     char *end_pos = utf_end(desc);  /* points behind utf string       */
596     int args = 0;
597     classinfo *cls;
598
599     /* method descriptor must start with parenthesis */
600     if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
601
602     /* check arguments */
603     while (utf_ptr != end_pos && *utf_ptr != ')') {
604                 if (++args > buflen)
605                         panic("Buffer too small for method arguments.");
606                 
607         *typebuf++ = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
608                                                                                   CLASSLOAD_NEW
609                                                                                   | CLASSLOAD_NULLPRIMITIVE
610                                                                                   | CLASSLOAD_NOVOID);
611                 
612                 if (cls)
613                         TYPEINFO_INIT_CLASSINFO(*infobuf,cls);
614                 else {
615                         TYPEINFO_INIT_PRIMITIVE(*infobuf);
616                 }
617                 infobuf++;
618
619                 if (twoword && (typebuf[-1] == TYPE_LONG || typebuf[-1] == TYPE_DOUBLE)) {
620                         if (++args > buflen)
621                                 panic("Buffer too small for method arguments.");
622                         *typebuf++ = TYPE_VOID;
623                         TYPEINFO_INIT_PRIMITIVE(*infobuf);
624                         infobuf++;
625                 }
626     }
627     utf_ptr++; /* skip ')' */
628
629     /* check returntype */
630     if (returntype) {
631                 *returntype = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
632                                                                                    CLASSLOAD_NULLPRIMITIVE
633                                                                                    | CLASSLOAD_NEW
634                                                                                    | CLASSLOAD_CHECKEND);
635                 if (returntypeinfo) {
636                         if (cls)
637                                 TYPEINFO_INIT_CLASSINFO(*returntypeinfo,cls);
638                         else
639                                 TYPEINFO_INIT_PRIMITIVE(*returntypeinfo);
640                 }
641         }
642 }
643
644 int
645 typedescriptors_init_from_method_args(typedescriptor *td,
646                                                                           utf *desc,
647                                                                           int buflen,bool twoword,
648                                                                           typedescriptor *returntype)
649 {
650     char *utf_ptr = desc->text;     /* current position in utf text   */
651     char *end_pos = utf_end(desc);  /* points behind utf string       */
652     int args = 0;
653     classinfo *cls;
654
655     /* method descriptor must start with parenthesis */
656     if (utf_ptr == end_pos || *utf_ptr++ != '(') panic ("Missing '(' in method descriptor");
657
658     /* check arguments */
659     while (utf_ptr != end_pos && *utf_ptr != ')') {
660                 if (++args > buflen)
661                         panic("Buffer too small for method arguments.");
662                 
663         td->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
664                                                                                 CLASSLOAD_NEW
665                                                                                 | CLASSLOAD_NULLPRIMITIVE
666                                                                                 | CLASSLOAD_NOVOID);
667                 
668                 if (cls)
669                         TYPEINFO_INIT_CLASSINFO(td->info,cls);
670                 else {
671                         TYPEINFO_INIT_PRIMITIVE(td->info);
672                 }
673                 td++;
674
675                 if (twoword && (td[-1].type == TYPE_LONG || td[-1].type == TYPE_DOUBLE)) {
676                         if (++args > buflen)
677                                 panic("Buffer too small for method arguments.");
678                         td->type = TYPE_VOID;
679                         TYPEINFO_INIT_PRIMITIVE(td->info);
680                         td++;
681                 }
682     }
683     utf_ptr++; /* skip ')' */
684
685     /* check returntype */
686     if (returntype) {
687                 returntype->type = type_from_descriptor(&cls,utf_ptr,end_pos,&utf_ptr,
688                                                                                                 CLASSLOAD_NULLPRIMITIVE
689                                                                                                 | CLASSLOAD_NEW
690                                                                                                 | CLASSLOAD_CHECKEND);
691                 if (cls)
692                         TYPEINFO_INIT_CLASSINFO(returntype->info,cls);
693                 else
694                         TYPEINFO_INIT_PRIMITIVE(returntype->info);
695         }
696         return args;
697 }
698
699 void
700 typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
701 {
702     vftbl *comp = NULL;
703
704     if (TYPEINFO_IS_NULLTYPE(*srcarray)) {
705         TYPEINFO_INIT_NULLTYPE(*dst);
706         return;
707     }
708     
709     if (!TYPEINFO_IS_ARRAY(*srcarray))
710         panic("Trying to access component of non-array");
711
712     comp = srcarray->typeclass->vftbl->arraydesc->componentvftbl;
713     if (comp) {
714         TYPEINFO_INIT_CLASSINFO(*dst,comp->class);
715     }
716     else {
717         TYPEINFO_INIT_PRIMITIVE(*dst);
718     }
719     
720     dst->merged = srcarray->merged;
721 }
722
723 void
724 typeinfo_clone(typeinfo *src,typeinfo *dest)
725 {
726     int count;
727     classinfo **srclist,**destlist;
728
729     if (src == dest)
730         return;
731     
732     *dest = *src;
733
734     if (src->merged) {
735         count = src->merged->count;
736         TYPEINFO_ALLOCMERGED(dest->merged,count);
737         dest->merged->count = count;
738
739         srclist = src->merged->list;
740         destlist = dest->merged->list;
741         while (count--)
742             *destlist++ = *srclist++;
743     }
744 }
745
746 /**********************************************************************/
747 /* MISCELLANEOUS FUNCTIONS                                            */
748 /**********************************************************************/
749
750 void
751 typeinfo_free(typeinfo *info)
752 {
753     TYPEINFO_FREEMERGED_IF_ANY(info->merged);
754     info->merged = NULL;
755 }
756
757 /**********************************************************************/
758 /* MERGING FUNCTIONS                                                  */
759 /* The following functions are used to merge the types represented by */
760 /* two typeinfo structures into one typeinfo structure.               */
761 /**********************************************************************/
762
763 static
764 void
765 typeinfo_merge_error(char *str,typeinfo *x,typeinfo *y) {
766 #ifdef TYPEINFO_DEBUG
767     fprintf(stderr,"Error in typeinfo_merge: %s\n",str);
768     fprintf(stderr,"Typeinfo x:\n");
769     typeinfo_print(stderr,x,1);
770     fprintf(stderr,"Typeinfo y:\n");
771     typeinfo_print(stderr,y,1);
772 #endif
773     panic(str);
774 }
775
776 /* Condition: clsx != clsy. */
777 /* Returns: true if dest was changed (always true). */
778 static
779 bool
780 typeinfo_merge_two(typeinfo *dest,classinfo *clsx,classinfo *clsy)
781 {
782     TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
783     TYPEINFO_ALLOCMERGED(dest->merged,2);
784     dest->merged->count = 2;
785
786 #ifdef TYPEINFO_DEBUG
787     if (clsx == clsy)
788         panic("Internal error: typeinfo_merge_two called with clsx==clsy.");
789 #endif
790
791     if (clsx < clsy) {
792         dest->merged->list[0] = clsx;
793         dest->merged->list[1] = clsy;
794     }
795     else {
796         dest->merged->list[0] = clsy;
797         dest->merged->list[1] = clsx;
798     }
799
800     return true;
801 }
802
803 /* Returns: true if dest was changed. */
804 static
805 bool
806 typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classinfo *cls)
807 {
808     int count;
809     typeinfo_mergedlist *newmerged;
810     classinfo **mlist,**newlist;
811
812     count = m->count;
813     mlist = m->list;
814
815     /* Check if cls is already in the mergedlist m. */
816     while (count--) {
817         if (*mlist++ == cls) {
818             /* cls is in the list, so m is the resulting mergedlist */
819             if (dest->merged == m)
820                 return false;
821
822             /* We have to copy the mergedlist */
823             TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
824             count = m->count;
825             TYPEINFO_ALLOCMERGED(dest->merged,count);
826             dest->merged->count = count;
827             newlist = dest->merged->list;
828             mlist = m->list;
829             while (count--) {
830                 *newlist++ = *mlist++;
831             }
832             return true;
833         }
834     }
835
836     /* Add cls to the mergedlist. */
837     count = m->count;
838     TYPEINFO_ALLOCMERGED(newmerged,count+1);
839     newmerged->count = count+1;
840     newlist = newmerged->list;    
841     mlist = m->list;
842     while (count) {
843         if (*mlist > cls)
844             break;
845         *newlist++ = *mlist++;
846         count--;
847     }
848     *newlist++ = cls;
849     while (count--) {
850         *newlist++ = *mlist++;
851     }
852
853     /* Put the new mergedlist into dest. */
854     TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
855     dest->merged = newmerged;
856     
857     return true;
858 }
859
860 /* Returns: true if dest was changed. */
861 static
862 bool
863 typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
864                            typeinfo_mergedlist *y)
865 {
866     int count = 0;
867     int countx,county;
868     typeinfo_mergedlist *temp,*result;
869     classinfo **clsx,**clsy,**newlist;
870
871     /* count the elements that will be in the resulting list */
872     /* (Both lists are sorted, equal elements are counted only once.) */
873     clsx = x->list;
874     clsy = y->list;
875     countx = x->count;
876     county = y->count;
877     while (countx && county) {
878         if (*clsx == *clsy) {
879             clsx++;
880             clsy++;
881             countx--;
882             county--;
883         }
884         else if (*clsx < *clsy) {
885             clsx++;
886             countx--;
887         }
888         else {
889             clsy++;
890             county--;
891         }
892         count++;
893     }
894     count += countx + county;
895
896     /* {The new mergedlist will have count entries.} */
897
898     if ((x->count != count) && (y->count == count)) {
899         temp = x; x = y; y = temp;
900     }
901     /* {If one of x,y is already the result it is x.} */
902     if (x->count == count) {
903         /* x->merged is equal to the result */
904         if (x == dest->merged)
905             return false;
906
907         if (!dest->merged || dest->merged->count != count) {
908             TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
909             TYPEINFO_ALLOCMERGED(dest->merged,count);
910             dest->merged->count = count;
911         }
912
913         newlist = dest->merged->list;
914         clsx = x->list;
915         while (count--) {
916             *newlist++ = *clsx++;
917         }
918         return true;
919     }
920
921     /* {We have to merge two lists.} */
922
923     /* allocate the result list */
924     TYPEINFO_ALLOCMERGED(result,count);
925     result->count = count;
926     newlist = result->list;
927
928     /* merge the sorted lists */
929     clsx = x->list;
930     clsy = y->list;
931     countx = x->count;
932     county = y->count;
933     while (countx && county) {
934         if (*clsx == *clsy) {
935             *newlist++ = *clsx++;
936             clsy++;
937             countx--;
938             county--;
939         }
940         else if (*clsx < *clsy) {
941             *newlist++ = *clsx++;
942             countx--;
943         }
944         else {
945             *newlist++ = *clsy++;
946             county--;
947         }
948     }
949     while (countx--)
950             *newlist++ = *clsx++;
951     while (county--)
952             *newlist++ = *clsy++;
953
954     /* replace the list in dest with the result list */
955     TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
956     dest->merged = result;
957
958     return true;
959 }
960
961 static
962 bool
963 typeinfo_merge_nonarrays(typeinfo *dest,
964                          classinfo **result,
965                          classinfo *clsx,classinfo *clsy,
966                          typeinfo_mergedlist *mergedx,
967                          typeinfo_mergedlist *mergedy)
968 {
969     classinfo *tcls,*common;
970     typeinfo_mergedlist *tmerged;
971     bool changed;
972
973     /* DEBUG */
974     /*
975 #ifdef TYPEINFO_DEBUG
976     typeinfo dbgx,dbgy;
977     printf("typeinfo_merge_nonarrays:\n");
978     TYPEINFO_INIT_CLASSINFO(dbgx,clsx);
979     dbgx.merged = mergedx;
980     TYPEINFO_INIT_CLASSINFO(dbgy,clsy);
981     dbgy.merged = mergedy;
982     typeinfo_print(stdout,&dbgx,4);
983     printf("  with:\n");
984     typeinfo_print(stdout,&dbgy,4);
985 #endif
986     */ 
987
988     /* Common case: clsx == clsy */
989     /* (This case is very simple unless *both* x and y really represent
990      *  merges of subclasses of clsx==clsy.)
991      */
992     if ((clsx == clsy) && (!mergedx || !mergedy)) {
993   return_simple_x:
994         /* DEBUG */ /* log_text("return simple x"); */
995         changed = (dest->merged != NULL);
996         TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
997         dest->merged = NULL;
998         *result = clsx;
999         /* DEBUG */ /* log_text("returning"); */
1000         return changed;
1001     }
1002     
1003     /* If clsy is an interface, swap x and y. */
1004     if (clsy->flags & ACC_INTERFACE) {
1005         tcls = clsx; clsx = clsy; clsy = tcls;
1006         tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1007     }
1008     /* {We know: If only one of x,y is an interface it is x.} */
1009
1010     /* Handle merging of interfaces: */
1011     if (clsx->flags & ACC_INTERFACE) {
1012         /* {clsx is an interface and mergedx == NULL.} */
1013         
1014         if (clsy->flags & ACC_INTERFACE) {
1015             /* We are merging two interfaces. */
1016             /* {mergedy == NULL} */
1017
1018             /* {We know that clsx!=clsy (see common case at beginning.)} */
1019             *result = class_java_lang_Object;
1020             return typeinfo_merge_two(dest,clsx,clsy);
1021         }
1022
1023         /* {We know: x is an interface, clsy is a class.} */
1024
1025         /* Check if we are merging an interface with java.lang.Object */
1026         if (clsy == class_java_lang_Object && !mergedy) {
1027             clsx = clsy;
1028             goto return_simple_x;
1029         }
1030             
1031
1032         /* If the type y implements clsx then the result of the merge
1033          * is clsx regardless of mergedy.
1034          */
1035         
1036         if (CLASS_IMPLEMENTS_INTERFACE(clsy,clsx->index)
1037             || mergedlist_implements_interface(mergedy,clsx))
1038         {
1039             /* y implements x, so the result of the merge is x. */
1040             goto return_simple_x;
1041         }
1042         
1043         /* {We know: x is an interface, the type y a class or a merge
1044          * of subclasses and does not implement x.} */
1045
1046         /* There may still be superinterfaces of x which are implemented
1047          * by y, too, so we have to add clsx to the mergedlist.
1048          */
1049
1050         /* if x has no superinterfaces we could return a simple java.lang.Object */
1051         
1052         common = class_java_lang_Object;
1053         goto merge_with_simple_x;
1054     }
1055
1056     /* {We know: x and y are classes (not interfaces).} */
1057     
1058     /* If *x is deeper in the inheritance hierarchy swap x and y. */
1059     if (clsx->index > clsy->index) {
1060         tcls = clsx; clsx = clsy; clsy = tcls;
1061         tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1062     }
1063
1064     /* {We know: y is at least as deep in the hierarchy as x.} */
1065
1066     /* Find nearest common anchestor for the classes. */
1067     common = clsx;
1068     tcls = clsy;
1069     while (tcls->index > common->index)
1070         tcls = tcls->super;
1071     while (common != tcls) {
1072         common = common->super;
1073         tcls = tcls->super;
1074     }
1075
1076     /* {common == nearest common anchestor of clsx and clsy.} */
1077
1078     /* If clsx==common and x is a whole class (not a merge of subclasses)
1079      * then the result of the merge is clsx.
1080      */
1081     if (clsx == common && !mergedx) {
1082         goto return_simple_x;
1083     }
1084    
1085     if (mergedx) {
1086         *result = common;
1087         if (mergedy)
1088             return typeinfo_merge_mergedlists(dest,mergedx,mergedy);
1089         else
1090             return typeinfo_merge_add(dest,mergedx,clsy);
1091     }
1092
1093  merge_with_simple_x:
1094     *result = common;
1095     if (mergedy)
1096         return typeinfo_merge_add(dest,mergedy,clsx);
1097     else
1098         return typeinfo_merge_two(dest,clsx,clsy);
1099 }
1100
1101 /* Condition: *dest must be a valid initialized typeinfo. */
1102 /* Condition: dest != y. */
1103 /* Returns: true if dest was changed. */
1104 bool
1105 typeinfo_merge(typeinfo *dest,typeinfo* y)
1106 {
1107     typeinfo *x;
1108     typeinfo *tmp;                      /* used for swapping */
1109     classinfo *common;
1110     classinfo *elementclass;
1111     int dimension;
1112     int elementtype;
1113     bool changed;
1114
1115     /* DEBUG */
1116     /*
1117 #ifdef TYPEINFO_DEBUG
1118     typeinfo_print(stdout,dest,4);
1119     typeinfo_print(stdout,y,4);
1120 #endif
1121     */
1122
1123     /* Merging something with itself is a nop */
1124     if (dest == y)
1125         return false;
1126
1127     /* Merging two returnAddress types is ok. */
1128     if (!dest->typeclass && !y->typeclass) {
1129 #ifdef TYPEINFO_DEBUG
1130                 if (TYPEINFO_RETURNADDRESS(*dest) != TYPEINFO_RETURNADDRESS(*y))
1131                         panic("Internal error: typeinfo_merge merges different returnAddresses");
1132 #endif
1133         return false;
1134         }
1135     
1136     /* Primitive types cannot be merged with reference types */
1137         /* XXX only check this in debug mode? */
1138     if (!dest->typeclass || !y->typeclass)
1139         typeinfo_merge_error("Trying to merge primitive types.",dest,y);
1140
1141 #ifdef TYPEINFO_DEBUG
1142     /* check that no unlinked classes are merged. */
1143     if (!dest->typeclass->linked || !y->typeclass->linked)
1144         typeinfo_merge_error("Trying to merge unlinked class(es).",dest,y);
1145 #endif
1146
1147     /* handle uninitialized object types */
1148     /* XXX is there a way we could put this after the common case? */
1149     if (TYPEINFO_IS_NEWOBJECT(*dest) || TYPEINFO_IS_NEWOBJECT(*y)) {
1150         if (!TYPEINFO_IS_NEWOBJECT(*dest) || !TYPEINFO_IS_NEWOBJECT(*y))
1151             typeinfo_merge_error("Trying to merge uninitialized object type.",dest,y);
1152         if (TYPEINFO_NEWOBJECT_INSTRUCTION(*dest)
1153             != TYPEINFO_NEWOBJECT_INSTRUCTION(*y))
1154             typeinfo_merge_error("Trying to merge different uninitialized objects.",dest,y);
1155         return false;
1156     }
1157     
1158     /* DEBUG */ /* log_text("Testing common case"); */
1159
1160     /* Common case: class dest == class y */
1161     /* (This case is very simple unless *both* dest and y really represent
1162      *  merges of subclasses of class dest==class y.)
1163      */
1164     if ((dest->typeclass == y->typeclass) && (!dest->merged || !y->merged)) {
1165         changed = (dest->merged != NULL);
1166         TYPEINFO_FREEMERGED_IF_ANY(dest->merged); /* unify if? */
1167         dest->merged = NULL;
1168         /* DEBUG */ /* log_text("common case handled"); */
1169         return changed;
1170     }
1171     
1172     /* DEBUG */ /* log_text("Handling null types"); */
1173
1174     /* Handle null types: */
1175     if (TYPEINFO_IS_NULLTYPE(*y)) {
1176         return false;
1177     }
1178     if (TYPEINFO_IS_NULLTYPE(*dest)) {
1179         TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1180         TYPEINFO_CLONE(*y,*dest);
1181         return true;
1182     }
1183
1184     /* This function uses x internally, so x and y can be swapped
1185      * without changing dest. */
1186     x = dest;
1187     changed = false;
1188     
1189     /* Handle merging of arrays: */
1190     if (TYPEINFO_IS_ARRAY(*x) && TYPEINFO_IS_ARRAY(*y)) {
1191         
1192         /* DEBUG */ /* log_text("Handling arrays"); */
1193
1194         /* Make x the one with lesser dimension */
1195         if (x->dimension > y->dimension) {
1196             tmp = x; x = y; y = tmp;
1197         }
1198
1199         /* If one array (y) has higher dimension than the other,
1200          * interpret it as an array (same dim. as x) of Arraystubs. */
1201         if (x->dimension < y->dimension) {
1202             dimension = x->dimension;
1203             elementtype = ARRAYTYPE_OBJECT;
1204             elementclass = pseudo_class_Arraystub;
1205         }
1206         else {
1207             dimension = y->dimension;
1208             elementtype = y->elementtype;
1209             elementclass = y->elementclass;
1210         }
1211         
1212         /* {The arrays are of the same dimension.} */
1213         
1214         if (x->elementtype != elementtype) {
1215             /* Different element types are merged, so the resulting array
1216              * type has one accessible dimension less. */
1217             if (--dimension == 0) {
1218                 common = pseudo_class_Arraystub;
1219                 elementtype = 0;
1220                 elementclass = NULL;
1221             }
1222             else {
1223                 common = class_multiarray_of(dimension,pseudo_class_Arraystub);
1224                 elementtype = ARRAYTYPE_OBJECT;
1225                 elementclass = pseudo_class_Arraystub;
1226             }
1227         }
1228         else {
1229             /* {The arrays have the same dimension and elementtype.} */
1230
1231             if (elementtype == ARRAYTYPE_OBJECT) {
1232                 /* The elements are references, so their respective
1233                  * types must be merged.
1234                  */
1235                 changed |= typeinfo_merge_nonarrays(dest,
1236                                                     &elementclass,
1237                                                     x->elementclass,
1238                                                     elementclass,
1239                                                     x->merged,y->merged);
1240
1241                 /* DEBUG */ /* log_text("finding resulting array class: "); */
1242                 common = class_multiarray_of(dimension,elementclass);
1243                 /* DEBUG */ /* utf_display(common->name); printf("\n"); */
1244             }
1245         }
1246     }
1247     else {
1248         /* {We know that at least one of x or y is no array, so the
1249          *  result cannot be an array.} */
1250         
1251         changed |= typeinfo_merge_nonarrays(dest,
1252                                             &common,
1253                                             x->typeclass,y->typeclass,
1254                                             x->merged,y->merged);
1255
1256         dimension = 0;
1257         elementtype = 0;
1258         elementclass = NULL;
1259     }
1260
1261     /* Put the new values into dest if neccessary. */
1262
1263     if (dest->typeclass != common) {
1264         dest->typeclass = common;
1265         changed = true;
1266     }
1267     if (dest->dimension != dimension) {
1268         dest->dimension = dimension;
1269         changed = true;
1270     }
1271     if (dest->elementtype != elementtype) {
1272         dest->elementtype = elementtype;
1273         changed = true;
1274     }
1275     if (dest->elementclass != elementclass) {
1276         dest->elementclass = elementclass;
1277         changed = true;
1278     }
1279
1280     /* DEBUG */ /* log_text("returning from merge"); */
1281     
1282     return changed;
1283 }
1284
1285
1286 /**********************************************************************/
1287 /* DEBUGGING HELPERS                                                  */
1288 /**********************************************************************/
1289
1290 #ifdef TYPEINFO_DEBUG
1291
1292 #include "tables.h"
1293 #include "loader.h"
1294 #include "jit/jit.h"
1295
1296 extern instruction *instr;
1297
1298 static int
1299 typeinfo_test_compare(classinfo **a,classinfo **b)
1300 {
1301     if (*a == *b) return 0;
1302     if (*a < *b) return -1;
1303     return +1;
1304 }
1305
1306 static void
1307 typeinfo_test_parse(typeinfo *info,char *str)
1308 {
1309     int num;
1310     int i;
1311     typeinfo *infobuf;
1312     u1 *typebuf;
1313     int returntype;
1314     utf *desc = utf_new_char(str);
1315     
1316     num = typeinfo_count_method_args(desc,false);
1317     if (num) {
1318         typebuf = DMNEW(u1,num);
1319         infobuf = DMNEW(typeinfo,num);
1320         
1321         typeinfo_init_from_method_args(desc,typebuf,infobuf,num,false,
1322                                        &returntype,info);
1323
1324         TYPEINFO_ALLOCMERGED(info->merged,num);
1325         info->merged->count = num;
1326
1327         for (i=0; i<num; ++i) {
1328             if (typebuf[i] != TYPE_ADDRESS)
1329                 panic("non-reference type in mergedlist");
1330             info->merged->list[i] = infobuf[i].typeclass;
1331         }
1332         qsort(info->merged->list,num,sizeof(classinfo*),
1333               (int(*)(const void *,const void *))&typeinfo_test_compare);
1334     }
1335     else {
1336         typeinfo_init_from_method_args(desc,NULL,NULL,0,false,
1337                                        &returntype,info);
1338     }
1339 }
1340
1341 #define TYPEINFO_TEST_BUFLEN  4000
1342
1343 static bool
1344 typeinfo_equal(typeinfo *x,typeinfo *y)
1345 {
1346     int i;
1347     
1348     if (x->typeclass != y->typeclass) return false;
1349     if (x->dimension != y->dimension) return false;
1350     if (x->dimension) {
1351         if (x->elementclass != y->elementclass) return false;
1352         if (x->elementtype != y->elementtype) return false;
1353     }
1354
1355     if (TYPEINFO_IS_NEWOBJECT(*x))
1356         if (TYPEINFO_NEWOBJECT_INSTRUCTION(*x)
1357             != TYPEINFO_NEWOBJECT_INSTRUCTION(*y))
1358             return false;
1359
1360     if (x->merged || y->merged) {
1361         if (!(x->merged && y->merged)) return false;
1362         if (x->merged->count != y->merged->count) return false;
1363         for (i=0; i<x->merged->count; ++i)
1364             if (x->merged->list[i] != y->merged->list[i])
1365                 return false;
1366     }
1367     return true;
1368 }
1369
1370 static void
1371 typeinfo_testmerge(typeinfo *a,typeinfo *b,typeinfo *result,int *failed)
1372 {
1373     typeinfo dest;
1374     bool changed,changed_should_be;
1375
1376     TYPEINFO_CLONE(*a,dest);
1377     
1378     printf("\n          ");
1379     typeinfo_print_short(stdout,&dest);
1380     printf("\n          ");
1381     typeinfo_print_short(stdout,b);
1382     printf("\n");
1383
1384     changed = (typeinfo_merge(&dest,b)) ? 1 : 0;
1385     changed_should_be = (!typeinfo_equal(&dest,a)) ? 1 : 0;
1386
1387     printf("          %s\n",(changed) ? "changed" : "=");
1388
1389     if (typeinfo_equal(&dest,result)) {
1390         printf("OK        ");
1391         typeinfo_print_short(stdout,&dest);
1392         printf("\n");
1393         if (changed != changed_should_be) {
1394             printf("WRONG RETURN VALUE!\n");
1395             (*failed)++;
1396         }
1397     }
1398     else {
1399         printf("RESULT    ");
1400         typeinfo_print_short(stdout,&dest);
1401         printf("\n");
1402         printf("SHOULD BE ");
1403         typeinfo_print_short(stdout,result);
1404         printf("\n");
1405         (*failed)++;
1406     }
1407 }
1408
1409 static void
1410 typeinfo_inc_dimension(typeinfo *info)
1411 {
1412     if (info->dimension++ == 0) {
1413         info->elementtype = ARRAYTYPE_OBJECT;
1414         info->elementclass = info->typeclass;
1415     }
1416     info->typeclass = class_array_of(info->typeclass);
1417 }
1418
1419 #define TYPEINFO_TEST_MAXDIM  10
1420
1421 static void
1422 typeinfo_testrun(char *filename)
1423 {
1424     char buf[TYPEINFO_TEST_BUFLEN];
1425     char bufa[TYPEINFO_TEST_BUFLEN];
1426     char bufb[TYPEINFO_TEST_BUFLEN];
1427     char bufc[TYPEINFO_TEST_BUFLEN];
1428     typeinfo a,b,c;
1429     int maxdim;
1430     int failed = 0;
1431     FILE *file = fopen(filename,"rt");
1432         int res;
1433     
1434     if (!file)
1435         panic("could not open typeinfo test file");
1436
1437     while (fgets(buf,TYPEINFO_TEST_BUFLEN,file)) {
1438         if (buf[0] == '#' || !strlen(buf))
1439             continue;
1440         
1441         res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc);
1442         if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc))
1443             panic("Invalid line in typeinfo test file (none of empty, comment or test)");
1444
1445         typeinfo_test_parse(&a,bufa);
1446         typeinfo_test_parse(&b,bufb);
1447         typeinfo_test_parse(&c,bufc);
1448         do {
1449             typeinfo_testmerge(&a,&b,&c,&failed); /* check result */
1450             typeinfo_testmerge(&b,&a,&c,&failed); /* check commutativity */
1451
1452             if (TYPEINFO_IS_NULLTYPE(a)) break;
1453             if (TYPEINFO_IS_NULLTYPE(b)) break;
1454             if (TYPEINFO_IS_NULLTYPE(c)) break;
1455             
1456             maxdim = a.dimension;
1457             if (b.dimension > maxdim) maxdim = b.dimension;
1458             if (c.dimension > maxdim) maxdim = c.dimension;
1459
1460             if (maxdim < TYPEINFO_TEST_MAXDIM) {
1461                 typeinfo_inc_dimension(&a);
1462                 typeinfo_inc_dimension(&b);
1463                 typeinfo_inc_dimension(&c);
1464             }
1465         } while (maxdim < TYPEINFO_TEST_MAXDIM);
1466     }
1467
1468     fclose(file);
1469
1470     if (failed) {
1471         fprintf(stderr,"Failed typeinfo_merge tests: %d\n",failed);
1472         panic("Failed test");
1473     }
1474 }
1475
1476 void
1477 typeinfo_test()
1478 {
1479     log_text("Running typeinfo test file...");
1480     typeinfo_testrun("typeinfo.tst");
1481     log_text("Finished typeinfo test file.");
1482 }
1483
1484 void
1485 typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc)
1486 {
1487     typeinfo_init_from_descriptor(info,desc,desc+strlen(desc));
1488 }
1489
1490 #define TYPEINFO_MAXINDENT  80
1491
1492 void
1493 typeinfo_print(FILE *file,typeinfo *info,int indent)
1494 {
1495     int i;
1496     char ind[TYPEINFO_MAXINDENT + 1];
1497     instruction *ins;
1498         basicblock *bptr;
1499
1500     if (indent > TYPEINFO_MAXINDENT) indent = TYPEINFO_MAXINDENT;
1501     
1502     for (i=0; i<indent; ++i)
1503         ind[i] = ' ';
1504     ind[i] = (char) 0;
1505     
1506     if (TYPEINFO_IS_PRIMITIVE(*info)) {
1507                 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
1508                 if (bptr)
1509                         fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->debug_nr);
1510                 else
1511                         fprintf(file,"%sprimitive\n",ind);
1512         return;
1513     }
1514     
1515     if (TYPEINFO_IS_NULLTYPE(*info)) {
1516         fprintf(file,"%snull\n",ind);
1517         return;
1518     }
1519
1520     if (TYPEINFO_IS_NEWOBJECT(*info)) {
1521         ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
1522         if (ins) {
1523             fprintf(file,"%sNEW(%d):",ind,ins-instr);
1524             utf_fprint(file,((classinfo *)ins[-1].val.a)->name);
1525             fprintf(file,"\n");
1526         }
1527         else {
1528             fprintf(file,"%sNEW(this)",ind);
1529         }
1530         return;
1531     }
1532
1533     fprintf(file,"%sClass:      ",ind);
1534     utf_fprint(file,info->typeclass->name);
1535     fprintf(file,"\n");
1536
1537     if (TYPEINFO_IS_ARRAY(*info)) {
1538         fprintf(file,"%sDimension:    %d",ind,(int)info->dimension);
1539         fprintf(file,"\n%sElements:     ",ind);
1540         switch (info->elementtype) {
1541           case ARRAYTYPE_INT     : fprintf(file,"int\n"); break;
1542           case ARRAYTYPE_LONG    : fprintf(file,"long\n"); break;
1543           case ARRAYTYPE_FLOAT   : fprintf(file,"float\n"); break;
1544           case ARRAYTYPE_DOUBLE  : fprintf(file,"double\n"); break;
1545           case ARRAYTYPE_BYTE    : fprintf(file,"byte\n"); break;
1546           case ARRAYTYPE_CHAR    : fprintf(file,"char\n"); break;
1547           case ARRAYTYPE_SHORT   : fprintf(file,"short\n"); break;
1548           case ARRAYTYPE_BOOLEAN : fprintf(file,"boolean\n"); break;
1549               
1550           case ARRAYTYPE_OBJECT:
1551               fprintf(file,"reference: ");
1552               utf_fprint(file,info->elementclass->name);
1553               fprintf(file,"\n");
1554               break;
1555               
1556           default:
1557               fprintf(file,"INVALID ARRAYTYPE!\n");
1558         }
1559     }
1560
1561     if (info->merged) {
1562         fprintf(file,"%sMerged: ",ind);
1563         for (i=0; i<info->merged->count; ++i) {
1564             if (i) fprintf(file,", ");
1565             utf_fprint(file,info->merged->list[i]->name);
1566         }
1567         fprintf(file,"\n");
1568     }
1569 }
1570
1571 void
1572 typeinfo_print_short(FILE *file,typeinfo *info)
1573 {
1574     int i;
1575     instruction *ins;
1576         basicblock *bptr;
1577
1578     if (TYPEINFO_IS_PRIMITIVE(*info)) {
1579                 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
1580                 if (bptr)
1581                         fprintf(file,"ret(L%03d)",bptr->debug_nr);
1582                 else
1583                         fprintf(file,"primitive");
1584         return;
1585     }
1586     
1587     if (TYPEINFO_IS_NULLTYPE(*info)) {
1588         fprintf(file,"null");
1589         return;
1590     }
1591     
1592     if (TYPEINFO_IS_NEWOBJECT(*info)) {
1593         ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
1594         if (ins) {
1595             fprintf(file,"NEW(%d):",ins-instr);
1596             utf_fprint(file,((classinfo *)ins[-1].val.a)->name);
1597         }
1598         else
1599             fprintf(file,"NEW(this)");
1600         return;
1601     }
1602
1603     utf_fprint(file,info->typeclass->name);
1604
1605     if (info->merged) {
1606         fprintf(file,"{");
1607         for (i=0; i<info->merged->count; ++i) {
1608             if (i) fprintf(file,",");
1609             utf_fprint(file,info->merged->list[i]->name);
1610         }
1611         fprintf(file,"}");
1612     }
1613 }
1614
1615 void
1616 typeinfo_print_type(FILE *file,int type,typeinfo *info)
1617 {
1618     switch (type) {
1619       case TYPE_VOID:   fprintf(file,"V"); break;
1620       case TYPE_INT:    fprintf(file,"I"); break;
1621       case TYPE_FLOAT:  fprintf(file,"F"); break;
1622       case TYPE_DOUBLE: fprintf(file,"D"); break;
1623       case TYPE_LONG:   fprintf(file,"J"); break;
1624       case TYPE_ADDRESS:
1625                   typeinfo_print_short(file,info);
1626           break;
1627           
1628       default:
1629           fprintf(file,"!");
1630     }
1631 }
1632
1633 void
1634 typeinfo_print_stacktype(FILE *file,int type,typeinfo *info)
1635 {
1636         if (type == TYPE_ADDRESS && TYPEINFO_IS_PRIMITIVE(*info)) {     
1637                 typeinfo_retaddr_set *set = (typeinfo_retaddr_set*)
1638                         TYPEINFO_RETURNADDRESS(*info);
1639                 fprintf(file,"ret(L%03d",((basicblock*)(set->addr))->debug_nr);
1640                 set = set->alt;
1641                 while (set) {
1642                         fprintf(file,"|L%03d",((basicblock*)(set->addr))->debug_nr);
1643                         set = set->alt;
1644                 }
1645                 fprintf(file,")");
1646         }
1647         else
1648                 typeinfo_print_type(file,type,info);
1649 }
1650
1651 void
1652 typedescriptor_print(FILE *file,typedescriptor *td)
1653 {
1654         typeinfo_print_type(file,td->type,&(td->info));
1655 }
1656
1657 void
1658 typevector_print(FILE *file,typevector *vec,int size)
1659 {
1660     int i;
1661
1662         fprintf(file,"[%d]",vec->k);
1663     for (i=0; i<size; ++i) {
1664                 fprintf(file," %d=",i);
1665         typedescriptor_print(file,vec->td + i);
1666     }
1667 }
1668
1669 void
1670 typevectorset_print(FILE *file,typevector *set,int size)
1671 {
1672     int i;
1673         typevector *vec;
1674
1675         fprintf(file,"[%d",set->k);
1676         vec = set->alt;
1677         while (vec) {
1678                 fprintf(file,"|%d",vec->k);
1679                 vec = vec->alt;
1680         }
1681         fprintf(file,"]");
1682         
1683     for (i=0; i<size; ++i) {
1684                 fprintf(file," %d=",i);
1685         typedescriptor_print(file,set->td + i);
1686                 vec = set->alt;
1687                 while (vec) {
1688                         fprintf(file,"|");
1689                         typedescriptor_print(file,vec->td + i);
1690                         vec = vec->alt;
1691                 }
1692     }
1693 }
1694
1695 #endif /* TYPEINFO_DEBUG */
1696
1697
1698 /*
1699  * These are local overrides for various environment variables in Emacs.
1700  * Please do not remove this and leave it at the end of the file, where
1701  * Emacs will automagically detect them.
1702  * ---------------------------------------------------------------------
1703  * Local variables:
1704  * mode: c
1705  * indent-tabs-mode: t
1706  * c-basic-offset: 4
1707  * tab-width: 4
1708  * End:
1709  */