1 /* src/vm/jit/verify/typeinfo.c - type system used by the type checker
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
8 This file is part of CACAO.
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.
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.
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
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Edwin Steiner
29 $Id: typeinfo.c 2810 2005-06-23 14:03:24Z edwin $
36 #include "mm/memory.h"
37 #include "toolbox/logging.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 #include "vm/exceptions.h"
48 /* check if a linked class is an array class. Only use for linked classes! */
49 #define CLASSINFO_IS_ARRAY(clsinfo) ((clsinfo)->vftbl->arraydesc != NULL)
51 /* check if a linked class implements the interface with the given index */
52 #define CLASSINFO_IMPLEMENTS_INTERFACE(cls,index) \
53 ( ((index) < (cls)->vftbl->interfacetablelength) \
54 && (VFTBLINTERFACETABLE((cls)->vftbl,(index)) != NULL) )
56 /******************************************************************************/
58 /******************************************************************************/
61 #define TYPEINFO_ASSERT(cond) assert(cond)
63 #define TYPEINFO_ASSERT(cond)
66 /**********************************************************************/
67 /* TYPEVECTOR FUNCTIONS */
68 /**********************************************************************/
70 /* typevectorset_copy **********************************************************
72 Return a copy of the given typevector set.
75 src..............typevector set to copy, must be != NULL
76 k................k-index to set in first typevector of resulting set
77 size.............number of elements per typevector
80 a pointer to the new typevector set
83 This function recursively invokes itself with increasing k-index to
84 copy the alternative typevectors in the given set.
86 *******************************************************************************/
89 typevectorset_copy(typevector *src,int k,int size)
95 dst = DNEW_TYPEVECTOR(size);
96 memcpy(dst,src,TYPEVECTOR_SIZE(size));
99 dst->alt = typevectorset_copy(src->alt,k+1,size);
103 /* typevectorset_checktype *****************************************************
105 Check if all typevectors contain a given type at a given index.
108 vec..............typevector set, must be != NULL
109 index............index of component to check
110 type.............TYPE_* constant to check against
113 true if all typevectors in the set contain TYPE at INDEX,
116 *******************************************************************************/
119 typevectorset_checktype(typevector *vec,int index,int type)
121 TYPEINFO_ASSERT(vec);
123 if (vec->td[index].type != type)
125 } while ((vec = vec->alt) != NULL);
129 /* typevectorset_checkreference ************************************************
131 Check if all typevectors contain a reference at a given index.
134 vec..............typevector set, must be != NULL
135 index............index of component to check
138 true if all typevectors in the set contain a reference at INDEX,
141 *******************************************************************************/
144 typevectorset_checkreference(typevector *vec,int index)
146 TYPEINFO_ASSERT(vec);
148 if (!TYPEDESC_IS_REFERENCE(vec->td[index]))
150 } while ((vec = vec->alt) != NULL);
154 /* typevectorset_checkretaddr **************************************************
156 Check if all typevectors contain a returnAddress at a given index.
159 vec..............typevector set, must be != NULL
160 index............index of component to check
163 true if all typevectors in the set contain a returnAddress at INDEX,
166 *******************************************************************************/
169 typevectorset_checkretaddr(typevector *vec,int index)
171 TYPEINFO_ASSERT(vec);
173 if (!TYPEDESC_IS_RETURNADDRESS(vec->td[index]))
175 } while ((vec = vec->alt) != NULL);
179 /* typevectorset_copymergedtype ************************************************
181 Merge the types at a given index in the typevectors of a set and
182 copy the result to a destination typeinfo.
185 m................method for exception messages
186 vec..............typevector set, must be != NULL
187 index............index of component to merge
190 *dst.............destination typeinfo, receives the merge result
193 the TYPE_* constant of the resulting type
194 TYPE_VOID if incompatible types were contained at INDEX in VEC, or
195 -1...............an exception has been thrown
197 *******************************************************************************/
200 typevectorset_copymergedtype(methodinfo *m,typevector *vec,int index,typeinfo *dst)
205 TYPEINFO_ASSERT(vec);
206 TYPEINFO_ASSERT(dst);
208 td = vec->td + index;
210 TYPEINFO_COPY(td->info,*dst);
215 primitive = TYPEINFO_IS_PRIMITIVE(*dst) ? 1 : 0;
217 while ((vec = vec->alt) != NULL) {
218 td = vec->td + index;
219 if (type != td->type)
222 if (type == TYPE_ADDRESS) {
223 if ((TYPEINFO_IS_PRIMITIVE(td->info) ? 1 : 0) != primitive)
225 /* there cannot be any merge errors now. In the worst case */
226 /* we either get a returnAddress type or a j.l.O reference */
227 if (typeinfo_merge(m,dst,&(td->info)) == typecheck_FAIL)
235 /* typevectorset_mergedtype ****************************************************
237 Return the merged type of the types at a given index in the typevectors
241 m................method for exception messages
242 vec..............typevector set, must be != NULL
243 index............index of component to merge
244 temp.............pointer to a typeinfo that may be used to merge the
248 *result..........set to the address of a typeinfo containing the
252 the TYPE_* constant of the resulting type
253 TYPE_VOID if incompatible types were contained at INDEX in VEC, or
254 -1...............an exception has been thrown
257 This function should be more efficient than typevectorset_copymergedtype
258 assuming that most typevector sets contain exactly one typevector.
260 *******************************************************************************/
263 typevectorset_mergedtype(methodinfo *m,typevector *vec,int index,typeinfo *temp,typeinfo **result)
265 TYPEINFO_ASSERT(vec);
266 TYPEINFO_ASSERT(temp);
267 TYPEINFO_ASSERT(result);
271 return typevectorset_copymergedtype(m,vec,index,temp);
274 *result = &(vec->td[index].info);
275 return vec->td[index].type;
278 /* typevectorset_store *********************************************************
280 Store a type at a given index in the typevectors of a set.
281 This function stores the same type in all typevectors of the set.
282 DO NOT use it to store returnAddress types!
283 DO NOT use it to store two-word types!
286 vec..............typevector set, must be != NULL
287 index............index of component to set
288 type.............TYPE_* constant of type to set
289 info.............typeinfo of type to set, may be NULL,
293 If there is a two-word type stored at INDEX-1 in any typevector, it is
294 changed to TYPE_VOID (because its upper half has become invalid).
296 The components at INDEX+1 are _not_ touched, regardless of TYPE.
298 *******************************************************************************/
301 typevectorset_store(typevector *vec,int index,int type,typeinfo *info)
303 TYPEINFO_ASSERT(vec);
304 TYPEINFO_ASSERT((info && !TYPEINFO_IS_PRIMITIVE(*info)) || type != TYPE_ADR);
307 vec->td[index].type = type;
309 TYPEINFO_COPY(*info,vec->td[index].info);
310 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
311 vec->td[index-1].type = TYPE_VOID;
312 } while ((vec = vec->alt) != NULL);
315 /* typevectorset_store_retaddr *************************************************
317 Store a returnAddress type at a given index in the typevectors of a set.
318 Each possible returnAddress of the type is stored in the corresponding
319 typevector of the set.
322 vec..............typevector set, must be != NULL
323 index............index of component to set
324 info.............typeinfo of the returnAddress. This typeinfo must
325 contain a return address set with at least as many
326 entries as there are typevectors in VEC.
329 If there is a two-word type stored at INDEX-1 in any typevector, it is
330 changed to TYPE_VOID (because its upper half has become invalid).
332 *******************************************************************************/
335 typevectorset_store_retaddr(typevector *vec,int index,typeinfo *info)
337 typeinfo_retaddr_set *adr;
339 TYPEINFO_ASSERT(vec);
340 TYPEINFO_ASSERT(TYPEINFO_IS_PRIMITIVE(*info));
342 adr = (typeinfo_retaddr_set*) TYPEINFO_RETURNADDRESS(*info);
344 TYPEINFO_ASSERT(adr);
346 vec->td[index].type = TYPE_ADDRESS;
347 TYPEINFO_INIT_RETURNADDRESS(vec->td[index].info,adr->addr);
348 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
349 vec->td[index-1].type = TYPE_VOID;
351 } while ((vec = vec->alt) != NULL);
354 /* typevectorset_store_twoword *************************************************
356 Store a two-word type at a given index in the typevectors of a set.
357 This function stores the same type in all typevectors of the set.
360 vec..............typevector set, must be != NULL
361 index............index of component to set
362 type.............TYPE_* constant of type to set (TYPE_LONG, TYPE_DOUBLE)
365 If there is a two-word type stored at INDEX-1 in any typevector, it is
366 changed to TYPE_VOID (because its upper half has become invalid).
368 The components at INDEX+1 are set to TYPE_VOID.
370 *******************************************************************************/
373 typevectorset_store_twoword(typevector *vec,int index,int type)
375 TYPEINFO_ASSERT(vec);
376 TYPEINFO_ASSERT(type == TYPE_LONG || type == TYPE_DOUBLE);
379 vec->td[index].type = type;
380 vec->td[index+1].type = TYPE_VOID;
381 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
382 vec->td[index-1].type = TYPE_VOID;
383 } while ((vec = vec->alt) != NULL);
386 /* typevectorset_init_object ***************************************************
388 Replace all uninitialized object types in the typevector set which were
389 created by the given instruction by initialized object types.
392 set..............typevector set
393 ins..............instruction which created the uninitialized object type
394 initclass........class of the initialized object type to set
395 size.............number of elements per typevector
398 true.............success
399 false............an exception has been thrown
401 XXX maybe we should do the lazy resolving before calling this function
403 *******************************************************************************/
406 typevectorset_init_object(typevector *set,void *ins,
407 classref_or_classinfo initclass,
412 for (;set; set=set->alt) {
413 for (i=0; i<size; ++i) {
414 if (set->td[i].type == TYPE_ADR
415 && TYPEINFO_IS_NEWOBJECT(set->td[i].info)
416 && TYPEINFO_NEWOBJECT_INSTRUCTION(set->td[i].info) == ins)
418 if (!typeinfo_init_class(&(set->td[i].info),initclass))
426 /* typevector_merge ************************************************************
428 Merge a typevector with another one.
429 The given typevectors must have the same number of components.
432 m................method for exception messages
433 dst..............the first typevector
434 y................the second typevector
435 size.............number of elements per typevector
438 *dst.............the resulting typevector
441 typecheck_TRUE...dst has been modified
442 typecheck_FALSE..dst has not been modified
443 typecheck_FAIL...an exception has been thrown
445 *******************************************************************************/
448 typevector_merge(methodinfo *m,typevector *dst,typevector *y,int size)
450 bool changed = false;
453 typedescriptor *a = dst->td;
454 typedescriptor *b = y->td;
456 if (a->type != TYPE_VOID && a->type != b->type) {
460 else if (a->type == TYPE_ADDRESS) {
461 if (TYPEINFO_IS_PRIMITIVE(a->info)) {
462 /* 'a' is a returnAddress */
463 if (!TYPEINFO_IS_PRIMITIVE(b->info)
464 || (TYPEINFO_RETURNADDRESS(a->info)
465 != TYPEINFO_RETURNADDRESS(b->info)))
472 /* 'a' is a reference */
473 if (TYPEINFO_IS_PRIMITIVE(b->info)) {
478 /* two reference types are merged. There cannot be */
479 /* a merge error. In the worst case we get j.l.O. */
480 r = typeinfo_merge(m,&(a->info),&(b->info));
481 if (r == typecheck_FAIL)
493 /* typevector_separable_from ***************************************************
495 Check if two typevectors are separable. Two typevectors are considered
496 separable if there is an index i for which both typevectors contain a
497 returnAddress type and the return addresses of the types are different.
498 The typevectors must have the same number of components.
501 a................the first typevector
502 b................the second typevector
503 size.............number of elements per typevector
506 true.............typevectors are separable
507 false............typevectors are not separable
509 *******************************************************************************/
512 typevector_separable_from(typevector *a,typevector *b,int size)
514 typedescriptor *tda = a->td;
515 typedescriptor *tdb = b->td;
516 for (;size--; tda++,tdb++) {
517 if (TYPEDESC_IS_RETURNADDRESS(*tda)
518 && TYPEDESC_IS_RETURNADDRESS(*tdb)
519 && TYPEINFO_RETURNADDRESS(tda->info)
520 != TYPEINFO_RETURNADDRESS(tdb->info))
526 /* typevectorset_add ***********************************************************
528 Add a typevector to a typevector set. The typevector is added at the end of
529 the set and the k-index of the typevector is set accordingly.
532 dst..............the typevector set to modify
533 v................the typevector to add
534 size.............number of elements per typevector
536 *******************************************************************************/
539 typevectorset_add(typevector *dst,typevector *v,int size)
541 TYPEINFO_ASSERT(dst);
546 dst->alt = DNEW_TYPEVECTOR(size);
547 memcpy(dst->alt,v,TYPEVECTOR_SIZE(size));
548 dst->alt->alt = NULL;
549 dst->alt->k = dst->k + 1;
552 /* typevectorset_select ********************************************************
554 Pick the typevectors from a set which contain a given return address.
557 set..............points to the location containing the typevector set.
559 index............index to check against the return address. All
560 typevectors must contain a returnAddress type at
562 retaddr..........the return address to select
565 *set.............receives the typevector set after removing the
566 selected typevectors.
569 a typevector set consisting of the selected typevectors.
571 *******************************************************************************/
574 typevectorset_select(typevector **set,int index,void *retaddr)
576 typevector *selected;
578 if (!*set) return NULL;
580 if (TYPEINFO_RETURNADDRESS((*set)->td[index].info) == retaddr) {
582 *set = selected->alt;
583 selected->alt = typevectorset_select(set,index,retaddr);
586 selected = typevectorset_select(&((*set)->alt),index,retaddr);
591 /* typevector_separable_with ***************************************************
593 Check if a typevector set would be separable after adding a given
594 typevector. A typevector set is considered separable if there is an
595 index i for which all typevectors in the set contain a returnAddress type,
596 and at least two different return addresses occurr at index i.
597 The typevectors must have the same number of components.
600 set..............the typevector set
601 add..............the typevector
602 size.............number of elements per typevector
605 true.............result would be separable
606 false............result would not be separable
608 *******************************************************************************/
611 typevectorset_separable_with(typevector *set,typevector *add,int size)
618 TYPEINFO_ASSERT(set);
619 TYPEINFO_ASSERT(add);
621 for (i=0; i<size; ++i) {
622 if (!TYPEDESC_IS_RETURNADDRESS(add->td[i]))
624 addr = TYPEINFO_RETURNADDRESS(add->td[i].info);
629 if (!TYPEDESC_IS_RETURNADDRESS(v->td[i]))
631 if (TYPEINFO_RETURNADDRESS(v->td[i].info) != addr)
635 if (separable) return true;
642 /* typevectorset_collapse ******************************************************
644 Collapse a typevector set into a single typevector by merging the
645 components of the typevectors at each index.
648 dst..............the type vector set
649 size.............number of elements per typevector
652 *dst.............the resulting typevector set (a single typevector)
655 typecheck_TRUE...dst has been modified
656 typecheck_FALSE..dst has not been modified
657 typecheck_FAIL...an exception has been thrown
659 *******************************************************************************/
662 typevectorset_collapse(methodinfo *m,typevector *dst,int size)
664 bool changed = false;
666 TYPEINFO_ASSERT(dst);
669 if (typevector_merge(m,dst,dst->alt,size) == typecheck_FAIL)
670 return typecheck_FAIL;
671 dst->alt = dst->alt->alt;
677 /**********************************************************************/
678 /* READ-ONLY FUNCTIONS */
679 /* The following functions don't change typeinfo data. */
680 /**********************************************************************/
683 typeinfo_is_array(typeinfo *info)
685 TYPEINFO_ASSERT(info);
686 return TYPEINFO_IS_ARRAY(*info);
690 typeinfo_is_primitive_array(typeinfo *info,int arraytype)
692 TYPEINFO_ASSERT(info);
693 return TYPEINFO_IS_PRIMITIVE_ARRAY(*info,arraytype);
697 typeinfo_is_array_of_refs(typeinfo *info)
699 TYPEINFO_ASSERT(info);
700 return TYPEINFO_IS_ARRAY_OF_REFS(*info);
703 /* interface_extends_interface *************************************************
705 Check if a resolved interface extends a given resolved interface.
708 cls..............the interface, must be linked
709 interf...........the interface to check against
712 true.............CLS extends INTERF
713 false............CLS does not extend INTERF
715 *******************************************************************************/
718 interface_extends_interface(classinfo *cls,classinfo *interf)
722 TYPEINFO_ASSERT(cls);
723 TYPEINFO_ASSERT(interf);
724 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
725 TYPEINFO_ASSERT((cls->flags & ACC_INTERFACE) != 0);
726 TYPEINFO_ASSERT(cls->linked);
728 /* first check direct superinterfaces */
729 for (i=0; i<cls->interfacescount; ++i) {
730 if (cls->interfaces[i].cls == interf)
734 /* check indirect superinterfaces */
735 for (i=0; i<cls->interfacescount; ++i) {
736 if (interface_extends_interface(cls->interfaces[i].cls,interf))
743 /* classinfo_implements_interface **********************************************
745 Check if a resolved class implements a given resolved interface.
748 cls..............the class
749 interf...........the interface
752 typecheck_TRUE...CLS implements INTERF
753 typecheck_FALSE..CLS does not implement INTERF
754 typecheck_FAIL...an exception has been thrown
756 *******************************************************************************/
758 static typecheck_result
759 classinfo_implements_interface(classinfo *cls,classinfo *interf)
761 TYPEINFO_ASSERT(cls);
762 TYPEINFO_ASSERT(interf);
763 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
766 if (!link_class(cls))
767 return typecheck_FAIL;
769 if (cls->flags & ACC_INTERFACE) {
770 /* cls is an interface */
772 return typecheck_TRUE;
774 /* check superinterfaces */
775 return interface_extends_interface(cls,interf);
778 TYPEINFO_ASSERT(cls->linked);
779 return CLASSINFO_IMPLEMENTS_INTERFACE(cls,interf->index);
782 /* mergedlist_implements_interface *********************************************
784 Check if all the classes in a given merged list implement a given resolved
788 merged...........the list of merged class types
789 interf...........the interface to check against
792 typecheck_TRUE...all classes implement INTERF
793 typecheck_FALSE..there is at least one class that does not implement
795 typecheck_MAYBE..check cannot be performed now because of unresolved
797 typecheck_FAIL...an exception has been thrown
799 *******************************************************************************/
801 static typecheck_result
802 mergedlist_implements_interface(typeinfo_mergedlist *merged,
806 classref_or_classinfo *mlist;
809 TYPEINFO_ASSERT(interf);
810 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
812 /* Check if there is an non-empty mergedlist. */
814 return typecheck_FALSE;
816 /* If all classinfos in the (non-empty) merged array implement the
817 * interface return true, otherwise false.
819 mlist = merged->list;
822 if (IS_CLASSREF(*mlist)) {
823 return typecheck_MAYBE;
825 r = classinfo_implements_interface((mlist++)->cls,interf);
826 if (r != typecheck_TRUE)
829 return typecheck_TRUE;
832 /* merged_implements_interface *************************************************
834 Check if a possible merged type implements a given resolved interface
838 typeclass........(common) class of the (merged) type
839 merged...........the list of merged class types
840 interf...........the interface to check against
843 typecheck_TRUE...the type implement INTERF
844 typecheck_FALSE..the type does not implement INTERF
845 typecheck_MAYBE..check cannot be performed now because of unresolved
847 typecheck_FAIL...an exception has been thrown
849 *******************************************************************************/
851 static typecheck_result
852 merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged,
857 /* primitive types don't support interfaces. */
859 return typecheck_FALSE;
861 /* the null type can be cast to any interface type. */
862 if (typeclass == pseudo_class_Null)
863 return typecheck_TRUE;
865 /* check if typeclass implements the interface. */
866 r = classinfo_implements_interface(typeclass,interf);
867 if (r != typecheck_FALSE)
870 /* check the mergedlist */
872 return typecheck_FALSE;
873 return mergedlist_implements_interface(merged,interf);
876 /* typeinfo_is_assignable_to_class *********************************************
878 Check if a type is assignable to a given class type.
881 value............the type of the value
882 dest.............the type of the destination
885 typecheck_TRUE...the type is assignable
886 typecheck_FALSE..the type is not assignable
887 typecheck_MAYBE..check cannot be performed now because of unresolved
889 typecheck_FAIL...an exception has been thrown
891 *******************************************************************************/
894 typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
896 classref_or_classinfo c;
900 TYPEINFO_ASSERT(value);
902 c = value->typeclass;
904 /* assignments of primitive values are not checked here. */
905 if (!c.any && !dest.any)
906 return typecheck_TRUE;
908 /* primitive and reference types are not assignment compatible. */
909 if (!c.any || !dest.any)
910 return typecheck_FALSE;
912 /* the null type can be assigned to any type */
913 if (TYPEINFO_IS_NULLTYPE(*value))
914 return typecheck_TRUE;
916 /* uninitialized objects are not assignable */
917 if (TYPEINFO_IS_NEWOBJECT(*value))
918 return typecheck_FALSE;
920 if (IS_CLASSREF(c)) {
921 /* The value type is an unresolved class reference. */
922 classname = c.ref->name;
925 classname = c.cls->name;
928 if (IS_CLASSREF(dest)) {
929 /* the destination type is an unresolved class reference */
930 /* In this case we cannot tell a lot about assignability. */
932 /* the common case of value and dest type having the same classname */
933 if (dest.ref->name == classname && !value->merged)
934 return typecheck_TRUE;
936 /* we cannot tell if value is assignable to dest, so we */
937 /* leave it up to the resolving code to check this */
938 return typecheck_MAYBE;
941 /* { we know that dest is a loaded class } */
943 if (IS_CLASSREF(c)) {
944 /* the value type is an unresolved class reference */
946 /* the common case of value and dest type having the same classname */
947 if (dest.cls->name == classname)
948 return typecheck_TRUE;
950 /* we cannot tell if value is assignable to dest, so we */
951 /* leave it up to the resolving code to check this */
952 return typecheck_MAYBE;
955 /* { we know that both c and dest are loaded classes } */
957 TYPEINFO_ASSERT(!IS_CLASSREF(c));
958 TYPEINFO_ASSERT(!IS_CLASSREF(dest));
962 TYPEINFO_ASSERT(cls->loaded);
963 TYPEINFO_ASSERT(dest.cls->loaded);
965 /* maybe we need to link the classes */
967 if (!link_class(cls))
968 return typecheck_FAIL;
969 if (!dest.cls->linked)
970 if (!link_class(dest.cls))
971 return typecheck_FAIL;
973 /* { we know that both c and dest are linked classes } */
974 TYPEINFO_ASSERT(cls->linked);
975 TYPEINFO_ASSERT(dest.cls->linked);
977 if (dest.cls->flags & ACC_INTERFACE) {
978 /* We are assigning to an interface type. */
979 return merged_implements_interface(cls,value->merged,dest.cls);
982 if (CLASSINFO_IS_ARRAY(dest.cls)) {
983 arraydescriptor *arraydesc = dest.cls->vftbl->arraydesc;
984 int dimension = arraydesc->dimension;
985 classinfo *elementclass = (arraydesc->elementvftbl)
986 ? arraydesc->elementvftbl->class : NULL;
988 /* We are assigning to an array type. */
989 if (!TYPEINFO_IS_ARRAY(*value))
990 return typecheck_FALSE;
992 /* {Both value and dest.cls are array types.} */
994 /* value must have at least the dimension of dest.cls. */
995 if (value->dimension < dimension)
996 return typecheck_FALSE;
998 if (value->dimension > dimension) {
999 /* value has higher dimension so we need to check
1000 * if its component array can be assigned to the
1001 * element type of dest.cls */
1003 if (!elementclass) return typecheck_FALSE;
1005 if (elementclass->flags & ACC_INTERFACE) {
1006 /* We are assigning to an interface type. */
1007 return classinfo_implements_interface(pseudo_class_Arraystub,
1011 /* We are assigning to a class type. */
1012 return class_issubclass(pseudo_class_Arraystub,elementclass);
1015 /* {value and dest.cls have the same dimension} */
1017 if (value->elementtype != arraydesc->elementtype)
1018 return typecheck_FALSE;
1020 if (value->elementclass.any) {
1021 /* We are assigning an array of objects so we have to
1022 * check if the elements are assignable.
1025 if (elementclass->flags & ACC_INTERFACE) {
1026 /* We are assigning to an interface type. */
1028 return merged_implements_interface(value->elementclass.cls,
1033 /* We are assigning to a class type. */
1034 return class_issubclass(value->elementclass.cls,elementclass);
1037 return typecheck_TRUE;
1040 /* {dest.cls is not an array} */
1041 /* {dest.cls is a loaded class} */
1043 /* If there are any unresolved references in the merged list, we cannot */
1044 /* tell if the assignment will be ok. */
1045 /* This can only happen when cls is java.lang.Object */
1046 if (cls == class_java_lang_Object && value->merged) {
1047 classref_or_classinfo *mlist = value->merged->list;
1048 int i = value->merged->count;
1050 if (IS_CLASSREF(*mlist++))
1051 return typecheck_MAYBE;
1054 /* We are assigning to a class type */
1055 if (cls->flags & ACC_INTERFACE)
1056 cls = class_java_lang_Object;
1058 return class_issubclass(cls,dest.cls);
1061 /* typeinfo_is_assignable ******************************************************
1063 Check if a type is assignable to a given type.
1066 value............the type of the value
1067 dest.............the type of the destination, must not be a merged type
1070 typecheck_TRUE...the type is assignable
1071 typecheck_FALSE..the type is not assignable
1072 typecheck_MAYBE..check cannot be performed now because of unresolved
1074 typecheck_FAIL...an exception has been thrown
1076 *******************************************************************************/
1079 typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
1081 TYPEINFO_ASSERT(value);
1082 TYPEINFO_ASSERT(dest);
1083 TYPEINFO_ASSERT(dest->merged == NULL);
1085 return typeinfo_is_assignable_to_class(value,dest->typeclass);
1088 /**********************************************************************/
1089 /* INITIALIZATION FUNCTIONS */
1090 /* The following functions fill in uninitialized typeinfo structures. */
1091 /**********************************************************************/
1093 /* typeinfo_init_class *********************************************************
1095 Initialize a typeinfo to a possibly unresolved class type.
1098 c................the class type
1101 *info............is initialized
1104 true.............success
1105 false............an exception has been thrown
1107 *******************************************************************************/
1110 typeinfo_init_class(typeinfo *info,classref_or_classinfo c)
1116 TYPEINFO_ASSERT(c.any);
1117 TYPEINFO_ASSERT(info);
1119 /* if necessary, try to resolve lazily */
1120 if (!resolve_classref_or_classinfo(NULL /* XXX should now method */,
1121 c,resolveLazy,false,true,&cls))
1127 TYPEINFO_INIT_CLASSINFO(*info,cls);
1131 /* {the type could no be resolved lazily} */
1133 info->typeclass.ref = c.ref;
1134 info->elementclass.any = NULL;
1135 info->dimension = 0;
1136 info->merged = NULL;
1138 /* handle array type references */
1139 utf_ptr = c.ref->name->text;
1140 len = c.ref->name->blength;
1141 if (*utf_ptr == '[') {
1142 /* count dimensions */
1143 while (*utf_ptr == '[') {
1148 if (*utf_ptr == 'L') {
1151 info->elementtype = ARRAYTYPE_OBJECT;
1152 info->elementclass.ref = class_get_classref(c.ref->referer,utf_new(utf_ptr,len));
1155 /* an array with primitive element type */
1156 /* should have been resolved above */
1157 TYPEINFO_ASSERT(false);
1164 typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info)
1166 TYPEINFO_ASSERT(desc);
1168 #ifdef TYPEINFO_VERBOSE
1169 fprintf(stderr,"typeinfo_init_from_typedesc(");
1170 descriptor_debug_print_typedesc(stderr,desc);
1171 fprintf(stderr,")\n");
1178 if (desc->type == TYPE_ADR) {
1179 TYPEINFO_ASSERT(desc->classref);
1180 if (!typeinfo_init_class(info,CLASSREF_OR_CLASSINFO(desc->classref)))
1184 TYPEINFO_INIT_PRIMITIVE(*info);
1191 typeinfo_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo *infobuf,
1192 int buflen,bool twoword,
1193 u1 *returntype,typeinfo *returntypeinfo)
1198 TYPEINFO_ASSERT(desc);
1199 TYPEINFO_ASSERT(typebuf);
1200 TYPEINFO_ASSERT(infobuf);
1202 #ifdef TYPEINFO_VERBOSE
1203 fprintf(stderr,"typeinfo_init_from_methoddesc(");
1204 descriptor_debug_print_methoddesc(stderr,desc);
1205 fprintf(stderr,")\n");
1208 /* check arguments */
1209 for (i=0; i<desc->paramcount; ++i) {
1210 if (++args > buflen) {
1211 *exceptionptr = new_internalerror("Buffer too small for method arguments.");
1215 if (!typeinfo_init_from_typedesc(desc->paramtypes + i,typebuf++,infobuf++))
1218 if (twoword && (typebuf[-1] == TYPE_LONG || typebuf[-1] == TYPE_DOUBLE)) {
1219 if (++args > buflen) {
1220 *exceptionptr = new_internalerror("Buffer too small for method arguments.");
1224 *typebuf++ = TYPE_VOID;
1225 TYPEINFO_INIT_PRIMITIVE(*infobuf);
1230 /* check returntype */
1232 if (!typeinfo_init_from_typedesc(&(desc->returntype),returntype,returntypeinfo))
1240 typedescriptor_init_from_typedesc(typedescriptor *td,
1243 td->type = desc->type;
1244 if (td->type == TYPE_ADR) {
1245 if (!typeinfo_init_class(&(td->info),CLASSREF_OR_CLASSINFO(desc->classref)))
1249 TYPEINFO_INIT_PRIMITIVE(td->info);
1255 typedescriptors_init_from_methoddesc(typedescriptor *td,
1257 int buflen,bool twoword,int startindex,
1258 typedescriptor *returntype)
1263 /* check arguments */
1264 for (i=startindex; i<desc->paramcount; ++i) {
1265 if (++args > buflen) {
1266 *exceptionptr = new_internalerror("Buffer too small for method arguments.");
1270 if (!typedescriptor_init_from_typedesc(td,desc->paramtypes + i))
1274 if (twoword && (td[-1].type == TYPE_LONG || td[-1].type == TYPE_DOUBLE)) {
1275 if (++args > buflen) {
1276 *exceptionptr = new_internalerror("Buffer too small for method arguments.");
1280 td->type = TYPE_VOID;
1281 TYPEINFO_INIT_PRIMITIVE(td->info);
1286 /* check returntype */
1288 if (!typedescriptor_init_from_typedesc(returntype,&(desc->returntype)))
1296 typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
1298 if (TYPEINFO_IS_NULLTYPE(*srcarray)) {
1299 TYPEINFO_INIT_NULLTYPE(*dst);
1303 if (!TYPEINFO_IS_ARRAY(*srcarray)) {
1304 *exceptionptr = new_internalerror("XXX Trying to access component of non-array");
1308 if (IS_CLASSREF(srcarray->typeclass)) {
1309 constant_classref *comp;
1310 comp = class_get_classref_component_of(srcarray->typeclass.ref);
1313 if (!typeinfo_init_class(dst,CLASSREF_OR_CLASSINFO(comp)))
1317 TYPEINFO_INIT_PRIMITIVE(*dst);
1323 if (!srcarray->typeclass.cls->linked) {
1324 if (!link_class(srcarray->typeclass.cls)) {
1329 TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl);
1330 TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl->arraydesc);
1332 comp = srcarray->typeclass.cls->vftbl->arraydesc->componentvftbl;
1334 TYPEINFO_INIT_CLASSINFO(*dst,comp->class);
1336 TYPEINFO_INIT_PRIMITIVE(*dst);
1339 dst->merged = srcarray->merged; /* XXX should we do a deep copy? */
1343 /* typeinfo_clone **************************************************************
1345 Create a deep copy of a typeinfo struct.
1348 src..............the typeinfo to copy
1351 *dest............receives the copy
1354 If src == dest this function is a nop.
1356 *******************************************************************************/
1359 typeinfo_clone(typeinfo *src,typeinfo *dest)
1362 classref_or_classinfo *srclist,*destlist;
1370 count = src->merged->count;
1371 TYPEINFO_ALLOCMERGED(dest->merged,count);
1372 dest->merged->count = count;
1374 srclist = src->merged->list;
1375 destlist = dest->merged->list;
1377 *destlist++ = *srclist++;
1381 /**********************************************************************/
1382 /* MISCELLANEOUS FUNCTIONS */
1383 /**********************************************************************/
1385 /* typeinfo_free ***************************************************************
1387 Free memory referenced by the given typeinfo. The typeinfo itself is not
1391 info.............the typeinfo
1393 *******************************************************************************/
1396 typeinfo_free(typeinfo *info)
1398 TYPEINFO_FREEMERGED_IF_ANY(info->merged);
1399 info->merged = NULL;
1402 /**********************************************************************/
1403 /* MERGING FUNCTIONS */
1404 /* The following functions are used to merge the types represented by */
1405 /* two typeinfo structures into one typeinfo structure. */
1406 /**********************************************************************/
1410 typeinfo_merge_error(methodinfo *m,char *str,typeinfo *x,typeinfo *y) {
1411 #ifdef TYPEINFO_VERBOSE
1412 fprintf(stderr,"Error in typeinfo_merge: %s\n",str);
1413 fprintf(stderr,"Typeinfo x:\n");
1414 typeinfo_print(stderr,x,1);
1415 fprintf(stderr,"Typeinfo y:\n");
1416 typeinfo_print(stderr,y,1);
1420 *exceptionptr = new_verifyerror(m,str);
1423 /* Condition: clsx != clsy. */
1424 /* Returns: true if dest was changed (currently always true). */
1427 typeinfo_merge_two(typeinfo *dest,classref_or_classinfo clsx,classref_or_classinfo clsy)
1429 TYPEINFO_ASSERT(dest);
1430 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1431 TYPEINFO_ALLOCMERGED(dest->merged,2);
1432 dest->merged->count = 2;
1434 TYPEINFO_ASSERT(clsx.any != clsy.any);
1436 if (clsx.any < clsy.any) {
1437 dest->merged->list[0] = clsx;
1438 dest->merged->list[1] = clsy;
1441 dest->merged->list[0] = clsy;
1442 dest->merged->list[1] = clsx;
1448 /* Returns: true if dest was changed. */
1451 typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classref_or_classinfo cls)
1454 typeinfo_mergedlist *newmerged;
1455 classref_or_classinfo *mlist,*newlist;
1460 /* Check if cls is already in the mergedlist m. */
1462 if ((mlist++)->any == cls.any) { /* XXX check equal classrefs? */
1463 /* cls is in the list, so m is the resulting mergedlist */
1464 if (dest->merged == m)
1467 /* We have to copy the mergedlist */
1468 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1470 TYPEINFO_ALLOCMERGED(dest->merged,count);
1471 dest->merged->count = count;
1472 newlist = dest->merged->list;
1475 *newlist++ = *mlist++;
1481 /* Add cls to the mergedlist. */
1483 TYPEINFO_ALLOCMERGED(newmerged,count+1);
1484 newmerged->count = count+1;
1485 newlist = newmerged->list;
1488 if (mlist->any > cls.any)
1490 *newlist++ = *mlist++;
1495 *newlist++ = *mlist++;
1498 /* Put the new mergedlist into dest. */
1499 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1500 dest->merged = newmerged;
1505 /* Returns: true if dest was changed. */
1508 typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
1509 typeinfo_mergedlist *y)
1513 typeinfo_mergedlist *temp,*result;
1514 classref_or_classinfo *clsx,*clsy,*newlist;
1516 /* count the elements that will be in the resulting list */
1517 /* (Both lists are sorted, equal elements are counted only once.) */
1522 while (countx && county) {
1523 if (clsx->any == clsy->any) {
1529 else if (clsx->any < clsy->any) {
1539 count += countx + county;
1541 /* {The new mergedlist will have count entries.} */
1543 if ((x->count != count) && (y->count == count)) {
1544 temp = x; x = y; y = temp;
1546 /* {If one of x,y is already the result it is x.} */
1547 if (x->count == count) {
1548 /* x->merged is equal to the result */
1549 if (x == dest->merged)
1552 if (!dest->merged || dest->merged->count != count) {
1553 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1554 TYPEINFO_ALLOCMERGED(dest->merged,count);
1555 dest->merged->count = count;
1558 newlist = dest->merged->list;
1561 *newlist++ = *clsx++;
1566 /* {We have to merge two lists.} */
1568 /* allocate the result list */
1569 TYPEINFO_ALLOCMERGED(result,count);
1570 result->count = count;
1571 newlist = result->list;
1573 /* merge the sorted lists */
1578 while (countx && county) {
1579 if (clsx->any == clsy->any) {
1580 *newlist++ = *clsx++;
1585 else if (clsx->any < clsy->any) {
1586 *newlist++ = *clsx++;
1590 *newlist++ = *clsy++;
1595 *newlist++ = *clsx++;
1597 *newlist++ = *clsy++;
1599 /* replace the list in dest with the result list */
1600 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1601 dest->merged = result;
1606 /* typeinfo_merge_nonarrays ****************************************************
1608 Merge two non-array types.
1611 x................the first type
1612 y................the second type
1613 mergedx..........merged list of the first type, may be NULL
1614 mergedy..........merged list of the descond type, may be NULL
1617 *dest............receives the resulting merged list
1618 *result..........receives the resulting type
1621 typecheck_TRUE...*dest has been modified
1622 typecheck_FALSE..*dest has not been modified
1623 typecheck_FAIL...an exception has been thrown
1626 RESULT is an extra parameter so it can point to dest->typeclass or to
1629 *******************************************************************************/
1631 static typecheck_result
1632 typeinfo_merge_nonarrays(typeinfo *dest,
1633 classref_or_classinfo *result,
1634 classref_or_classinfo x,classref_or_classinfo y,
1635 typeinfo_mergedlist *mergedx,
1636 typeinfo_mergedlist *mergedy)
1638 classref_or_classinfo t;
1639 classinfo *tcls,*common;
1640 typeinfo_mergedlist *tmerged;
1646 TYPEINFO_ASSERT(dest && result && x.any && y.any);
1647 TYPEINFO_ASSERT(x.cls != pseudo_class_Null);
1648 TYPEINFO_ASSERT(y.cls != pseudo_class_Null);
1649 TYPEINFO_ASSERT(x.cls != pseudo_class_New);
1650 TYPEINFO_ASSERT(y.cls != pseudo_class_New);
1652 /*--------------------------------------------------*/
1654 /*--------------------------------------------------*/
1656 /* Common case 1: x and y are the same class or class reference */
1657 /* (This case is very simple unless *both* x and y really represent
1658 * merges of subclasses of clsx==clsy.)
1660 if ( (x.any == y.any) && (!mergedx || !mergedy) ) {
1662 /* DEBUG */ /* log_text("return simple x"); */
1663 changed = (dest->merged != NULL);
1664 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1665 dest->merged = NULL;
1667 /* DEBUG */ /* log_text("returning"); */
1671 xname = (IS_CLASSREF(x)) ? x.ref->name : x.cls->name;
1672 yname = (IS_CLASSREF(y)) ? y.ref->name : y.cls->name;
1674 /* Common case 2: xname == yname, at least one unresolved */
1675 if ((IS_CLASSREF(x) || IS_CLASSREF(y)) && (xname == yname))
1677 /* use the loaded one if any */
1678 if (!IS_CLASSREF(y))
1680 goto return_simple_x;
1683 /*--------------------------------------------------*/
1684 /* non-trivial cases */
1685 /*--------------------------------------------------*/
1687 #ifdef TYPEINFO_VERBOSE
1690 fprintf(stderr,"merge_nonarrays:\n");
1691 fprintf(stderr," ");if(IS_CLASSREF(x))fprintf(stderr,"<ref>");utf_fprint(stderr,xname);fprintf(stderr,"\n");
1692 fprintf(stderr," ");if(IS_CLASSREF(y))fprintf(stderr,"<ref>");utf_fprint(stderr,yname);fprintf(stderr,"\n");
1694 TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(dbgx,x);
1695 dbgx.merged = mergedx;
1696 TYPEINFO_INIT_CLASSREF_OR_CLASSINFO(dbgy,y);
1697 dbgy.merged = mergedy;
1698 typeinfo_print(stderr,&dbgx,4);
1699 fprintf(stderr," with:\n");
1700 typeinfo_print(stderr,&dbgy,4);
1704 TYPEINFO_ASSERT(IS_CLASSREF(x) || x.cls->loaded);
1705 TYPEINFO_ASSERT(IS_CLASSREF(y) || y.cls->loaded);
1707 /* If y is unresolved or an interface, swap x and y. */
1708 if (IS_CLASSREF(y) || (!IS_CLASSREF(x) && y.cls->flags & ACC_INTERFACE))
1710 t = x; x = y; y = t;
1711 tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1714 /* {We know: If only one of x,y is unresolved it is x,} */
1715 /* { If both x,y are resolved and only one of x,y is an interface it is x.} */
1717 if (IS_CLASSREF(x)) {
1718 /* {We know: x and y have different class names} */
1720 /* Check if we are merging an unresolved type with java.lang.Object */
1721 if (y.cls == class_java_lang_Object && !mergedy) {
1723 goto return_simple_x;
1726 common = class_java_lang_Object;
1727 goto merge_with_simple_x;
1730 /* {We know: both x and y are resolved} */
1731 /* {We know: If only one of x,y is an interface it is x.} */
1733 TYPEINFO_ASSERT(!IS_CLASSREF(x) && !IS_CLASSREF(y));
1734 TYPEINFO_ASSERT(x.cls->loaded);
1735 TYPEINFO_ASSERT(y.cls->loaded);
1737 /* Handle merging of interfaces: */
1738 if (x.cls->flags & ACC_INTERFACE) {
1739 /* {x.cls is an interface and mergedx == NULL.} */
1741 if (y.cls->flags & ACC_INTERFACE) {
1742 /* We are merging two interfaces. */
1743 /* {mergedy == NULL} */
1745 /* {We know that x.cls!=y.cls (see common case at beginning.)} */
1746 result->cls = class_java_lang_Object;
1747 return typeinfo_merge_two(dest,x,y);
1750 /* {We know: x is an interface, y is a class.} */
1752 /* Check if we are merging an interface with java.lang.Object */
1753 if (y.cls == class_java_lang_Object && !mergedy) {
1755 goto return_simple_x;
1758 /* If the type y implements x then the result of the merge
1759 * is x regardless of mergedy.
1762 /* we may have to link the classes */
1764 if (!link_class(x.cls))
1765 return typecheck_FAIL;
1767 if (!link_class(y.cls))
1768 return typecheck_FAIL;
1770 TYPEINFO_ASSERT(x.cls->linked);
1771 TYPEINFO_ASSERT(y.cls->linked);
1773 if (CLASSINFO_IMPLEMENTS_INTERFACE(y.cls,x.cls->index))
1775 /* y implements x, so the result of the merge is x. */
1776 goto return_simple_x;
1779 r = mergedlist_implements_interface(mergedy,x.cls);
1780 if (r == typecheck_FAIL)
1782 if (r == typecheck_TRUE)
1784 /* y implements x, so the result of the merge is x. */
1785 goto return_simple_x;
1788 /* {We know: x is an interface, the type y a class or a merge
1789 * of subclasses and is not guaranteed to implement x.} */
1791 common = class_java_lang_Object;
1792 goto merge_with_simple_x;
1795 /* {We know: x and y are classes (not interfaces).} */
1797 /* we may have to link the classes */
1799 if (!link_class(x.cls))
1800 return typecheck_FAIL;
1802 if (!link_class(y.cls))
1803 return typecheck_FAIL;
1805 TYPEINFO_ASSERT(x.cls->linked);
1806 TYPEINFO_ASSERT(y.cls->linked);
1808 /* If *x is deeper in the inheritance hierarchy swap x and y. */
1809 if (x.cls->index > y.cls->index) {
1810 t = x; x = y; y = t;
1811 tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1814 /* {We know: y is at least as deep in the hierarchy as x.} */
1816 /* Find nearest common anchestor for the classes. */
1819 while (tcls->index > common->index)
1820 tcls = tcls->super.cls;
1821 while (common != tcls) {
1822 common = common->super.cls;
1823 tcls = tcls->super.cls;
1826 /* {common == nearest common anchestor of x and y.} */
1828 /* If x.cls==common and x is a whole class (not a merge of subclasses)
1829 * then the result of the merge is x.
1831 if (x.cls == common && !mergedx) {
1832 goto return_simple_x;
1836 result->cls = common;
1838 return typeinfo_merge_mergedlists(dest,mergedx,mergedy);
1840 return typeinfo_merge_add(dest,mergedx,y);
1843 merge_with_simple_x:
1844 result->cls = common;
1846 return typeinfo_merge_add(dest,mergedy,x);
1848 return typeinfo_merge_two(dest,x,y);
1851 /* typeinfo_merge **************************************************************
1856 m................method for exception messages
1857 dest.............the first type
1858 y................the second type
1861 *dest............receives the result of the merge
1864 typecheck_TRUE...*dest has been modified
1865 typecheck_FALSE..*dest has not been modified
1866 typecheck_FAIL...an exception has been thrown
1869 RESULT is an extra parameter so it can point to dest->typeclass or to
1872 *******************************************************************************/
1874 /* Condition: *dest must be a valid initialized typeinfo. */
1875 /* Condition: dest != y. */
1876 /* Returns: true if dest was changed. */
1878 typeinfo_merge(methodinfo *m,typeinfo *dest,typeinfo* y)
1882 classref_or_classinfo common;
1883 classref_or_classinfo elementclass;
1889 /*--------------------------------------------------*/
1891 /*--------------------------------------------------*/
1893 /* Merging something with itself is a nop */
1895 return typecheck_FALSE;
1897 /* Merging two returnAddress types is ok. */
1898 /* Merging two different returnAddresses never happens, as the verifier */
1899 /* keeps them separate in order to check all the possible return paths */
1900 /* from JSR subroutines. */
1901 if (!dest->typeclass.any && !y->typeclass.any) {
1902 TYPEINFO_ASSERT(TYPEINFO_RETURNADDRESS(*dest) == TYPEINFO_RETURNADDRESS(*y));
1903 return typecheck_FALSE;
1906 /* Primitive types cannot be merged with reference types */
1907 /* This must be checked before calls to typeinfo_merge. */
1908 TYPEINFO_ASSERT(dest->typeclass.any && y->typeclass.any);
1910 /* handle uninitialized object types */
1911 if (TYPEINFO_IS_NEWOBJECT(*dest) || TYPEINFO_IS_NEWOBJECT(*y)) {
1912 if (!TYPEINFO_IS_NEWOBJECT(*dest) || !TYPEINFO_IS_NEWOBJECT(*y)) {
1913 typeinfo_merge_error(m,"Trying to merge uninitialized object type.",dest,y);
1914 return typecheck_FAIL;
1916 if (TYPEINFO_NEWOBJECT_INSTRUCTION(*dest) != TYPEINFO_NEWOBJECT_INSTRUCTION(*y)) {
1917 typeinfo_merge_error(m,"Trying to merge different uninitialized objects.",dest,y);
1918 return typecheck_FAIL;
1920 /* the same uninitialized object -- no change */
1921 return typecheck_FALSE;
1924 /*--------------------------------------------------*/
1926 /*--------------------------------------------------*/
1928 /* Common case: dest and y are the same class or class reference */
1929 /* (This case is very simple unless *both* dest and y really represent
1930 * merges of subclasses of class dest==class y.)
1932 if ((dest->typeclass.any == y->typeclass.any) && (!dest->merged || !y->merged)) {
1934 changed = (dest->merged != NULL);
1935 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1936 dest->merged = NULL;
1940 /* Handle null types: */
1941 if (TYPEINFO_IS_NULLTYPE(*y)) {
1942 return typecheck_FALSE;
1944 if (TYPEINFO_IS_NULLTYPE(*dest)) {
1945 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1946 TYPEINFO_CLONE(*y,*dest);
1947 return typecheck_TRUE;
1950 /* Common case: two types with the same name, at least one unresolved */
1951 if (IS_CLASSREF(dest->typeclass)) {
1952 if (IS_CLASSREF(y->typeclass)) {
1953 if (dest->typeclass.ref->name == y->typeclass.ref->name)
1957 /* XXX should we take y instead of dest here? */
1958 if (dest->typeclass.ref->name == y->typeclass.cls->name)
1963 if (IS_CLASSREF(y->typeclass)
1964 && (dest->typeclass.cls->name == y->typeclass.ref->name))
1970 /*--------------------------------------------------*/
1971 /* non-trivial cases */
1972 /*--------------------------------------------------*/
1974 #ifdef TYPEINFO_VERBOSE
1975 fprintf(stderr,"merge:\n");
1976 typeinfo_print(stderr,dest,4);
1977 typeinfo_print(stderr,y,4);
1980 /* This function uses x internally, so x and y can be swapped
1981 * without changing dest. */
1985 /* Handle merging of arrays: */
1986 if (TYPEINFO_IS_ARRAY(*x) && TYPEINFO_IS_ARRAY(*y)) {
1988 /* Make x the one with lesser dimension */
1989 if (x->dimension > y->dimension) {
1990 tmp = x; x = y; y = tmp;
1993 /* If one array (y) has higher dimension than the other,
1994 * interpret it as an array (same dim. as x) of Arraystubs. */
1995 if (x->dimension < y->dimension) {
1996 dimension = x->dimension;
1997 elementtype = ARRAYTYPE_OBJECT;
1998 elementclass.cls = pseudo_class_Arraystub;
2001 dimension = y->dimension;
2002 elementtype = y->elementtype;
2003 elementclass = y->elementclass;
2006 /* {The arrays are of the same dimension.} */
2008 if (x->elementtype != elementtype) {
2009 /* Different element types are merged, so the resulting array
2010 * type has one accessible dimension less. */
2011 if (--dimension == 0) {
2012 common.cls = pseudo_class_Arraystub;
2014 elementclass.any = NULL;
2017 common.cls = class_multiarray_of(dimension,pseudo_class_Arraystub,true);
2019 *exceptionptr = new_internalerror("XXX Coult not create array class");
2020 return typecheck_FAIL;
2023 elementtype = ARRAYTYPE_OBJECT;
2024 elementclass.cls = pseudo_class_Arraystub;
2028 /* {The arrays have the same dimension and elementtype.} */
2030 if (elementtype == ARRAYTYPE_OBJECT) {
2031 /* The elements are references, so their respective
2032 * types must be merged.
2034 r = typeinfo_merge_nonarrays(dest,
2038 x->merged,y->merged);
2039 TYPEINFO_ASSERT(r != typecheck_MAYBE);
2040 if (r == typecheck_FAIL)
2044 /* DEBUG */ /* log_text("finding resulting array class: "); */
2045 if (IS_CLASSREF(elementclass))
2046 common.ref = class_get_classref_multiarray_of(dimension,elementclass.ref);
2048 common.cls = class_multiarray_of(dimension,elementclass.cls,true);
2050 *exceptionptr = new_internalerror("XXX Coult not create array class");
2051 return typecheck_FAIL;
2054 /* DEBUG */ /* utf_display(common->name); printf("\n"); */
2057 common.any = y->typeclass.any;
2062 /* {We know that at least one of x or y is no array, so the
2063 * result cannot be an array.} */
2065 r = typeinfo_merge_nonarrays(dest,
2067 x->typeclass,y->typeclass,
2068 x->merged,y->merged);
2069 TYPEINFO_ASSERT(r != typecheck_MAYBE);
2070 if (r == typecheck_FAIL)
2076 elementclass.any = NULL;
2079 /* Put the new values into dest if neccessary. */
2081 if (dest->typeclass.any != common.any) {
2082 dest->typeclass.any = common.any;
2085 if (dest->dimension != dimension) {
2086 dest->dimension = dimension;
2089 if (dest->elementtype != elementtype) {
2090 dest->elementtype = elementtype;
2093 if (dest->elementclass.any != elementclass.any) {
2094 dest->elementclass.any = elementclass.any;
2102 /**********************************************************************/
2103 /* DEBUGGING HELPERS */
2104 /**********************************************************************/
2106 #ifdef TYPEINFO_DEBUG
2110 typeinfo_test_compare(classref_or_classinfo *a,classref_or_classinfo *b)
2112 if (a->any == b->any) return 0;
2113 if (a->any < b->any) return -1;
2118 typeinfo_test_parse(typeinfo *info,char *str)
2125 utf *desc = utf_new_char(str);
2127 num = typeinfo_count_method_args(desc,false);
2129 typebuf = DMNEW(u1,num);
2130 infobuf = DMNEW(typeinfo,num);
2132 typeinfo_init_from_method_args(desc,typebuf,infobuf,num,false,
2135 TYPEINFO_ALLOCMERGED(info->merged,num);
2136 info->merged->count = num;
2138 for (i=0; i<num; ++i) {
2139 if (typebuf[i] != TYPE_ADDRESS) {
2140 log_text("non-reference type in mergedlist");
2144 info->merged->list[i].any = infobuf[i].typeclass.any;
2146 qsort(info->merged->list,num,sizeof(classref_or_classinfo),
2147 (int(*)(const void *,const void *))&typeinfo_test_compare);
2150 typeinfo_init_from_method_args(desc,NULL,NULL,0,false,
2156 #define TYPEINFO_TEST_BUFLEN 4000
2159 typeinfo_equal(typeinfo *x,typeinfo *y)
2163 if (x->typeclass.any != y->typeclass.any) return false;
2164 if (x->dimension != y->dimension) return false;
2166 if (x->elementclass.any != y->elementclass.any) return false;
2167 if (x->elementtype != y->elementtype) return false;
2170 if (TYPEINFO_IS_NEWOBJECT(*x))
2171 if (TYPEINFO_NEWOBJECT_INSTRUCTION(*x)
2172 != TYPEINFO_NEWOBJECT_INSTRUCTION(*y))
2175 if (x->merged || y->merged) {
2176 if (!(x->merged && y->merged)) return false;
2177 if (x->merged->count != y->merged->count) return false;
2178 for (i=0; i<x->merged->count; ++i)
2179 if (x->merged->list[i].any != y->merged->list[i].any)
2186 typeinfo_testmerge(typeinfo *a,typeinfo *b,typeinfo *result,int *failed)
2189 bool changed,changed_should_be;
2192 TYPEINFO_CLONE(*a,dest);
2195 typeinfo_print_short(stdout,&dest);
2197 typeinfo_print_short(stdout,b);
2200 r = typeinfo_merge(NULL,&dest,b);
2201 if (r == typecheck_FAIL) {
2202 printf("EXCEPTION\n");
2205 changed = (r) ? 1 : 0;
2206 changed_should_be = (!typeinfo_equal(&dest,a)) ? 1 : 0;
2208 printf(" %s\n",(changed) ? "changed" : "=");
2210 if (typeinfo_equal(&dest,result)) {
2212 typeinfo_print_short(stdout,&dest);
2214 if (changed != changed_should_be) {
2215 printf("WRONG RETURN VALUE!\n");
2221 typeinfo_print_short(stdout,&dest);
2223 printf("SHOULD BE ");
2224 typeinfo_print_short(stdout,result);
2232 typeinfo_inc_dimension(typeinfo *info)
2234 if (info->dimension++ == 0) {
2235 info->elementtype = ARRAYTYPE_OBJECT;
2236 info->elementclass = info->typeclass;
2238 info->typeclass = class_array_of(info->typeclass,true);
2242 #define TYPEINFO_TEST_MAXDIM 10
2245 typeinfo_testrun(char *filename)
2247 char buf[TYPEINFO_TEST_BUFLEN];
2248 char bufa[TYPEINFO_TEST_BUFLEN];
2249 char bufb[TYPEINFO_TEST_BUFLEN];
2250 char bufc[TYPEINFO_TEST_BUFLEN];
2254 FILE *file = fopen(filename,"rt");
2258 log_text("could not open typeinfo test file");
2262 while (fgets(buf,TYPEINFO_TEST_BUFLEN,file)) {
2263 if (buf[0] == '#' || !strlen(buf))
2266 res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc);
2267 if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc)) {
2268 log_text("Invalid line in typeinfo test file (none of empty, comment or test)");
2273 typeinfo_test_parse(&a,bufa);
2274 typeinfo_test_parse(&b,bufb);
2275 typeinfo_test_parse(&c,bufc);
2280 typeinfo_testmerge(&a,&b,&c,&failed); /* check result */
2281 typeinfo_testmerge(&b,&a,&c,&failed); /* check commutativity */
2283 if (TYPEINFO_IS_NULLTYPE(a)) break;
2284 if (TYPEINFO_IS_NULLTYPE(b)) break;
2285 if (TYPEINFO_IS_NULLTYPE(c)) break;
2287 maxdim = a.dimension;
2288 if (b.dimension > maxdim) maxdim = b.dimension;
2289 if (c.dimension > maxdim) maxdim = c.dimension;
2292 if (maxdim < TYPEINFO_TEST_MAXDIM) {
2293 typeinfo_inc_dimension(&a);
2294 typeinfo_inc_dimension(&b);
2295 typeinfo_inc_dimension(&c);
2297 } while (maxdim < TYPEINFO_TEST_MAXDIM);
2304 fprintf(stderr,"Failed typeinfo_merge tests: %d\n",failed);
2305 log_text("Failed test");
2313 log_text("Running typeinfo test file...");
2314 typeinfo_testrun("typeinfo.tst");
2315 log_text("Finished typeinfo test file.");
2320 typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc)
2322 typeinfo_init_from_descriptor(info,desc,desc+strlen(desc));
2326 #define TYPEINFO_MAXINDENT 80
2329 typeinfo_print_class(FILE *file,classref_or_classinfo c)
2331 /*fprintf(file,"<class %p>",c.any);*/
2334 fprintf(file,"<null>");
2337 if (IS_CLASSREF(c)) {
2338 fprintf(file,"<ref>");
2339 utf_fprint(file,c.ref->name);
2342 utf_fprint(file,c.cls->name);
2348 typeinfo_print(FILE *file,typeinfo *info,int indent)
2351 char ind[TYPEINFO_MAXINDENT + 1];
2355 if (indent > TYPEINFO_MAXINDENT) indent = TYPEINFO_MAXINDENT;
2357 for (i=0; i<indent; ++i)
2361 if (TYPEINFO_IS_PRIMITIVE(*info)) {
2362 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
2364 fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->debug_nr);
2366 fprintf(file,"%sprimitive\n",ind);
2370 if (TYPEINFO_IS_NULLTYPE(*info)) {
2371 fprintf(file,"%snull\n",ind);
2375 if (TYPEINFO_IS_NEWOBJECT(*info)) {
2376 ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
2378 fprintf(file,"%sNEW(%p):",ind,(void*)ins);
2379 typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].val.a));
2383 fprintf(file,"%sNEW(this)",ind);
2388 fprintf(file,"%sClass: ",ind);
2389 typeinfo_print_class(file,info->typeclass);
2392 if (TYPEINFO_IS_ARRAY(*info)) {
2393 fprintf(file,"%sDimension: %d",ind,(int)info->dimension);
2394 fprintf(file,"\n%sElements: ",ind);
2395 switch (info->elementtype) {
2396 case ARRAYTYPE_INT : fprintf(file,"int\n"); break;
2397 case ARRAYTYPE_LONG : fprintf(file,"long\n"); break;
2398 case ARRAYTYPE_FLOAT : fprintf(file,"float\n"); break;
2399 case ARRAYTYPE_DOUBLE : fprintf(file,"double\n"); break;
2400 case ARRAYTYPE_BYTE : fprintf(file,"byte\n"); break;
2401 case ARRAYTYPE_CHAR : fprintf(file,"char\n"); break;
2402 case ARRAYTYPE_SHORT : fprintf(file,"short\n"); break;
2403 case ARRAYTYPE_BOOLEAN : fprintf(file,"boolean\n"); break;
2405 case ARRAYTYPE_OBJECT:
2406 typeinfo_print_class(file,info->elementclass);
2411 fprintf(file,"INVALID ARRAYTYPE!\n");
2416 fprintf(file,"%sMerged: ",ind);
2417 for (i=0; i<info->merged->count; ++i) {
2418 if (i) fprintf(file,", ");
2419 typeinfo_print_class(file,info->merged->list[i]);
2426 typeinfo_print_short(FILE *file,typeinfo *info)
2432 /*fprintf(file,"<typeinfo %p>",info);*/
2435 fprintf(file,"(typeinfo*)NULL");
2439 if (TYPEINFO_IS_PRIMITIVE(*info)) {
2440 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
2442 fprintf(file,"ret(L%03d)",bptr->debug_nr);
2444 fprintf(file,"primitive");
2448 if (TYPEINFO_IS_NULLTYPE(*info)) {
2449 fprintf(file,"null");
2453 if (TYPEINFO_IS_NEWOBJECT(*info)) {
2454 ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
2456 /*fprintf(file,"<ins %p>",ins);*/
2457 fprintf(file,"NEW(%p):",(void*)ins);
2458 typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].val.a));
2461 fprintf(file,"NEW(this)");
2465 typeinfo_print_class(file,info->typeclass);
2469 for (i=0; i<info->merged->count; ++i) {
2470 if (i) fprintf(file,",");
2471 typeinfo_print_class(file,info->merged->list[i]);
2478 typeinfo_print_type(FILE *file,int type,typeinfo *info)
2481 case TYPE_VOID: fprintf(file,"V"); break;
2482 case TYPE_INT: fprintf(file,"I"); break;
2483 case TYPE_FLOAT: fprintf(file,"F"); break;
2484 case TYPE_DOUBLE: fprintf(file,"D"); break;
2485 case TYPE_LONG: fprintf(file,"J"); break;
2487 typeinfo_print_short(file,info);
2496 typeinfo_print_stacktype(FILE *file,int type,typeinfo *info)
2498 TYPEINFO_ASSERT(file);
2499 TYPEINFO_ASSERT(type != TYPE_ADDRESS || info != NULL);
2500 if (type == TYPE_ADDRESS && TYPEINFO_IS_PRIMITIVE(*info)) {
2501 typeinfo_retaddr_set *set = (typeinfo_retaddr_set*)
2502 TYPEINFO_RETURNADDRESS(*info);
2504 fprintf(file,"ret(L%03d",((basicblock*)(set->addr))->debug_nr);
2507 fprintf(file,"|L%03d",((basicblock*)(set->addr))->debug_nr);
2512 fprintf(file,"ret(<NULL>");
2517 typeinfo_print_type(file,type,info);
2521 typedescriptor_print(FILE *file,typedescriptor *td)
2523 typeinfo_print_type(file,td->type,&(td->info));
2527 typevector_print(FILE *file,typevector *vec,int size)
2531 fprintf(file,"[%d]",vec->k);
2532 for (i=0; i<size; ++i) {
2533 fprintf(file," %d=",i);
2534 typedescriptor_print(file,vec->td + i);
2539 typevectorset_print(FILE *file,typevector *set,int size)
2544 fprintf(file,"[%d",set->k);
2547 fprintf(file,"|%d",vec->k);
2552 for (i=0; i<size; ++i) {
2553 fprintf(file," %d=",i);
2554 typedescriptor_print(file,set->td + i);
2558 typedescriptor_print(file,vec->td + i);
2564 #endif /* TYPEINFO_DEBUG */
2568 * These are local overrides for various environment variables in Emacs.
2569 * Please do not remove this and leave it at the end of the file, where
2570 * Emacs will automagically detect them.
2571 * ---------------------------------------------------------------------
2574 * indent-tabs-mode: t
2578 * vim:noexpandtab:sw=4:ts=4: