* Time for -Werror
[cacao.git] / src / vm / jit / verify / typeinfo.c
1 /* src/vm/jit/verify/typeinfo.c - type system used by the type checker
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
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 2803 2005-06-23 13:19:41Z twisti $
30
31 */
32
33 #include <assert.h>
34 #include <string.h>
35
36 #include "mm/memory.h"
37 #include "toolbox/logging.h"
38 #include "vm/class.h"
39 #include "vm/loader.h"
40 #include "vm/tables.h"
41 #include "vm/jit/jit.h"
42 #include "vm/jit/verify/typeinfo.h"
43 #include "vm/descriptor.h"
44 #include "vm/resolve.h"
45
46
47 /* check if a linked class is an array class. Only use for linked classes! */
48 #define CLASSINFO_IS_ARRAY(clsinfo)  ((clsinfo)->vftbl->arraydesc != NULL)
49
50 #define CLASSINFO_IMPLEMENTS_INTERFACE(cls,index)                   \
51     ( ((index) < (cls)->vftbl->interfacetablelength)            \
52       && (VFTBLINTERFACETABLE((cls)->vftbl,(index)) != NULL) )
53
54 /******************************************************************************/
55 /* DEBUG HELPERS                                                              */
56 /******************************************************************************/
57
58 #ifdef TYPEINFO_DEBUG
59 #define TYPEINFO_ASSERT(cond)  assert(cond)
60 #else
61 #define TYPEINFO_ASSERT(cond)
62 #endif
63
64 /**********************************************************************/
65 /* TYPEVECTOR FUNCTIONS                                               */
66 /**********************************************************************/
67
68 /* typevectorset_copy **********************************************************
69  
70    Return a copy of the given typevector set.
71   
72    IN:
73            src..............typevector set to copy, must be != NULL
74            k................k-index to set in first typevector of resulting set
75            size.............number of elements per typevector
76
77    RETURN VALUE:
78        a pointer to the new typevector set
79
80    NOTE:
81        This function recursively invokes itself with increasing k-index to
82            copy the alternative typevectors in the given set.
83
84 *******************************************************************************/
85
86 typevector *
87 typevectorset_copy(typevector *src,int k,int size)
88 {
89         typevector *dst = DNEW_TYPEVECTOR(size);
90         
91         TYPEINFO_ASSERT(src);
92         
93         memcpy(dst,src,TYPEVECTOR_SIZE(size));
94         dst->k = k;
95         if (src->alt)
96                 dst->alt = typevectorset_copy(src->alt,k+1,size);
97         return dst;
98 }
99
100 /* typevectorset_checktype *****************************************************
101  
102    Check if all typevectors contain a given type at a given index.
103   
104    IN:
105            vec..............typevector set, must be != NULL
106            index............index of component to check
107            type.............TYPE_* constant to check against
108
109    RETURN VALUE:
110        true if all typevectors in the set contain TYPE at INDEX,
111            false otherwise
112
113 *******************************************************************************/
114
115 bool
116 typevectorset_checktype(typevector *vec,int index,int type)
117 {
118         TYPEINFO_ASSERT(vec);
119         do {
120                 if (vec->td[index].type != type)
121                         return false;
122         } while ((vec = vec->alt) != NULL);
123         return true;
124 }
125
126 /* typevectorset_checkreference ************************************************
127  
128    Check if all typevectors contain a reference at a given index.
129   
130    IN:
131            vec..............typevector set, must be != NULL
132            index............index of component to check
133
134    RETURN VALUE:
135        true if all typevectors in the set contain a reference at INDEX,
136            false otherwise
137
138 *******************************************************************************/
139
140 bool
141 typevectorset_checkreference(typevector *vec,int index)
142 {
143         TYPEINFO_ASSERT(vec);
144         do {
145                 if (!TYPEDESC_IS_REFERENCE(vec->td[index]))
146                         return false;
147         } while ((vec = vec->alt) != NULL);
148         return true;
149 }
150
151 /* typevectorset_checkretaddr **************************************************
152  
153    Check if all typevectors contain a returnAddress at a given index.
154   
155    IN:
156            vec..............typevector set, must be != NULL
157            index............index of component to check
158
159    RETURN VALUE:
160        true if all typevectors in the set contain a returnAddress at INDEX,
161            false otherwise
162
163 *******************************************************************************/
164
165 bool
166 typevectorset_checkretaddr(typevector *vec,int index)
167 {
168         TYPEINFO_ASSERT(vec);
169         do {
170                 if (!TYPEDESC_IS_RETURNADDRESS(vec->td[index]))
171                         return false;
172         } while ((vec = vec->alt) != NULL);
173         return true;
174 }
175
176 /* typevectorset_copymergedtype ************************************************
177  
178    Merge the types at a given index in the typevectors of a set and
179    copy the result to a destination typeinfo.
180   
181    IN:
182            vec..............typevector set, must be != NULL
183            index............index of component to merge
184
185    OUT:
186        *dst.............destination typeinfo, receives the merge result
187
188    RETURN VALUE:
189        the TYPE_* constant of the resulting type
190            TYPE_VOID if incompatible types were contained at INDEX in VEC
191
192 *******************************************************************************/
193
194 int
195 typevectorset_copymergedtype(typevector *vec,int index,typeinfo *dst)
196 {
197         int type;
198         typedescriptor *td;
199
200         TYPEINFO_ASSERT(vec);
201         TYPEINFO_ASSERT(dst);
202
203         td = vec->td + index;
204         type = td->type;
205         TYPEINFO_COPY(td->info,*dst);
206         
207         if (vec->alt) {
208                 int primitive;
209                 
210                 primitive = TYPEINFO_IS_PRIMITIVE(*dst) ? 1 : 0;
211                 
212                 while ((vec = vec->alt) != NULL) {
213                         td = vec->td + index;
214                         if (type != td->type)
215                                 return TYPE_VOID;
216
217                         if (type == TYPE_ADDRESS) {
218                                 if ((TYPEINFO_IS_PRIMITIVE(td->info) ? 1 : 0) != primitive)
219                                         return TYPE_VOID;
220                                 /* there cannot be any merge errors now. In the worst case */
221                                 /* we either get a returnAddress type or a j.l.O reference */
222                                 typeinfo_merge(dst,&(td->info));
223                         }
224                 }
225         }
226         return type;
227 }
228
229 /* typevectorset_mergedtype ****************************************************
230  
231    Return the merged type of the types at a given index in the typevectors 
232    of a set.
233   
234    IN:
235            vec..............typevector set, must be != NULL
236            index............index of component to merge
237            temp.............pointer to a typeinfo that may be used to merge the
238                             result if necessary
239
240    OUT:
241        *result..........set to the address of a typeinfo containing the
242                             merged type.
243
244    RETURN VALUE:
245        the TYPE_* constant of the resulting type
246            TYPE_VOID if incompatible types were contained at INDEX in VEC
247
248    NOTE:
249        This function should be more efficient than typevectorset_copymergedtype
250            assuming that most typevector sets contain exactly one typevector.
251
252 *******************************************************************************/
253
254 int
255 typevectorset_mergedtype(typevector *vec,int index,typeinfo *temp,typeinfo **result)
256 {
257         TYPEINFO_ASSERT(vec);
258         TYPEINFO_ASSERT(temp);
259         TYPEINFO_ASSERT(result);
260         
261         if (vec->alt) {
262                 *result = temp;
263                 return typevectorset_copymergedtype(vec,index,temp);
264         }
265
266         *result = &(vec->td[index].info);
267         return vec->td[index].type;
268 }
269
270 /* typevectorset_mergedtypeinfo ************************************************
271  
272    This is a convenience wrapper around typevectorset_mergedtype. Use this if
273    you are only interested in TYPE_ADR results.
274   
275    IN:
276            vec..............typevector set, must be != NULL
277            index............index of component to merge
278            temp.............pointer to a typeinfo that may be used to merge the
279                             result if necessary
280
281    RETURN VALUE:
282        a pointer to the resulting typeinfo, or
283            NULL if the result is not a TYPE_ADR type
284
285 *******************************************************************************/
286
287 typeinfo *
288 typevectorset_mergedtypeinfo(typevector *vec,int index,typeinfo *temp)
289 {
290         typeinfo *result;
291         int type = typevectorset_mergedtype(vec,index,temp,&result);
292         return (type == TYPE_ADDRESS) ? result : NULL;
293 }
294
295 /* typevectorset_store *********************************************************
296  
297    Store a type at a given index in the typevectors of a set.
298    This function stores the same type in all typevectors of the set.
299    DO NOT use it to store returnAddress types!
300    DO NOT use it to store two-word types!
301   
302    IN:
303            vec..............typevector set, must be != NULL
304            index............index of component to set
305            type.............TYPE_* constant of type to set
306            info.............typeinfo of type to set, may be NULL, 
307                             if TYPE != TYPE_ADR
308
309    NOTE:
310        If there is a two-word type stored at INDEX-1 in any typevector, it is
311            changed to TYPE_VOID (because its upper half has become invalid).
312
313            The components at INDEX+1 are _not_ touched, regardless of TYPE.
314
315 *******************************************************************************/
316
317 void
318 typevectorset_store(typevector *vec,int index,int type,typeinfo *info)
319 {
320         TYPEINFO_ASSERT(vec);
321         TYPEINFO_ASSERT((info && !TYPEINFO_IS_PRIMITIVE(*info)) || type != TYPE_ADR);
322
323         do {
324                 vec->td[index].type = type;
325                 if (info)
326                         TYPEINFO_COPY(*info,vec->td[index].info);
327                 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
328                         vec->td[index-1].type = TYPE_VOID;
329         } while ((vec = vec->alt) != NULL);
330 }
331
332 /* typevectorset_store_retaddr *************************************************
333  
334    Store a returnAddress type at a given index in the typevectors of a set.
335    Each possible returnAddress of the type is stored in the corresponding
336    typevector of the set.
337   
338    IN:
339            vec..............typevector set, must be != NULL
340            index............index of component to set
341            info.............typeinfo of the returnAddress. This typeinfo must
342                             contain a return address set with at least as many
343                                                 entries as there are typevectors in VEC.
344
345    NOTE:
346        If there is a two-word type stored at INDEX-1 in any typevector, it is
347            changed to TYPE_VOID (because its upper half has become invalid).
348
349 *******************************************************************************/
350
351 void
352 typevectorset_store_retaddr(typevector *vec,int index,typeinfo *info)
353 {
354         typeinfo_retaddr_set *adr;
355
356         TYPEINFO_ASSERT(vec);
357         TYPEINFO_ASSERT(TYPEINFO_IS_PRIMITIVE(*info));
358         
359         adr = (typeinfo_retaddr_set*) TYPEINFO_RETURNADDRESS(*info);
360         do {
361                 TYPEINFO_ASSERT(adr);
362
363                 vec->td[index].type = TYPE_ADDRESS;
364                 TYPEINFO_INIT_RETURNADDRESS(vec->td[index].info,adr->addr);
365                 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
366                         vec->td[index-1].type = TYPE_VOID;
367                 adr = adr->alt;
368         } while ((vec = vec->alt) != NULL);
369 }
370
371 /* typevectorset_store_twoword *************************************************
372  
373    Store a two-word type at a given index in the typevectors of a set.
374    This function stores the same type in all typevectors of the set.
375   
376    IN:
377            vec..............typevector set, must be != NULL
378            index............index of component to set
379            type.............TYPE_* constant of type to set (TYPE_LONG, TYPE_DOUBLE)
380
381    NOTE:
382        If there is a two-word type stored at INDEX-1 in any typevector, it is
383            changed to TYPE_VOID (because its upper half has become invalid).
384
385            The components at INDEX+1 are set to TYPE_VOID.
386
387 *******************************************************************************/
388
389 void
390 typevectorset_store_twoword(typevector *vec,int index,int type)
391 {
392         TYPEINFO_ASSERT(vec);
393         TYPEINFO_ASSERT(type == TYPE_LONG || type == TYPE_DOUBLE);
394
395         do {
396                 vec->td[index].type = type;
397                 vec->td[index+1].type = TYPE_VOID;
398                 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
399                         vec->td[index-1].type = TYPE_VOID;
400         } while ((vec = vec->alt) != NULL);
401 }
402
403 /* typevectorset_init_object ***************************************************
404  
405    Replace all uninitialized object types in the typevector set which were 
406    created by the given instruction by initialized object types.
407   
408    IN:
409            set..............typevector set
410            ins..............instruction which created the uninitialized object type
411            initclass........class of the initialized object type to set
412            size.............number of elements per typevector
413
414    RETURN VALUE:
415        true.............success
416            false............an exception has been thrown
417
418    XXX maybe we should do the lazy resolving before calling this function
419
420 *******************************************************************************/
421
422 bool
423 typevectorset_init_object(typevector *set,void *ins,
424                                                   classref_or_classinfo initclass,
425                                                   int size)
426 {
427         int i;
428
429         for (;set; set=set->alt) {
430                 for (i=0; i<size; ++i) {
431                         if (set->td[i].type == TYPE_ADR
432                                 && TYPEINFO_IS_NEWOBJECT(set->td[i].info)
433                                 && TYPEINFO_NEWOBJECT_INSTRUCTION(set->td[i].info) == ins)
434                         {
435                                 if (!typeinfo_init_class(&(set->td[i].info),initclass))
436                                         return false;
437                         }
438                 }
439         }
440         return true;
441 }
442
443 /* typevector_merge ************************************************************
444  
445    Merge a typevector with another one.
446    The given typevectors must have the same number of components.
447   
448    IN:
449            dst..............the first typevector
450            y................the second typevector
451            size.............number of elements per typevector
452
453    OUT:
454        *dst.............the resulting typevector
455
456    RETURN VALUE:
457        true.............dst has been modified
458            false............dst has not been modified
459
460 *******************************************************************************/
461
462 bool
463 typevector_merge(typevector *dst,typevector *y,int size)
464 {
465         bool changed = false;
466         
467         typedescriptor *a = dst->td;
468         typedescriptor *b = y->td;
469         while (size--) {
470                 if (a->type != TYPE_VOID && a->type != b->type) {
471                         a->type = TYPE_VOID;
472                         changed = true;
473                 }
474                 else if (a->type == TYPE_ADDRESS) {
475                         if (TYPEINFO_IS_PRIMITIVE(a->info)) {
476                                 /* 'a' is a returnAddress */
477                                 if (!TYPEINFO_IS_PRIMITIVE(b->info)
478                                         || (TYPEINFO_RETURNADDRESS(a->info)
479                                                 != TYPEINFO_RETURNADDRESS(b->info)))
480                                 {
481                                         a->type = TYPE_VOID;
482                                         changed = true;
483                                 }
484                         }
485                         else {
486                                 /* 'a' is a reference */
487                                 if (TYPEINFO_IS_PRIMITIVE(b->info)) {
488                                         a->type = TYPE_VOID;
489                                         changed = true;
490                                 }
491                                 else {
492                                         /* two reference types are merged. There cannot be */
493                                         /* a merge error. In the worst case we get j.l.O.  */
494                                         changed |= typeinfo_merge(&(a->info),&(b->info));
495                                 }
496                         }
497                 }
498                 a++;
499                 b++;
500         }
501         return changed;
502 }
503
504 /* typevector_separable_from ***************************************************
505  
506    Check if two typevectors are separable. Two typevectors are considered
507    separable if there is an index i for which both typevectors contain a
508    returnAddress type and the return addresses of the types are different.
509    The typevectors must have the same number of components.
510   
511    IN:
512            a................the first typevector
513            b................the second typevector
514            size.............number of elements per typevector
515
516    RETURN VALUE:
517        true.............typevectors are separable
518            false............typevectors are not separable
519
520 *******************************************************************************/
521
522 bool 
523 typevector_separable_from(typevector *a,typevector *b,int size)
524 {
525         typedescriptor *tda = a->td;
526         typedescriptor *tdb = b->td;
527         for (;size--; tda++,tdb++) {
528                 if (TYPEDESC_IS_RETURNADDRESS(*tda)
529                         && TYPEDESC_IS_RETURNADDRESS(*tdb)
530                         && TYPEINFO_RETURNADDRESS(tda->info)
531                            != TYPEINFO_RETURNADDRESS(tdb->info))
532                         return true;
533         }
534         return false;
535 }
536
537 /* typevectorset_add ***********************************************************
538  
539    Add a typevector to a typevector set. The typevector is added at the end of
540    the set and the k-index of the typevector is set accordingly.
541   
542    IN:
543            dst..............the typevector set to modify
544            v................the typevector to add
545            size.............number of elements per typevector
546
547 *******************************************************************************/
548
549 void
550 typevectorset_add(typevector *dst,typevector *v,int size)
551 {
552         TYPEINFO_ASSERT(dst);
553         TYPEINFO_ASSERT(v);
554
555         while (dst->alt)
556                 dst = dst->alt;
557         dst->alt = DNEW_TYPEVECTOR(size);
558         memcpy(dst->alt,v,TYPEVECTOR_SIZE(size));
559         dst->alt->alt = NULL;
560         dst->alt->k = dst->k + 1;
561 }
562
563 /* typevectorset_select ********************************************************
564  
565    Pick the typevectors from a set which contain a given return address.
566   
567    IN:
568            set..............points to the location containing the typevector set.
569                             *set may be NULL.
570            index............index to check against the return address. All
571                             typevectors must contain a returnAddress type at
572                                                 this index.
573            retaddr..........the return address to select
574
575    OUT:
576        *set.............receives the typevector set after removing the
577                             selected typevectors.
578
579    RETURN VALUE:
580        a typevector set consisting of the selected typevectors.
581
582 *******************************************************************************/
583
584 typevector *
585 typevectorset_select(typevector **set,int index,void *retaddr)
586 {
587         typevector *selected;
588
589         if (!*set) return NULL;
590         
591         if (TYPEINFO_RETURNADDRESS((*set)->td[index].info) == retaddr) {
592                 selected = *set;
593                 *set = selected->alt;
594                 selected->alt = typevectorset_select(set,index,retaddr);
595         }
596         else {
597                 selected = typevectorset_select(&((*set)->alt),index,retaddr);
598         }
599         return selected;
600 }
601
602 /* typevector_separable_with ***************************************************
603  
604    Check if a typevector set would be separable after adding a given
605    typevector. A typevector set is considered separable if there is an
606    index i for which all typevectors in the set contain a returnAddress type,
607    and at least two different return addresses occurr at index i.
608    The typevectors must have the same number of components.
609   
610    IN:
611            set..............the typevector set
612            add..............the typevector
613            size.............number of elements per typevector
614
615    RETURN VALUE:
616        true.............result would be separable
617            false............result would not be separable
618
619 *******************************************************************************/
620
621 bool
622 typevectorset_separable_with(typevector *set,typevector *add,int size)
623 {
624         int i;
625         typevector *v;
626         void *addr;
627         bool separable;
628
629         TYPEINFO_ASSERT(set);
630         TYPEINFO_ASSERT(add);
631
632         for (i=0; i<size; ++i) {
633                 if (!TYPEDESC_IS_RETURNADDRESS(add->td[i]))
634                         continue;
635                 addr = TYPEINFO_RETURNADDRESS(add->td[i].info);
636                 
637                 v = set;
638                 separable = false;
639                 do {
640                         if (!TYPEDESC_IS_RETURNADDRESS(v->td[i]))
641                                 goto next_index;
642                         if (TYPEINFO_RETURNADDRESS(v->td[i].info) != addr)
643                                 separable = true;
644                         v = v->alt;
645                 } while (v);
646                 if (separable) return true;
647         next_index:
648                 ;
649         }
650         return false;
651 }
652
653 /* typevectorset_collapse ******************************************************
654  
655    Collapse a typevector set into a single typevector by merging the
656    components of the typevectors at each index.
657    
658    IN:
659            dst..............the type vector set
660            size.............number of elements per typevector
661
662    OUT:
663        *dst.............the resulting typevector set (a single typevector)
664
665    RETURN VALUE:
666        true.............dst has been modified
667            false............dst has not been modified
668
669 *******************************************************************************/
670
671 bool
672 typevectorset_collapse(typevector *dst,int size)
673 {
674         bool changed = false;
675
676         TYPEINFO_ASSERT(dst);
677         
678         while (dst->alt) {
679                 typevector_merge(dst,dst->alt,size);
680                 dst->alt = dst->alt->alt;
681                 changed = true;
682         }
683         return changed;
684 }
685
686 /**********************************************************************/
687 /* READ-ONLY FUNCTIONS                                                */
688 /* The following functions don't change typeinfo data.                */
689 /**********************************************************************/
690
691 bool
692 typeinfo_is_array(typeinfo *info)
693 {
694         TYPEINFO_ASSERT(info);
695     return TYPEINFO_IS_ARRAY(*info);
696 }
697
698 bool
699 typeinfo_is_primitive_array(typeinfo *info,int arraytype)
700 {
701         TYPEINFO_ASSERT(info);
702     return TYPEINFO_IS_PRIMITIVE_ARRAY(*info,arraytype);
703 }
704
705 bool
706 typeinfo_is_array_of_refs(typeinfo *info)
707 {
708         TYPEINFO_ASSERT(info);
709     return TYPEINFO_IS_ARRAY_OF_REFS(*info);
710 }
711
712 static bool
713 interface_extends_interface(classinfo *cls,classinfo *interf)
714 {
715     int i;
716     
717         TYPEINFO_ASSERT(cls);
718         TYPEINFO_ASSERT(interf);
719         TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
720         TYPEINFO_ASSERT((cls->flags & ACC_INTERFACE) != 0);
721         TYPEINFO_ASSERT(cls->linked);
722
723     /* first check direct superinterfaces */
724     for (i=0; i<cls->interfacescount; ++i) {
725         if (cls->interfaces[i].cls == interf)
726             return true;
727     }
728     
729     /* check indirect superinterfaces */
730     for (i=0; i<cls->interfacescount; ++i) {
731         if (interface_extends_interface(cls->interfaces[i].cls,interf))
732             return true;
733     }
734     
735     return false;
736 }
737
738 static bool
739 classinfo_implements_interface(classinfo *cls,classinfo *interf)
740 {
741         TYPEINFO_ASSERT(cls);
742         TYPEINFO_ASSERT(interf);
743         TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
744
745         if (!cls->linked)
746                 if (!link_class(cls)) /* XXX */
747                         return false;
748
749     if (cls->flags & ACC_INTERFACE) {
750         /* cls is an interface */
751         if (cls == interf)
752             return true;
753
754         /* check superinterfaces */
755         return interface_extends_interface(cls,interf);
756     }
757
758     return CLASSINFO_IMPLEMENTS_INTERFACE(cls,interf->index);
759 }
760
761 tristate_t 
762 mergedlist_implements_interface(typeinfo_mergedlist *merged,
763                                 classinfo *interf)
764 {
765     int i;
766     classref_or_classinfo *mlist;
767     
768         TYPEINFO_ASSERT(interf);
769         TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
770
771     /* Check if there is an non-empty mergedlist. */
772     if (!merged)
773         return false;
774
775     /* If all classinfos in the (non-empty) merged array implement the
776      * interface return true, otherwise false.
777      */
778     mlist = merged->list;
779     i = merged->count;
780     while (i--) {
781                 if (IS_CLASSREF(*mlist)) {
782                         return MAYBE;
783                 }
784         if (!classinfo_implements_interface((mlist++)->cls,interf))
785             return false;
786     }
787     return true;
788 }
789
790 tristate_t
791 merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged,
792                             classinfo *interf)
793 {
794     /* primitive types don't support interfaces. */
795     if (!typeclass)
796         return false;
797
798     /* the null type can be cast to any interface type. */
799     if (typeclass == pseudo_class_Null)
800         return true;
801
802     /* check if typeclass implements the interface. */
803     if (classinfo_implements_interface(typeclass,interf))
804         return true;
805
806     /* check the mergedlist */
807     return (merged && mergedlist_implements_interface(merged,interf));
808 }
809
810 tristate_t
811 typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
812 {
813         TYPEINFO_ASSERT(value);
814         TYPEINFO_ASSERT(dest);
815         TYPEINFO_ASSERT(dest->merged == NULL);
816
817         return typeinfo_is_assignable_to_class(value,dest->typeclass);
818 }
819
820 tristate_t
821 typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
822 {
823         classref_or_classinfo c;
824     classinfo *cls;
825         utf *classname;
826
827         TYPEINFO_ASSERT(value);
828
829     c = value->typeclass;
830
831     /* assignments of primitive values are not checked here. */
832     if (!c.any && !dest.any)
833         return true;
834
835     /* primitive and reference types are not assignment compatible. */
836     if (!c.any || !dest.any)
837         return false;
838
839     /* the null type can be assigned to any type */
840     if (TYPEINFO_IS_NULLTYPE(*value))
841         return true;
842
843     /* uninitialized objects are not assignable */
844     if (TYPEINFO_IS_NEWOBJECT(*value))
845         return false;
846
847         if (IS_CLASSREF(c)) {
848                 /* The value type is an unresolved class reference. */
849                 classname = c.ref->name;
850         }
851         else {
852                 classname = c.cls->name;
853         }
854
855         if (IS_CLASSREF(dest)) {
856                 /* the destination type is an unresolved class reference */
857                 /* In this case we cannot tell a lot about assignability. */
858
859                 /* the common case of value and dest type having the same classname */
860                 if (dest.ref->name == classname && !value->merged)
861                         return true;
862
863                 /* we cannot tell if value is assignable to dest, so we */
864                 /* leave it up to the resolving code to check this      */
865                 return MAYBE;
866         }
867
868         /* { we know that dest is a loaded class } */
869
870         if (IS_CLASSREF(c)) {
871                 /* the value type is an unresolved class reference */
872                 
873                 /* the common case of value and dest type having the same classname */
874                 if (dest.cls->name == classname)
875                         return true;
876
877                 /* we cannot tell if value is assignable to dest, so we */
878                 /* leave it up to the resolving code to check this      */
879                 return MAYBE;
880         }
881
882         /* { we know that both c and dest are loaded classes } */
883
884         TYPEINFO_ASSERT(!IS_CLASSREF(c));
885         TYPEINFO_ASSERT(!IS_CLASSREF(dest));
886
887         cls = c.cls;
888         
889         TYPEINFO_ASSERT(cls->loaded);
890         TYPEINFO_ASSERT(dest.cls->loaded);
891
892         /* maybe we need to link the classes */
893         if (!cls->linked)
894                 link_class(cls); /* XXX */
895         if (!dest.cls->linked)
896                 link_class(dest.cls); /* XXX */
897
898         /* { we know that both c and dest are linked classes } */
899         TYPEINFO_ASSERT(cls->linked);
900         TYPEINFO_ASSERT(dest.cls->linked);
901
902     if (dest.cls->flags & ACC_INTERFACE) {
903         /* We are assigning to an interface type. */
904         return merged_implements_interface(cls,value->merged,dest.cls);
905     }
906
907     if (CLASSINFO_IS_ARRAY(dest.cls)) {
908                 arraydescriptor *arraydesc = dest.cls->vftbl->arraydesc;
909                 int dimension = arraydesc->dimension;
910                 classinfo *elementclass = (arraydesc->elementvftbl)
911                         ? arraydesc->elementvftbl->class : NULL;
912                         
913         /* We are assigning to an array type. */
914         if (!TYPEINFO_IS_ARRAY(*value))
915             return false;
916
917         /* {Both value and dest.cls are array types.} */
918
919         /* value must have at least the dimension of dest.cls. */
920         if (value->dimension < dimension)
921             return false;
922
923         if (value->dimension > dimension) {
924             /* value has higher dimension so we need to check
925              * if its component array can be assigned to the
926              * element type of dest.cls */
927
928                         if (!elementclass) return false;
929             
930             if (elementclass->flags & ACC_INTERFACE) {
931                 /* We are assigning to an interface type. */
932                 return classinfo_implements_interface(pseudo_class_Arraystub,
933                                                       elementclass);
934             }
935
936             /* We are assigning to a class type. */
937             return class_issubclass(pseudo_class_Arraystub,elementclass);
938         }
939
940         /* {value and dest.cls have the same dimension} */
941
942         if (value->elementtype != arraydesc->elementtype)
943             return false;
944
945         if (value->elementclass.any) {
946             /* We are assigning an array of objects so we have to
947              * check if the elements are assignable.
948              */
949
950             if (elementclass->flags & ACC_INTERFACE) {
951                 /* We are assigning to an interface type. */
952
953                 return merged_implements_interface(value->elementclass.cls,
954                                                    value->merged,
955                                                    elementclass);
956             }
957             
958             /* We are assigning to a class type. */
959             return class_issubclass(value->elementclass.cls,elementclass);
960         }
961
962         return true;
963     }
964
965     /* {dest.cls is not an array} */
966     /* {dest.cls is a loaded class} */
967
968         /* If there are any unresolved references in the merged list, we cannot */
969         /* tell if the assignment will be ok.                                   */
970         /* This can only happen when cls is java.lang.Object                    */
971         if (cls == class_java_lang_Object && value->merged) {
972                 classref_or_classinfo *mlist = value->merged->list;
973                 int i = value->merged->count;
974                 while (i--)
975                         if (IS_CLASSREF(*mlist++))
976                                 return MAYBE;
977         }
978         
979     /* We are assigning to a class type */
980     if (cls->flags & ACC_INTERFACE)
981         cls = class_java_lang_Object;
982     
983     return class_issubclass(cls,dest.cls);
984 }
985
986 /**********************************************************************/
987 /* INITIALIZATION FUNCTIONS                                           */
988 /* The following functions fill in uninitialized typeinfo structures. */
989 /**********************************************************************/
990
991 bool
992 typeinfo_init_class(typeinfo *info,classref_or_classinfo c)
993 {
994         char *utf_ptr;
995         int len;
996         classinfo *cls;
997                 
998         TYPEINFO_ASSERT(c.any);
999         TYPEINFO_ASSERT(info);
1000
1001         /* if necessary, try to resolve lazily */
1002         if (!resolve_classref_or_classinfo(NULL /* XXX should now method */,
1003                                 c,resolveLazy,false,true,&cls))
1004         {
1005                 return false;
1006         }
1007         
1008         if (cls) {
1009                 TYPEINFO_INIT_CLASSINFO(*info,cls);
1010                 return true;
1011         }
1012
1013         /* {the type could no be resolved lazily} */
1014
1015         info->typeclass.ref = c.ref;
1016         info->elementclass.any = NULL;
1017         info->dimension = 0;
1018         info->merged = NULL;
1019
1020         /* handle array type references */
1021         utf_ptr = c.ref->name->text;
1022         len = c.ref->name->blength;
1023         if (*utf_ptr == '[') {
1024                 /* count dimensions */
1025                 while (*utf_ptr == '[') {
1026                         utf_ptr++;
1027                         info->dimension++;
1028                         len--;
1029                 }
1030                 if (*utf_ptr == 'L') {
1031                         utf_ptr++;
1032                         len -= 2;
1033                         info->elementtype = ARRAYTYPE_OBJECT;
1034                         info->elementclass.ref = class_get_classref(c.ref->referer,utf_new(utf_ptr,len));
1035                 }
1036                 else {
1037                         /* an array with primitive element type */
1038                         /* should have been resolved above */
1039                         TYPEINFO_ASSERT(false);
1040                 }
1041         }
1042         return true;
1043 }
1044
1045 bool
1046 typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info)
1047 {
1048         TYPEINFO_ASSERT(desc);
1049
1050 #ifdef TYPEINFO_VERBOSE
1051         fprintf(stderr,"typeinfo_init_from_typedesc(");
1052         descriptor_debug_print_typedesc(stderr,desc);
1053         fprintf(stderr,")\n");
1054 #endif
1055
1056         if (type)
1057                 *type = desc->type;
1058
1059         if (info) {
1060                 if (desc->type == TYPE_ADR) {
1061                         TYPEINFO_ASSERT(desc->classref);
1062                         if (!typeinfo_init_class(info,CLASSREF_OR_CLASSINFO(desc->classref)))
1063                                 return false;
1064                 }
1065                 else {
1066                         TYPEINFO_INIT_PRIMITIVE(*info);
1067                 }
1068         }
1069         return true;
1070 }
1071
1072 bool
1073 typeinfo_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo *infobuf,
1074                               int buflen,bool twoword,
1075                               u1 *returntype,typeinfo *returntypeinfo)
1076 {
1077         int i;
1078     int args = 0;
1079
1080         TYPEINFO_ASSERT(desc);
1081         TYPEINFO_ASSERT(typebuf);
1082         TYPEINFO_ASSERT(infobuf);
1083
1084 #ifdef TYPEINFO_VERBOSE
1085         fprintf(stderr,"typeinfo_init_from_methoddesc(");
1086         descriptor_debug_print_methoddesc(stderr,desc);
1087         fprintf(stderr,")\n");
1088 #endif
1089
1090     /* check arguments */
1091     for (i=0; i<desc->paramcount; ++i) {
1092                 if (++args > buflen) {
1093                         log_text("Buffer too small for method arguments."); /* XXX */
1094                         assert(0);
1095                 }
1096
1097                 if (!typeinfo_init_from_typedesc(desc->paramtypes + i,typebuf++,infobuf++))
1098                         return false;
1099                 
1100                 if (twoword && (typebuf[-1] == TYPE_LONG || typebuf[-1] == TYPE_DOUBLE)) {
1101                         if (++args > buflen) {
1102                                 log_text("Buffer too small for method arguments."); /* XXX */
1103                                 assert(0);
1104                         }
1105
1106                         *typebuf++ = TYPE_VOID;
1107                         TYPEINFO_INIT_PRIMITIVE(*infobuf);
1108                         infobuf++;
1109                 }
1110     }
1111
1112     /* check returntype */
1113     if (returntype) {
1114                 if (!typeinfo_init_from_typedesc(&(desc->returntype),returntype,returntypeinfo))
1115                         return false;
1116         }
1117
1118         return true;
1119 }
1120
1121 bool
1122 typedescriptor_init_from_typedesc(typedescriptor *td,
1123                                                                   typedesc *desc)
1124 {
1125         td->type = desc->type;
1126         if (td->type == TYPE_ADR) {
1127                 if (!typeinfo_init_class(&(td->info),CLASSREF_OR_CLASSINFO(desc->classref)))
1128                         return false;
1129         }
1130         else {
1131                 TYPEINFO_INIT_PRIMITIVE(td->info);
1132         }
1133         return true;
1134 }
1135
1136 int
1137 typedescriptors_init_from_methoddesc(typedescriptor *td,
1138                                                                          methoddesc *desc,
1139                                                                          int buflen,bool twoword,int startindex,
1140                                                                          typedescriptor *returntype)
1141 {
1142         int i;
1143     int args = 0;
1144
1145     /* check arguments */
1146     for (i=startindex; i<desc->paramcount; ++i) {
1147                 if (++args > buflen) {
1148                         log_text("Buffer too small for method arguments."); /* XXX */
1149                         assert(0);
1150                 }
1151
1152                 if (!typedescriptor_init_from_typedesc(td,desc->paramtypes + i))
1153                         return -1;
1154                 td++;
1155
1156                 if (twoword && (td[-1].type == TYPE_LONG || td[-1].type == TYPE_DOUBLE)) {
1157                         if (++args > buflen) {
1158                                 log_text("Buffer too small for method arguments."); /* XXX */
1159                                 assert(0);
1160                         }
1161
1162                         td->type = TYPE_VOID;
1163                         TYPEINFO_INIT_PRIMITIVE(td->info);
1164                         td++;
1165                 }
1166     }
1167
1168     /* check returntype */
1169     if (returntype) {
1170                 if (!typedescriptor_init_from_typedesc(returntype,&(desc->returntype)))
1171                         return -1;
1172         }
1173
1174         return args;
1175 }
1176
1177 bool
1178 typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
1179 {
1180     if (TYPEINFO_IS_NULLTYPE(*srcarray)) {
1181         TYPEINFO_INIT_NULLTYPE(*dst);
1182         return true;
1183     }
1184     
1185     if (!TYPEINFO_IS_ARRAY(*srcarray)) {
1186         log_text("Trying to access component of non-array"); /* XXX throw exception */
1187                 assert(0);
1188         }
1189
1190         if (IS_CLASSREF(srcarray->typeclass)) {
1191                 constant_classref *comp;
1192                 comp = class_get_classref_component_of(srcarray->typeclass.ref);
1193
1194                 if (comp) {
1195                         if (!typeinfo_init_class(dst,CLASSREF_OR_CLASSINFO(comp)))
1196                                 return false;
1197                 }
1198                 else {
1199                         TYPEINFO_INIT_PRIMITIVE(*dst);
1200                 }
1201         }
1202         else {
1203                 vftbl_t *comp;
1204                 
1205                 if (!srcarray->typeclass.cls->linked) {
1206                         if (!link_class(srcarray->typeclass.cls)) {
1207                                 return false;
1208                         }
1209                 }
1210
1211                 TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl);
1212                 TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl->arraydesc);
1213
1214                 comp = srcarray->typeclass.cls->vftbl->arraydesc->componentvftbl;
1215                 if (comp)
1216                         TYPEINFO_INIT_CLASSINFO(*dst,comp->class);
1217                 else
1218                         TYPEINFO_INIT_PRIMITIVE(*dst);
1219         }
1220     
1221     dst->merged = srcarray->merged; /* XXX should we do a deep copy? */
1222         return true;
1223 }
1224
1225 void
1226 typeinfo_clone(typeinfo *src,typeinfo *dest)
1227 {
1228     int count;
1229     classref_or_classinfo *srclist,*destlist;
1230
1231     if (src == dest)
1232         return;
1233     
1234     *dest = *src;
1235
1236     if (src->merged) {
1237         count = src->merged->count;
1238         TYPEINFO_ALLOCMERGED(dest->merged,count);
1239         dest->merged->count = count;
1240
1241         srclist = src->merged->list;
1242         destlist = dest->merged->list;
1243         while (count--)
1244             *destlist++ = *srclist++;
1245     }
1246 }
1247
1248 /**********************************************************************/
1249 /* MISCELLANEOUS FUNCTIONS                                            */
1250 /**********************************************************************/
1251
1252 void
1253 typeinfo_free(typeinfo *info)
1254 {
1255     TYPEINFO_FREEMERGED_IF_ANY(info->merged);
1256     info->merged = NULL;
1257 }
1258
1259 /**********************************************************************/
1260 /* MERGING FUNCTIONS                                                  */
1261 /* The following functions are used to merge the types represented by */
1262 /* two typeinfo structures into one typeinfo structure.               */
1263 /**********************************************************************/
1264
1265 static
1266 void
1267 typeinfo_merge_error(char *str,typeinfo *x,typeinfo *y) {
1268 #ifdef TYPEINFO_VERBOSE
1269     fprintf(stderr,"Error in typeinfo_merge: %s\n",str);
1270     fprintf(stderr,"Typeinfo x:\n");
1271     typeinfo_print(stderr,x,1);
1272     fprintf(stderr,"Typeinfo y:\n");
1273     typeinfo_print(stderr,y,1);
1274 #endif
1275
1276     log_text(str); /* XXX throw an exception */
1277         assert(0);
1278 }
1279
1280 /* Condition: clsx != clsy. */
1281 /* Returns: true if dest was changed (currently always true). */
1282 static
1283 bool
1284 typeinfo_merge_two(typeinfo *dest,classref_or_classinfo clsx,classref_or_classinfo clsy)
1285 {
1286         TYPEINFO_ASSERT(dest);
1287     TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1288     TYPEINFO_ALLOCMERGED(dest->merged,2);
1289     dest->merged->count = 2;
1290
1291         TYPEINFO_ASSERT(clsx.any != clsy.any);
1292
1293     if (clsx.any < clsy.any) {
1294         dest->merged->list[0] = clsx;
1295         dest->merged->list[1] = clsy;
1296     }
1297     else {
1298         dest->merged->list[0] = clsy;
1299         dest->merged->list[1] = clsx;
1300     }
1301
1302     return true;
1303 }
1304
1305 /* Returns: true if dest was changed. */
1306 static
1307 bool
1308 typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classref_or_classinfo cls)
1309 {
1310     int count;
1311     typeinfo_mergedlist *newmerged;
1312     classref_or_classinfo *mlist,*newlist;
1313
1314     count = m->count;
1315     mlist = m->list;
1316
1317     /* Check if cls is already in the mergedlist m. */
1318     while (count--) {
1319         if ((mlist++)->any == cls.any) { /* XXX check equal classrefs? */
1320             /* cls is in the list, so m is the resulting mergedlist */
1321             if (dest->merged == m)
1322                 return false;
1323
1324             /* We have to copy the mergedlist */
1325             TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1326             count = m->count;
1327             TYPEINFO_ALLOCMERGED(dest->merged,count);
1328             dest->merged->count = count;
1329             newlist = dest->merged->list;
1330             mlist = m->list;
1331             while (count--) {
1332                 *newlist++ = *mlist++;
1333             }
1334             return true;
1335         }
1336     }
1337
1338     /* Add cls to the mergedlist. */
1339     count = m->count;
1340     TYPEINFO_ALLOCMERGED(newmerged,count+1);
1341     newmerged->count = count+1;
1342     newlist = newmerged->list;    
1343     mlist = m->list;
1344     while (count) {
1345         if (mlist->any > cls.any)
1346             break;
1347         *newlist++ = *mlist++;
1348         count--;
1349     }
1350     *newlist++ = cls;
1351     while (count--) {
1352         *newlist++ = *mlist++;
1353     }
1354
1355     /* Put the new mergedlist into dest. */
1356     TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1357     dest->merged = newmerged;
1358     
1359     return true;
1360 }
1361
1362 /* Returns: true if dest was changed. */
1363 static
1364 bool
1365 typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
1366                            typeinfo_mergedlist *y)
1367 {
1368     int count = 0;
1369     int countx,county;
1370     typeinfo_mergedlist *temp,*result;
1371     classref_or_classinfo *clsx,*clsy,*newlist;
1372
1373     /* count the elements that will be in the resulting list */
1374     /* (Both lists are sorted, equal elements are counted only once.) */
1375     clsx = x->list;
1376     clsy = y->list;
1377     countx = x->count;
1378     county = y->count;
1379     while (countx && county) {
1380         if (clsx->any == clsy->any) {
1381             clsx++;
1382             clsy++;
1383             countx--;
1384             county--;
1385         }
1386         else if (clsx->any < clsy->any) {
1387             clsx++;
1388             countx--;
1389         }
1390         else {
1391             clsy++;
1392             county--;
1393         }
1394         count++;
1395     }
1396     count += countx + county;
1397
1398     /* {The new mergedlist will have count entries.} */
1399
1400     if ((x->count != count) && (y->count == count)) {
1401         temp = x; x = y; y = temp;
1402     }
1403     /* {If one of x,y is already the result it is x.} */
1404     if (x->count == count) {
1405         /* x->merged is equal to the result */
1406         if (x == dest->merged)
1407             return false;
1408
1409         if (!dest->merged || dest->merged->count != count) {
1410             TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1411             TYPEINFO_ALLOCMERGED(dest->merged,count);
1412             dest->merged->count = count;
1413         }
1414
1415         newlist = dest->merged->list;
1416         clsx = x->list;
1417         while (count--) {
1418             *newlist++ = *clsx++;
1419         }
1420         return true;
1421     }
1422
1423     /* {We have to merge two lists.} */
1424
1425     /* allocate the result list */
1426     TYPEINFO_ALLOCMERGED(result,count);
1427     result->count = count;
1428     newlist = result->list;
1429
1430     /* merge the sorted lists */
1431     clsx = x->list;
1432     clsy = y->list;
1433     countx = x->count;
1434     county = y->count;
1435     while (countx && county) {
1436         if (clsx->any == clsy->any) {
1437             *newlist++ = *clsx++;
1438             clsy++;
1439             countx--;
1440             county--;
1441         }
1442         else if (clsx->any < clsy->any) {
1443             *newlist++ = *clsx++;
1444             countx--;
1445         }
1446         else {
1447             *newlist++ = *clsy++;
1448             county--;
1449         }
1450     }
1451     while (countx--)
1452             *newlist++ = *clsx++;
1453     while (county--)
1454             *newlist++ = *clsy++;
1455
1456     /* replace the list in dest with the result list */
1457     TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1458     dest->merged = result;
1459
1460     return true;
1461 }
1462
1463 static
1464 bool
1465 typeinfo_merge_nonarrays(typeinfo *dest,
1466                          classref_or_classinfo *result,
1467                          classref_or_classinfo x,classref_or_classinfo y,
1468                          typeinfo_mergedlist *mergedx,
1469                          typeinfo_mergedlist *mergedy)
1470 {
1471         classref_or_classinfo t;
1472     classinfo *tcls,*common;
1473     typeinfo_mergedlist *tmerged;
1474     bool changed;
1475         utf *xname;
1476         utf *yname;
1477
1478         TYPEINFO_ASSERT(dest && result && x.any && y.any);
1479         TYPEINFO_ASSERT(x.cls != pseudo_class_Null);
1480         TYPEINFO_ASSERT(y.cls != pseudo_class_Null);
1481         TYPEINFO_ASSERT(x.cls != pseudo_class_New);
1482         TYPEINFO_ASSERT(y.cls != pseudo_class_New);
1483
1484         /*--------------------------------------------------*/
1485         /* common cases                                     */
1486         /*--------------------------------------------------*/
1487
1488     /* Common case 1: x and y are the same class or class reference */
1489     /* (This case is very simple unless *both* x and y really represent
1490      *  merges of subclasses of clsx==clsy.)
1491      */
1492     if ( (x.any == y.any) && (!mergedx || !mergedy) ) {
1493   return_simple_x:
1494         /* DEBUG */ /* log_text("return simple x"); */
1495         changed = (dest->merged != NULL);
1496         TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1497         dest->merged = NULL;
1498         *result = x;
1499         /* DEBUG */ /* log_text("returning"); */
1500         return changed;
1501     }
1502
1503         xname = (IS_CLASSREF(x)) ? x.ref->name : x.cls->name;
1504         yname = (IS_CLASSREF(y)) ? y.ref->name : y.cls->name;
1505
1506         /* Common case 2: xname == yname, at least one unresolved */
1507     if ((IS_CLASSREF(x) || IS_CLASSREF(y)) && (xname == yname))
1508         {
1509                 /* use the loaded one if any */
1510                 if (!IS_CLASSREF(y))
1511                         x = y;
1512                 goto return_simple_x;
1513     }
1514
1515         /*--------------------------------------------------*/
1516         /* non-trivial cases                                */
1517         /*--------------------------------------------------*/
1518
1519 #ifdef TYPEINFO_VERBOSE
1520         {
1521                 typeinfo dbgx,dbgy;
1522                 fprintf(stderr,"merge_nonarrays:\n");
1523                 fprintf(stderr,"    ");if(IS_CLASSREF(x))fprintf(stderr,"<ref>");utf_fprint(stderr,xname);fprintf(stderr,"\n");
1524                 fprintf(stderr,"    ");if(IS_CLASSREF(y))fprintf(stderr,"<ref>");utf_fprint(stderr,yname);fprintf(stderr,"\n");
1525                 fflush(stderr);
1526                 TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(dbgx,x);
1527                 dbgx.merged = mergedx;
1528                 TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(dbgy,y);
1529                 dbgy.merged = mergedy;
1530                 typeinfo_print(stderr,&dbgx,4);
1531                 fprintf(stderr,"  with:\n");
1532                 typeinfo_print(stderr,&dbgy,4);
1533         }
1534 #endif
1535
1536         TYPEINFO_ASSERT(IS_CLASSREF(x) || x.cls->loaded);
1537         TYPEINFO_ASSERT(IS_CLASSREF(y) || y.cls->loaded);
1538
1539     /* If y is unresolved or an interface, swap x and y. */
1540     if (IS_CLASSREF(y) || (!IS_CLASSREF(x) && y.cls->flags & ACC_INTERFACE))
1541         {
1542         t = x; x = y; y = t;
1543         tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1544     }
1545         
1546     /* {We know: If only one of x,y is unresolved it is x,} */
1547     /* {         If both x,y are resolved and only one of x,y is an interface it is x.} */
1548
1549         if (IS_CLASSREF(x)) {
1550                 /* {We know: x and y have different class names} */
1551                 
1552         /* Check if we are merging an unresolved type with java.lang.Object */
1553         if (y.cls == class_java_lang_Object && !mergedy) {
1554             x = y;
1555             goto return_simple_x;
1556         }
1557             
1558                 common = class_java_lang_Object;
1559                 goto merge_with_simple_x;
1560         }
1561
1562         /* {We know: both x and y are resolved} */
1563     /* {We know: If only one of x,y is an interface it is x.} */
1564
1565         TYPEINFO_ASSERT(!IS_CLASSREF(x) && !IS_CLASSREF(y));
1566         TYPEINFO_ASSERT(x.cls->loaded);
1567         TYPEINFO_ASSERT(y.cls->loaded);
1568
1569     /* Handle merging of interfaces: */
1570     if (x.cls->flags & ACC_INTERFACE) {
1571         /* {x.cls is an interface and mergedx == NULL.} */
1572         
1573         if (y.cls->flags & ACC_INTERFACE) {
1574             /* We are merging two interfaces. */
1575             /* {mergedy == NULL} */
1576
1577             /* {We know that x.cls!=y.cls (see common case at beginning.)} */
1578             result->cls = class_java_lang_Object;
1579             return typeinfo_merge_two(dest,x,y);
1580         }
1581
1582         /* {We know: x is an interface, y is a class.} */
1583
1584         /* Check if we are merging an interface with java.lang.Object */
1585         if (y.cls == class_java_lang_Object && !mergedy) {
1586             x = y;
1587             goto return_simple_x;
1588         }
1589
1590         /* If the type y implements x then the result of the merge
1591          * is x regardless of mergedy.
1592          */
1593
1594                 /* we may have to link the classes */
1595                 if (!x.cls->linked)
1596                         link_class(x.cls); /* XXX */
1597                 if (!y.cls->linked)
1598                         link_class(y.cls); /* XXX */
1599         
1600                 TYPEINFO_ASSERT(x.cls->linked);
1601                 TYPEINFO_ASSERT(y.cls->linked);
1602
1603         if (CLASSINFO_IMPLEMENTS_INTERFACE(y.cls,x.cls->index)
1604             || mergedlist_implements_interface(mergedy,x.cls))
1605         {
1606             /* y implements x, so the result of the merge is x. */
1607             goto return_simple_x;
1608         }
1609         
1610         /* {We know: x is an interface, the type y a class or a merge
1611          * of subclasses and does not implement x.} */
1612
1613         /* There may still be superinterfaces of x which are implemented
1614          * by y, too, so we have to add x.cls to the mergedlist.
1615          */
1616
1617         /* if x has no superinterfaces we could return a simple java.lang.Object */
1618         
1619         common = class_java_lang_Object;
1620         goto merge_with_simple_x;
1621     }
1622
1623     /* {We know: x and y are classes (not interfaces).} */
1624     
1625         /* we may have to link the classes */
1626         if (!x.cls->linked)
1627                 link_class(x.cls); /* XXX */
1628         if (!y.cls->linked)
1629                 link_class(y.cls); /* XXX */
1630         
1631         TYPEINFO_ASSERT(x.cls->linked);
1632         TYPEINFO_ASSERT(y.cls->linked);
1633
1634     /* If *x is deeper in the inheritance hierarchy swap x and y. */
1635     if (x.cls->index > y.cls->index) {
1636         t = x; x = y; y = t;
1637         tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1638     }
1639
1640     /* {We know: y is at least as deep in the hierarchy as x.} */
1641
1642     /* Find nearest common anchestor for the classes. */
1643     common = x.cls;
1644     tcls = y.cls;
1645     while (tcls->index > common->index)
1646         tcls = tcls->super.cls;
1647     while (common != tcls) {
1648         common = common->super.cls;
1649         tcls = tcls->super.cls;
1650     }
1651
1652     /* {common == nearest common anchestor of x and y.} */
1653
1654     /* If x.cls==common and x is a whole class (not a merge of subclasses)
1655      * then the result of the merge is x.
1656      */
1657     if (x.cls == common && !mergedx) {
1658         goto return_simple_x;
1659     }
1660    
1661     if (mergedx) {
1662         result->cls = common;
1663         if (mergedy)
1664             return typeinfo_merge_mergedlists(dest,mergedx,mergedy);
1665         else
1666             return typeinfo_merge_add(dest,mergedx,y);
1667     }
1668
1669 merge_with_simple_x:
1670     result->cls = common;
1671     if (mergedy)
1672         return typeinfo_merge_add(dest,mergedy,x);
1673     else
1674         return typeinfo_merge_two(dest,x,y);
1675 }
1676
1677 /* Condition: *dest must be a valid initialized typeinfo. */
1678 /* Condition: dest != y. */
1679 /* Returns: true if dest was changed. */
1680 bool
1681 typeinfo_merge(typeinfo *dest,typeinfo* y)
1682 {
1683     typeinfo *x;
1684     typeinfo *tmp;
1685     classref_or_classinfo common;
1686     classref_or_classinfo elementclass;
1687     int dimension;
1688     int elementtype;
1689     bool changed;
1690
1691         /*--------------------------------------------------*/
1692         /* fast checks                                      */
1693         /*--------------------------------------------------*/
1694
1695     /* Merging something with itself is a nop */
1696     if (dest == y)
1697         return false;
1698
1699     /* Merging two returnAddress types is ok. */
1700         /* Merging two different returnAddresses never happens, as the verifier */
1701         /* keeps them separate in order to check all the possible return paths  */
1702         /* from JSR subroutines.                                                */
1703     if (!dest->typeclass.any && !y->typeclass.any) {
1704                 TYPEINFO_ASSERT(TYPEINFO_RETURNADDRESS(*dest) ==  TYPEINFO_RETURNADDRESS(*y));
1705         return false;
1706         }
1707     
1708     /* Primitive types cannot be merged with reference types */
1709         /* XXX only check this in debug mode? */
1710     if (!dest->typeclass.any || !y->typeclass.any)
1711         typeinfo_merge_error("Trying to merge primitive types.",dest,y);
1712
1713     /* handle uninitialized object types */
1714     if (TYPEINFO_IS_NEWOBJECT(*dest) || TYPEINFO_IS_NEWOBJECT(*y)) {
1715         if (!TYPEINFO_IS_NEWOBJECT(*dest) || !TYPEINFO_IS_NEWOBJECT(*y))
1716             typeinfo_merge_error("Trying to merge uninitialized object type.",dest,y);
1717         if (TYPEINFO_NEWOBJECT_INSTRUCTION(*dest)
1718             != TYPEINFO_NEWOBJECT_INSTRUCTION(*y))
1719             typeinfo_merge_error("Trying to merge different uninitialized objects.",dest,y);
1720         return false;
1721     }
1722     
1723         /*--------------------------------------------------*/
1724         /* common cases                                     */
1725         /*--------------------------------------------------*/
1726
1727     /* Common case: dest and y are the same class or class reference */
1728     /* (This case is very simple unless *both* dest and y really represent
1729      *  merges of subclasses of class dest==class y.)
1730      */
1731     if ((dest->typeclass.any == y->typeclass.any) && (!dest->merged || !y->merged)) {
1732 return_simple:
1733         changed = (dest->merged != NULL);
1734         TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1735         dest->merged = NULL;
1736         return changed;
1737     }
1738     
1739     /* Handle null types: */
1740     if (TYPEINFO_IS_NULLTYPE(*y)) {
1741         return false;
1742     }
1743     if (TYPEINFO_IS_NULLTYPE(*dest)) {
1744         TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1745         TYPEINFO_CLONE(*y,*dest);
1746         return true;
1747     }
1748
1749         /* Common case: two types with the same name, at least one unresolved */
1750         if (IS_CLASSREF(dest->typeclass)) {
1751                 if (IS_CLASSREF(y->typeclass)) {
1752                         if (dest->typeclass.ref->name == y->typeclass.ref->name)
1753                                 goto return_simple;
1754                 }
1755                 else {
1756                         /* XXX should we take y instead of dest here? */
1757                         if (dest->typeclass.ref->name == y->typeclass.cls->name)
1758                                 goto return_simple;
1759                 }
1760         }
1761         else {
1762                 if (IS_CLASSREF(y->typeclass) 
1763                     && (dest->typeclass.cls->name == y->typeclass.ref->name))
1764                 {
1765                         goto return_simple;
1766                 }
1767         }
1768
1769         /*--------------------------------------------------*/
1770         /* non-trivial cases                                */
1771         /*--------------------------------------------------*/
1772
1773 #ifdef TYPEINFO_VERBOSE
1774         fprintf(stderr,"merge:\n");
1775     typeinfo_print(stderr,dest,4);
1776     typeinfo_print(stderr,y,4);
1777 #endif
1778
1779     /* This function uses x internally, so x and y can be swapped
1780      * without changing dest. */
1781     x = dest;
1782     changed = false;
1783     
1784     /* Handle merging of arrays: */
1785     if (TYPEINFO_IS_ARRAY(*x) && TYPEINFO_IS_ARRAY(*y)) {
1786         
1787         /* Make x the one with lesser dimension */
1788         if (x->dimension > y->dimension) {
1789             tmp = x; x = y; y = tmp;
1790         }
1791
1792         /* If one array (y) has higher dimension than the other,
1793          * interpret it as an array (same dim. as x) of Arraystubs. */
1794         if (x->dimension < y->dimension) {
1795             dimension = x->dimension;
1796             elementtype = ARRAYTYPE_OBJECT;
1797             elementclass.cls = pseudo_class_Arraystub;
1798         }
1799         else {
1800             dimension = y->dimension;
1801             elementtype = y->elementtype;
1802             elementclass = y->elementclass;
1803         }
1804         
1805         /* {The arrays are of the same dimension.} */
1806         
1807         if (x->elementtype != elementtype) {
1808             /* Different element types are merged, so the resulting array
1809              * type has one accessible dimension less. */
1810             if (--dimension == 0) {
1811                 common.cls = pseudo_class_Arraystub;
1812                 elementtype = 0;
1813                 elementclass.any = NULL;
1814             }
1815             else {
1816                 common.cls = class_multiarray_of(dimension,pseudo_class_Arraystub,true);
1817                                 if (!common.cls) {
1818                                         log_text("XXX Coult not create array class");
1819                                         assert(0);
1820                                 }
1821
1822                 elementtype = ARRAYTYPE_OBJECT;
1823                 elementclass.cls = pseudo_class_Arraystub;
1824             }
1825         }
1826         else {
1827             /* {The arrays have the same dimension and elementtype.} */
1828
1829             if (elementtype == ARRAYTYPE_OBJECT) {
1830                 /* The elements are references, so their respective
1831                  * types must be merged.
1832                  */
1833                 changed |= typeinfo_merge_nonarrays(dest,
1834                                                     &elementclass,
1835                                                     x->elementclass,
1836                                                     elementclass,
1837                                                     x->merged,y->merged);
1838
1839                 /* DEBUG */ /* log_text("finding resulting array class: "); */
1840                                 if (IS_CLASSREF(elementclass))
1841                                         common.ref = class_get_classref_multiarray_of(dimension,elementclass.ref);
1842                                 else {
1843                                         common.cls = class_multiarray_of(dimension,elementclass.cls,true);
1844                                         if (!common.cls) {
1845                                                 log_text("XXX Coult not create array class");
1846                                                 assert(0);
1847                                         }
1848                                 }
1849                 /* DEBUG */ /* utf_display(common->name); printf("\n"); */
1850             }
1851                         else {
1852                                 common.any = y->typeclass.any;
1853                         }
1854         }
1855     }
1856     else {
1857         /* {We know that at least one of x or y is no array, so the
1858          *  result cannot be an array.} */
1859         
1860         changed |= typeinfo_merge_nonarrays(dest,
1861                                             &common,
1862                                             x->typeclass,y->typeclass,
1863                                             x->merged,y->merged);
1864
1865         dimension = 0;
1866         elementtype = 0;
1867         elementclass.any = NULL;
1868     }
1869
1870     /* Put the new values into dest if neccessary. */
1871
1872     if (dest->typeclass.any != common.any) {
1873         dest->typeclass.any = common.any;
1874         changed = true;
1875     }
1876     if (dest->dimension != dimension) {
1877         dest->dimension = dimension;
1878         changed = true;
1879     }
1880     if (dest->elementtype != elementtype) {
1881         dest->elementtype = elementtype;
1882         changed = true;
1883     }
1884     if (dest->elementclass.any != elementclass.any) {
1885         dest->elementclass.any = elementclass.any;
1886         changed = true;
1887     }
1888
1889     return changed;
1890 }
1891
1892
1893 /**********************************************************************/
1894 /* DEBUGGING HELPERS                                                  */
1895 /**********************************************************************/
1896
1897 #ifdef TYPEINFO_DEBUG
1898
1899 #if 0
1900 static int
1901 typeinfo_test_compare(classref_or_classinfo *a,classref_or_classinfo *b)
1902 {
1903     if (a->any == b->any) return 0;
1904     if (a->any < b->any) return -1;
1905     return +1;
1906 }
1907
1908 static void
1909 typeinfo_test_parse(typeinfo *info,char *str)
1910 {
1911     int num;
1912     int i;
1913     typeinfo *infobuf;
1914     u1 *typebuf;
1915     int returntype;
1916     utf *desc = utf_new_char(str);
1917     
1918     num = typeinfo_count_method_args(desc,false);
1919     if (num) {
1920         typebuf = DMNEW(u1,num);
1921         infobuf = DMNEW(typeinfo,num);
1922         
1923         typeinfo_init_from_method_args(desc,typebuf,infobuf,num,false,
1924                                        &returntype,info);
1925
1926         TYPEINFO_ALLOCMERGED(info->merged,num);
1927         info->merged->count = num;
1928
1929         for (i=0; i<num; ++i) {
1930             if (typebuf[i] != TYPE_ADDRESS) {
1931                 log_text("non-reference type in mergedlist");
1932                                 assert(0);
1933                         }
1934
1935             info->merged->list[i].any = infobuf[i].typeclass.any;
1936         }
1937         qsort(info->merged->list,num,sizeof(classref_or_classinfo),
1938               (int(*)(const void *,const void *))&typeinfo_test_compare);
1939     }
1940     else {
1941         typeinfo_init_from_method_args(desc,NULL,NULL,0,false,
1942                                        &returntype,info);
1943     }
1944 }
1945 #endif
1946
1947 #define TYPEINFO_TEST_BUFLEN  4000
1948
1949 static bool
1950 typeinfo_equal(typeinfo *x,typeinfo *y)
1951 {
1952     int i;
1953     
1954     if (x->typeclass.any != y->typeclass.any) return false;
1955     if (x->dimension != y->dimension) return false;
1956     if (x->dimension) {
1957         if (x->elementclass.any != y->elementclass.any) return false;
1958         if (x->elementtype != y->elementtype) return false;
1959     }
1960
1961     if (TYPEINFO_IS_NEWOBJECT(*x))
1962         if (TYPEINFO_NEWOBJECT_INSTRUCTION(*x)
1963             != TYPEINFO_NEWOBJECT_INSTRUCTION(*y))
1964             return false;
1965
1966     if (x->merged || y->merged) {
1967         if (!(x->merged && y->merged)) return false;
1968         if (x->merged->count != y->merged->count) return false;
1969         for (i=0; i<x->merged->count; ++i)
1970             if (x->merged->list[i].any != y->merged->list[i].any)
1971                 return false;
1972     }
1973     return true;
1974 }
1975
1976 static void
1977 typeinfo_testmerge(typeinfo *a,typeinfo *b,typeinfo *result,int *failed)
1978 {
1979     typeinfo dest;
1980     bool changed,changed_should_be;
1981
1982     TYPEINFO_CLONE(*a,dest);
1983     
1984     printf("\n          ");
1985     typeinfo_print_short(stdout,&dest);
1986     printf("\n          ");
1987     typeinfo_print_short(stdout,b);
1988     printf("\n");
1989
1990     changed = (typeinfo_merge(&dest,b)) ? 1 : 0;
1991     changed_should_be = (!typeinfo_equal(&dest,a)) ? 1 : 0;
1992
1993     printf("          %s\n",(changed) ? "changed" : "=");
1994
1995     if (typeinfo_equal(&dest,result)) {
1996         printf("OK        ");
1997         typeinfo_print_short(stdout,&dest);
1998         printf("\n");
1999         if (changed != changed_should_be) {
2000             printf("WRONG RETURN VALUE!\n");
2001             (*failed)++;
2002         }
2003     }
2004     else {
2005         printf("RESULT    ");
2006         typeinfo_print_short(stdout,&dest);
2007         printf("\n");
2008         printf("SHOULD BE ");
2009         typeinfo_print_short(stdout,result);
2010         printf("\n");
2011         (*failed)++;
2012     }
2013 }
2014
2015 #if 0
2016 static void
2017 typeinfo_inc_dimension(typeinfo *info)
2018 {
2019     if (info->dimension++ == 0) {
2020         info->elementtype = ARRAYTYPE_OBJECT;
2021         info->elementclass = info->typeclass;
2022     }
2023     info->typeclass = class_array_of(info->typeclass,true);
2024 }
2025 #endif
2026
2027 #define TYPEINFO_TEST_MAXDIM  10
2028
2029 static void
2030 typeinfo_testrun(char *filename)
2031 {
2032     char buf[TYPEINFO_TEST_BUFLEN];
2033     char bufa[TYPEINFO_TEST_BUFLEN];
2034     char bufb[TYPEINFO_TEST_BUFLEN];
2035     char bufc[TYPEINFO_TEST_BUFLEN];
2036     typeinfo a,b,c;
2037     int maxdim;
2038     int failed = 0;
2039     FILE *file = fopen(filename,"rt");
2040         int res;
2041     
2042     if (!file) {
2043         log_text("could not open typeinfo test file");
2044                 assert(0);
2045         }
2046
2047     while (fgets(buf,TYPEINFO_TEST_BUFLEN,file)) {
2048         if (buf[0] == '#' || !strlen(buf))
2049             continue;
2050         
2051         res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc);
2052         if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc)) {
2053             log_text("Invalid line in typeinfo test file (none of empty, comment or test)");
2054                         assert(0);
2055                 }
2056
2057 #if 0
2058         typeinfo_test_parse(&a,bufa);
2059         typeinfo_test_parse(&b,bufb);
2060         typeinfo_test_parse(&c,bufc);
2061 #endif
2062 #if 0
2063         do {
2064 #endif
2065             typeinfo_testmerge(&a,&b,&c,&failed); /* check result */
2066             typeinfo_testmerge(&b,&a,&c,&failed); /* check commutativity */
2067
2068             if (TYPEINFO_IS_NULLTYPE(a)) break;
2069             if (TYPEINFO_IS_NULLTYPE(b)) break;
2070             if (TYPEINFO_IS_NULLTYPE(c)) break;
2071             
2072             maxdim = a.dimension;
2073             if (b.dimension > maxdim) maxdim = b.dimension;
2074             if (c.dimension > maxdim) maxdim = c.dimension;
2075
2076 #if 0
2077             if (maxdim < TYPEINFO_TEST_MAXDIM) {
2078                 typeinfo_inc_dimension(&a);
2079                 typeinfo_inc_dimension(&b);
2080                 typeinfo_inc_dimension(&c);
2081             }
2082         } while (maxdim < TYPEINFO_TEST_MAXDIM);
2083 #endif
2084     }
2085
2086     fclose(file);
2087
2088     if (failed) {
2089         fprintf(stderr,"Failed typeinfo_merge tests: %d\n",failed);
2090         log_text("Failed test");
2091                 assert(0);
2092     }
2093 }
2094
2095 void
2096 typeinfo_test()
2097 {
2098     log_text("Running typeinfo test file...");
2099     typeinfo_testrun("typeinfo.tst");
2100     log_text("Finished typeinfo test file.");
2101 }
2102
2103 #if 0
2104 void
2105 typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc)
2106 {
2107     typeinfo_init_from_descriptor(info,desc,desc+strlen(desc));
2108 }
2109 #endif
2110
2111 #define TYPEINFO_MAXINDENT  80
2112
2113 void
2114 typeinfo_print_class(FILE *file,classref_or_classinfo c)
2115 {
2116         /*fprintf(file,"<class %p>",c.any);*/
2117
2118         if (!c.any) {
2119                 fprintf(file,"<null>");
2120         }
2121         else {
2122                 if (IS_CLASSREF(c)) {
2123                         fprintf(file,"<ref>");
2124                         utf_fprint(file,c.ref->name);
2125                 }
2126                 else {
2127                         utf_fprint(file,c.cls->name);
2128                 }
2129         }
2130 }
2131
2132 void
2133 typeinfo_print(FILE *file,typeinfo *info,int indent)
2134 {
2135     int i;
2136     char ind[TYPEINFO_MAXINDENT + 1];
2137     instruction *ins;
2138         basicblock *bptr;
2139
2140     if (indent > TYPEINFO_MAXINDENT) indent = TYPEINFO_MAXINDENT;
2141     
2142     for (i=0; i<indent; ++i)
2143         ind[i] = ' ';
2144     ind[i] = (char) 0;
2145     
2146     if (TYPEINFO_IS_PRIMITIVE(*info)) {
2147                 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
2148                 if (bptr)
2149                         fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->debug_nr);
2150                 else
2151                         fprintf(file,"%sprimitive\n",ind);
2152         return;
2153     }
2154     
2155     if (TYPEINFO_IS_NULLTYPE(*info)) {
2156         fprintf(file,"%snull\n",ind);
2157         return;
2158     }
2159
2160     if (TYPEINFO_IS_NEWOBJECT(*info)) {
2161         ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
2162         if (ins) {
2163             fprintf(file,"%sNEW(%p):",ind,(void*)ins);
2164                         typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].val.a));
2165             fprintf(file,"\n");
2166         }
2167         else {
2168             fprintf(file,"%sNEW(this)",ind);
2169         }
2170         return;
2171     }
2172
2173     fprintf(file,"%sClass:      ",ind);
2174         typeinfo_print_class(file,info->typeclass);
2175     fprintf(file,"\n");
2176
2177     if (TYPEINFO_IS_ARRAY(*info)) {
2178         fprintf(file,"%sDimension:    %d",ind,(int)info->dimension);
2179         fprintf(file,"\n%sElements:     ",ind);
2180         switch (info->elementtype) {
2181           case ARRAYTYPE_INT     : fprintf(file,"int\n"); break;
2182           case ARRAYTYPE_LONG    : fprintf(file,"long\n"); break;
2183           case ARRAYTYPE_FLOAT   : fprintf(file,"float\n"); break;
2184           case ARRAYTYPE_DOUBLE  : fprintf(file,"double\n"); break;
2185           case ARRAYTYPE_BYTE    : fprintf(file,"byte\n"); break;
2186           case ARRAYTYPE_CHAR    : fprintf(file,"char\n"); break;
2187           case ARRAYTYPE_SHORT   : fprintf(file,"short\n"); break;
2188           case ARRAYTYPE_BOOLEAN : fprintf(file,"boolean\n"); break;
2189               
2190           case ARRAYTYPE_OBJECT:
2191                           typeinfo_print_class(file,info->elementclass);
2192               fprintf(file,"\n");
2193               break;
2194               
2195           default:
2196               fprintf(file,"INVALID ARRAYTYPE!\n");
2197         }
2198     }
2199
2200     if (info->merged) {
2201         fprintf(file,"%sMerged:     ",ind);
2202         for (i=0; i<info->merged->count; ++i) {
2203             if (i) fprintf(file,", ");
2204                         typeinfo_print_class(file,info->merged->list[i]);
2205         }
2206         fprintf(file,"\n");
2207     }
2208 }
2209
2210 void
2211 typeinfo_print_short(FILE *file,typeinfo *info)
2212 {
2213     int i;
2214     instruction *ins;
2215         basicblock *bptr;
2216
2217         /*fprintf(file,"<typeinfo %p>",info);*/
2218
2219         if (!info) {
2220                 fprintf(file,"(typeinfo*)NULL");
2221                 return;
2222         }
2223
2224     if (TYPEINFO_IS_PRIMITIVE(*info)) {
2225                 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
2226                 if (bptr)
2227                         fprintf(file,"ret(L%03d)",bptr->debug_nr);
2228                 else
2229                         fprintf(file,"primitive");
2230         return;
2231     }
2232     
2233     if (TYPEINFO_IS_NULLTYPE(*info)) {
2234         fprintf(file,"null");
2235         return;
2236     }
2237     
2238     if (TYPEINFO_IS_NEWOBJECT(*info)) {
2239         ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
2240         if (ins) {
2241                         /*fprintf(file,"<ins %p>",ins);*/
2242             fprintf(file,"NEW(%p):",(void*)ins);
2243                         typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].val.a));
2244         }
2245         else
2246             fprintf(file,"NEW(this)");
2247         return;
2248     }
2249
2250     typeinfo_print_class(file,info->typeclass);
2251
2252     if (info->merged) {
2253         fprintf(file,"{");
2254         for (i=0; i<info->merged->count; ++i) {
2255             if (i) fprintf(file,",");
2256                         typeinfo_print_class(file,info->merged->list[i]);
2257         }
2258         fprintf(file,"}");
2259     }
2260 }
2261
2262 void
2263 typeinfo_print_type(FILE *file,int type,typeinfo *info)
2264 {
2265     switch (type) {
2266       case TYPE_VOID:   fprintf(file,"V"); break;
2267       case TYPE_INT:    fprintf(file,"I"); break;
2268       case TYPE_FLOAT:  fprintf(file,"F"); break;
2269       case TYPE_DOUBLE: fprintf(file,"D"); break;
2270       case TYPE_LONG:   fprintf(file,"J"); break;
2271       case TYPE_ADDRESS:
2272                   typeinfo_print_short(file,info);
2273           break;
2274           
2275       default:
2276           fprintf(file,"!");
2277     }
2278 }
2279
2280 void
2281 typeinfo_print_stacktype(FILE *file,int type,typeinfo *info)
2282 {
2283         TYPEINFO_ASSERT(file);
2284         TYPEINFO_ASSERT(type != TYPE_ADDRESS || info != NULL);
2285         if (type == TYPE_ADDRESS && TYPEINFO_IS_PRIMITIVE(*info)) {     
2286                 typeinfo_retaddr_set *set = (typeinfo_retaddr_set*)
2287                         TYPEINFO_RETURNADDRESS(*info);
2288                 if (set) {
2289                         fprintf(file,"ret(L%03d",((basicblock*)(set->addr))->debug_nr);
2290                         set = set->alt;
2291                         while (set) {
2292                                 fprintf(file,"|L%03d",((basicblock*)(set->addr))->debug_nr);
2293                                 set = set->alt;
2294                         }
2295                 }
2296                 else {
2297                         fprintf(file,"ret(<NULL>");
2298                 }
2299                 fprintf(file,")");
2300         }
2301         else
2302                 typeinfo_print_type(file,type,info);
2303 }
2304
2305 void
2306 typedescriptor_print(FILE *file,typedescriptor *td)
2307 {
2308         typeinfo_print_type(file,td->type,&(td->info));
2309 }
2310
2311 void
2312 typevector_print(FILE *file,typevector *vec,int size)
2313 {
2314     int i;
2315
2316         fprintf(file,"[%d]",vec->k);
2317     for (i=0; i<size; ++i) {
2318                 fprintf(file," %d=",i);
2319         typedescriptor_print(file,vec->td + i);
2320     }
2321 }
2322
2323 void
2324 typevectorset_print(FILE *file,typevector *set,int size)
2325 {
2326     int i;
2327         typevector *vec;
2328
2329         fprintf(file,"[%d",set->k);
2330         vec = set->alt;
2331         while (vec) {
2332                 fprintf(file,"|%d",vec->k);
2333                 vec = vec->alt;
2334         }
2335         fprintf(file,"]");
2336         
2337     for (i=0; i<size; ++i) {
2338                 fprintf(file," %d=",i);
2339         typedescriptor_print(file,set->td + i);
2340                 vec = set->alt;
2341                 while (vec) {
2342                         fprintf(file,"|");
2343                         typedescriptor_print(file,vec->td + i);
2344                         vec = vec->alt;
2345                 }
2346     }
2347 }
2348
2349 #endif /* TYPEINFO_DEBUG */
2350
2351
2352 /*
2353  * These are local overrides for various environment variables in Emacs.
2354  * Please do not remove this and leave it at the end of the file, where
2355  * Emacs will automagically detect them.
2356  * ---------------------------------------------------------------------
2357  * Local variables:
2358  * mode: c
2359  * indent-tabs-mode: t
2360  * c-basic-offset: 4
2361  * tab-width: 4
2362  * End:
2363  */