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