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