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 3888 2005-12-05 22:08:45Z twisti $
36 #include "mm/memory.h"
37 #include "toolbox/logging.h"
39 #include "vm/loader.h"
40 #include "vm/jit/jit.h"
41 #include "vm/jit/verify/typeinfo.h"
42 #include "vm/descriptor.h"
43 #include "vm/resolve.h"
44 #include "vm/exceptions.h"
47 /* check if a linked class is an array class. Only use for linked classes! */
48 #define CLASSINFO_IS_ARRAY(clsinfo) ((clsinfo)->vftbl->arraydesc != NULL)
50 /* check if a linked class implements the interface with the given index */
51 #define CLASSINFO_IMPLEMENTS_INTERFACE(cls,index) \
52 ( ((index) < (cls)->vftbl->interfacetablelength) \
53 && (VFTBLINTERFACETABLE((cls)->vftbl,(index)) != NULL) )
55 /******************************************************************************/
57 /******************************************************************************/
60 #define TYPEINFO_ASSERT(cond) assert(cond)
62 #define TYPEINFO_ASSERT(cond)
65 /**********************************************************************/
66 /* TYPEVECTOR (SET) FUNCTIONS */
67 /**********************************************************************/
69 /* typevectorset_copy **********************************************************
71 Return a copy of the given typevector set.
74 src..............typevector set to copy, must be != NULL
75 k................k-index to set in first typevector of resulting set
76 size.............number of elements per typevector
79 a pointer to the new typevector set
82 This function recursively invokes itself with increasing k-index to
83 copy the alternative typevectors in the given set.
85 *******************************************************************************/
88 typevectorset_copy(typevector *src,int k,int size)
94 dst = DNEW_TYPEVECTOR(size);
95 memcpy(dst,src,TYPEVECTOR_SIZE(size));
98 dst->alt = typevectorset_copy(src->alt,k+1,size);
102 /* typevectorset_copy_inplace **************************************************
104 Return a copy of the given typevector set.
106 The DST typevector is overwritten, but alternative vectors, if SRC has any,
110 src..............typevector set to copy, must be != NULL
111 dst..............destination to write the copy to
112 size.............number of elements per typevector
114 *******************************************************************************/
117 typevectorset_copy_inplace(typevector *src,typevector *dst,int size)
119 memcpy(dst,src,TYPEVECTOR_SIZE(size));
122 (dst)->alt = typevectorset_copy((src)->alt,1,size);
126 /* typevectorset_checktype *****************************************************
128 Check if all typevectors contain a given type at a given index.
131 vec..............typevector set, must be != NULL
132 index............index of component to check
133 type.............TYPE_* constant to check against
136 true if all typevectors in the set contain TYPE at INDEX,
139 *******************************************************************************/
142 typevectorset_checktype(typevector *vec,int index,int type)
144 TYPEINFO_ASSERT(vec);
146 if (vec->td[index].type != type)
148 } while ((vec = vec->alt) != NULL);
152 /* typevectorset_checkreference ************************************************
154 Check if all typevectors contain a reference at a given index.
157 vec..............typevector set, must be != NULL
158 index............index of component to check
161 true if all typevectors in the set contain a reference at INDEX,
164 *******************************************************************************/
167 typevectorset_checkreference(typevector *vec,int index)
169 TYPEINFO_ASSERT(vec);
171 if (!TYPEDESC_IS_REFERENCE(vec->td[index]))
173 } while ((vec = vec->alt) != NULL);
177 /* typevectorset_checkretaddr **************************************************
179 Check if all typevectors contain a returnAddress at a given index.
182 vec..............typevector set, must be != NULL
183 index............index of component to check
186 true if all typevectors in the set contain a returnAddress at INDEX,
189 *******************************************************************************/
192 typevectorset_checkretaddr(typevector *vec,int index)
194 TYPEINFO_ASSERT(vec);
196 if (!TYPEDESC_IS_RETURNADDRESS(vec->td[index]))
198 } while ((vec = vec->alt) != NULL);
202 /* typevectorset_copymergedtype ************************************************
204 Merge the types at a given index in the typevectors of a set and
205 copy the result to a destination typeinfo.
208 m................method for exception messages
209 vec..............typevector set, must be != NULL
210 index............index of component to merge
213 *dst.............destination typeinfo, receives the merge result
216 the TYPE_* constant of the resulting type
217 TYPE_VOID if incompatible types were contained at INDEX in VEC, or
218 -1...............an exception has been thrown
220 *******************************************************************************/
223 typevectorset_copymergedtype(methodinfo *m,typevector *vec,int index,typeinfo *dst)
228 TYPEINFO_ASSERT(vec);
229 TYPEINFO_ASSERT(dst);
231 td = vec->td + index;
233 TYPEINFO_COPY(td->info,*dst);
238 primitive = TYPEINFO_IS_PRIMITIVE(*dst) ? 1 : 0;
240 while ((vec = vec->alt) != NULL) {
241 td = vec->td + index;
242 if (type != td->type)
245 if (type == TYPE_ADDRESS) {
246 if ((TYPEINFO_IS_PRIMITIVE(td->info) ? 1 : 0) != primitive)
248 /* there cannot be any merge errors now. In the worst case */
249 /* we either get a returnAddress type or a j.l.O reference */
250 if (typeinfo_merge(m,dst,&(td->info)) == typecheck_FAIL)
258 /* typevectorset_mergedtype ****************************************************
260 Return the merged type of the types at a given index in the typevectors
264 m................method for exception messages
265 vec..............typevector set, must be != NULL
266 index............index of component to merge
267 temp.............pointer to a typeinfo that may be used to merge the
271 *result..........set to the address of a typeinfo containing the
275 the TYPE_* constant of the resulting type
276 TYPE_VOID if incompatible types were contained at INDEX in VEC, or
277 -1...............an exception has been thrown
280 This function should be more efficient than typevectorset_copymergedtype
281 assuming that most typevector sets contain exactly one typevector.
283 *******************************************************************************/
286 typevectorset_mergedtype(methodinfo *m,typevector *vec,int index,typeinfo *temp,typeinfo **result)
288 TYPEINFO_ASSERT(vec);
289 TYPEINFO_ASSERT(temp);
290 TYPEINFO_ASSERT(result);
294 return typevectorset_copymergedtype(m,vec,index,temp);
297 *result = &(vec->td[index].info);
298 return vec->td[index].type;
301 /* typevectorset_store *********************************************************
303 Store a type at a given index in the typevectors of a set.
304 This function stores the same type in all typevectors of the set.
305 DO NOT use it to store returnAddress types!
306 DO NOT use it to store two-word types!
309 vec..............typevector set, must be != NULL
310 index............index of component to set
311 type.............TYPE_* constant of type to set
312 info.............typeinfo of type to set, may be NULL,
316 If there is a two-word type stored at INDEX-1 in any typevector, it is
317 changed to TYPE_VOID (because its upper half has become invalid).
319 The components at INDEX+1 are _not_ touched, regardless of TYPE.
321 *******************************************************************************/
324 typevectorset_store(typevector *vec,int index,int type,typeinfo *info)
326 TYPEINFO_ASSERT(vec);
327 TYPEINFO_ASSERT((info && !TYPEINFO_IS_PRIMITIVE(*info)) || type != TYPE_ADR);
330 vec->td[index].type = type;
332 TYPEINFO_COPY(*info,vec->td[index].info);
333 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
334 vec->td[index-1].type = TYPE_VOID;
335 } while ((vec = vec->alt) != NULL);
338 /* typevectorset_store_retaddr *************************************************
340 Store a returnAddress type at a given index in the typevectors of a set.
341 Each possible returnAddress of the type is stored in the corresponding
342 typevector of the set.
345 vec..............typevector set, must be != NULL
346 index............index of component to set
347 info.............typeinfo of the returnAddress. This typeinfo must
348 contain a return address set with at least as many
349 entries as there are typevectors in VEC.
352 If there is a two-word type stored at INDEX-1 in any typevector, it is
353 changed to TYPE_VOID (because its upper half has become invalid).
355 *******************************************************************************/
358 typevectorset_store_retaddr(typevector *vec,int index,typeinfo *info)
360 typeinfo_retaddr_set *adr;
362 TYPEINFO_ASSERT(vec);
363 TYPEINFO_ASSERT(TYPEINFO_IS_PRIMITIVE(*info));
365 adr = (typeinfo_retaddr_set*) TYPEINFO_RETURNADDRESS(*info);
367 TYPEINFO_ASSERT(adr);
369 vec->td[index].type = TYPE_ADDRESS;
370 TYPEINFO_INIT_RETURNADDRESS(vec->td[index].info,adr->addr);
371 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
372 vec->td[index-1].type = TYPE_VOID;
374 } while ((vec = vec->alt) != NULL);
377 /* typevectorset_store_twoword *************************************************
379 Store a two-word type at a given index in the typevectors of a set.
380 This function stores the same type in all typevectors of the set.
383 vec..............typevector set, must be != NULL
384 index............index of component to set
385 type.............TYPE_* constant of type to set (TYPE_LONG, TYPE_DOUBLE)
388 If there is a two-word type stored at INDEX-1 in any typevector, it is
389 changed to TYPE_VOID (because its upper half has become invalid).
391 The components at INDEX+1 are set to TYPE_VOID.
393 *******************************************************************************/
396 typevectorset_store_twoword(typevector *vec,int index,int type)
398 TYPEINFO_ASSERT(vec);
399 TYPEINFO_ASSERT(type == TYPE_LONG || type == TYPE_DOUBLE);
402 vec->td[index].type = type;
403 vec->td[index+1].type = TYPE_VOID;
404 if (index > 0 && IS_2_WORD_TYPE(vec->td[index-1].type))
405 vec->td[index-1].type = TYPE_VOID;
406 } while ((vec = vec->alt) != NULL);
409 /* typevectorset_init_object ***************************************************
411 Replace all uninitialized object types in the typevector set which were
412 created by the given instruction by initialized object types.
415 set..............typevector set
416 ins..............instruction which created the uninitialized object type
417 initclass........class of the initialized object type to set
418 size.............number of elements per typevector
421 true.............success
422 false............an exception has been thrown
424 XXX maybe we should do the lazy resolving before calling this function
426 *******************************************************************************/
429 typevectorset_init_object(typevector *set,void *ins,
430 classref_or_classinfo initclass,
435 for (;set; set=set->alt) {
436 for (i=0; i<size; ++i) {
437 if (set->td[i].type == TYPE_ADR
438 && TYPEINFO_IS_NEWOBJECT(set->td[i].info)
439 && TYPEINFO_NEWOBJECT_INSTRUCTION(set->td[i].info) == ins)
441 if (!typeinfo_init_class(&(set->td[i].info),initclass))
449 /* typevector_merge ************************************************************
451 Merge a typevector with another one.
452 The given typevectors must have the same number of components.
455 m................method for exception messages
456 dst..............the first typevector
457 y................the second typevector
458 size.............number of elements per typevector
461 *dst.............the resulting typevector
464 typecheck_TRUE...dst has been modified
465 typecheck_FALSE..dst has not been modified
466 typecheck_FAIL...an exception has been thrown
468 *******************************************************************************/
471 typevector_merge(methodinfo *m,typevector *dst,typevector *y,int size)
473 bool changed = false;
476 typedescriptor *a = dst->td;
477 typedescriptor *b = y->td;
479 if (a->type != TYPE_VOID && a->type != b->type) {
483 else if (a->type == TYPE_ADDRESS) {
484 if (TYPEINFO_IS_PRIMITIVE(a->info)) {
485 /* 'a' is a returnAddress */
486 if (!TYPEINFO_IS_PRIMITIVE(b->info)
487 || (TYPEINFO_RETURNADDRESS(a->info)
488 != TYPEINFO_RETURNADDRESS(b->info)))
495 /* 'a' is a reference */
496 if (TYPEINFO_IS_PRIMITIVE(b->info)) {
501 /* two reference types are merged. There cannot be */
502 /* a merge error. In the worst case we get j.l.O. */
503 r = typeinfo_merge(m,&(a->info),&(b->info));
504 if (r == typecheck_FAIL)
516 /* typevector_separable_from ***************************************************
518 Check if two typevectors are separable. Two typevectors are considered
519 separable if there is an index i for which both typevectors contain a
520 returnAddress type and the return addresses of the types are different.
521 The typevectors must have the same number of components.
524 a................the first typevector
525 b................the second typevector
526 size.............number of elements per typevector
529 true.............typevectors are separable
530 false............typevectors are not separable
532 *******************************************************************************/
535 typevector_separable_from(typevector *a,typevector *b,int size)
537 typedescriptor *tda = a->td;
538 typedescriptor *tdb = b->td;
539 for (;size--; tda++,tdb++) {
540 if (TYPEDESC_IS_RETURNADDRESS(*tda)
541 && TYPEDESC_IS_RETURNADDRESS(*tdb)
542 && TYPEINFO_RETURNADDRESS(tda->info)
543 != TYPEINFO_RETURNADDRESS(tdb->info))
549 /* typevectorset_add ***********************************************************
551 Add a typevector to a typevector set. The typevector is added at the end of
552 the set and the k-index of the typevector is set accordingly.
555 dst..............the typevector set to modify
556 v................the typevector to add
557 size.............number of elements per typevector
559 *******************************************************************************/
562 typevectorset_add(typevector *dst,typevector *v,int size)
564 TYPEINFO_ASSERT(dst);
569 dst->alt = DNEW_TYPEVECTOR(size);
570 memcpy(dst->alt,v,TYPEVECTOR_SIZE(size));
571 dst->alt->alt = NULL;
572 dst->alt->k = dst->k + 1;
575 /* typevectorset_select ********************************************************
577 Pick the typevectors from a set which contain a given return address.
580 set..............points to the location containing the typevector set.
582 index............index to check against the return address. All
583 typevectors must contain a returnAddress type at
585 retaddr..........the return address to select
588 *set.............receives the typevector set after removing the
589 selected typevectors.
592 a typevector set consisting of the selected typevectors.
594 *******************************************************************************/
597 typevectorset_select(typevector **set,int index,void *retaddr)
599 typevector *selected;
601 if (!*set) return NULL;
603 if (TYPEINFO_RETURNADDRESS((*set)->td[index].info) == retaddr) {
605 *set = selected->alt;
606 selected->alt = typevectorset_select(set,index,retaddr);
609 selected = typevectorset_select(&((*set)->alt),index,retaddr);
614 /* typevector_separable_with ***************************************************
616 Check if a typevector set would be separable after adding a given
617 typevector. A typevector set is considered separable if there is an
618 index i for which all typevectors in the set contain a returnAddress type,
619 and at least two different return addresses occurr at index i.
620 The typevectors must have the same number of components.
623 set..............the typevector set
624 add..............the typevector
625 size.............number of elements per typevector
628 true.............result would be separable
629 false............result would not be separable
631 *******************************************************************************/
634 typevectorset_separable_with(typevector *set,typevector *add,int size)
641 TYPEINFO_ASSERT(set);
642 TYPEINFO_ASSERT(add);
644 for (i=0; i<size; ++i) {
645 if (!TYPEDESC_IS_RETURNADDRESS(add->td[i]))
647 addr = TYPEINFO_RETURNADDRESS(add->td[i].info);
652 if (!TYPEDESC_IS_RETURNADDRESS(v->td[i]))
654 if (TYPEINFO_RETURNADDRESS(v->td[i].info) != addr)
658 if (separable) return true;
665 /* typevectorset_collapse ******************************************************
667 Collapse a typevector set into a single typevector by merging the
668 components of the typevectors at each index.
671 dst..............the type vector set
672 size.............number of elements per typevector
675 *dst.............the resulting typevector set (a single typevector)
678 typecheck_TRUE...dst has been modified
679 typecheck_FALSE..dst has not been modified
680 typecheck_FAIL...an exception has been thrown
682 *******************************************************************************/
685 typevectorset_collapse(methodinfo *m,typevector *dst,int size)
687 bool changed = false;
689 TYPEINFO_ASSERT(dst);
692 if (typevector_merge(m,dst,dst->alt,size) == typecheck_FAIL)
693 return typecheck_FAIL;
694 dst->alt = dst->alt->alt;
700 /**********************************************************************/
701 /* READ-ONLY FUNCTIONS */
702 /* The following functions don't change typeinfo data. */
703 /**********************************************************************/
705 /* typeinfo_is_array ***********************************************************
707 Check whether a typeinfo describes an array type.
710 info.............the typeinfo, must be != NULL
713 true if INFO describes an array type.
715 *******************************************************************************/
718 typeinfo_is_array(typeinfo *info)
720 TYPEINFO_ASSERT(info);
721 return TYPEINFO_IS_ARRAY(*info);
724 /* typeinfo_is_primitive_array *************************************************
726 Check whether a typeinfo describes a primitive array type.
729 info.............the typeinfo, must be != NULL
732 true if INFO describes an array of a primitive type.
734 *******************************************************************************/
737 typeinfo_is_primitive_array(typeinfo *info,int arraytype)
739 TYPEINFO_ASSERT(info);
740 return TYPEINFO_IS_PRIMITIVE_ARRAY(*info,arraytype);
743 /* typeinfo_is_array_of_refs ***************************************************
745 Check whether a typeinfo describes an array of references type.
748 info.............the typeinfo, must be != NULL
751 true if INFO describes an array of a refrence type.
753 *******************************************************************************/
756 typeinfo_is_array_of_refs(typeinfo *info)
758 TYPEINFO_ASSERT(info);
759 return TYPEINFO_IS_ARRAY_OF_REFS(*info);
762 /* interface_extends_interface *************************************************
764 Check if a resolved interface extends a given resolved interface.
767 cls..............the interface, must be linked
768 interf...........the interface to check against
771 true.............CLS extends INTERF
772 false............CLS does not extend INTERF
774 *******************************************************************************/
777 interface_extends_interface(classinfo *cls,classinfo *interf)
781 TYPEINFO_ASSERT(cls);
782 TYPEINFO_ASSERT(interf);
783 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
784 TYPEINFO_ASSERT((cls->flags & ACC_INTERFACE) != 0);
785 TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
787 /* first check direct superinterfaces */
788 for (i=0; i<cls->interfacescount; ++i) {
789 if (cls->interfaces[i].cls == interf)
793 /* check indirect superinterfaces */
794 for (i=0; i<cls->interfacescount; ++i) {
795 if (interface_extends_interface(cls->interfaces[i].cls,interf))
802 /* classinfo_implements_interface **********************************************
804 Check if a resolved class implements a given resolved interface.
807 cls..............the class
808 interf...........the interface
811 typecheck_TRUE...CLS implements INTERF
812 typecheck_FALSE..CLS does not implement INTERF
813 typecheck_FAIL...an exception has been thrown
815 *******************************************************************************/
817 static typecheck_result
818 classinfo_implements_interface(classinfo *cls,classinfo *interf)
820 TYPEINFO_ASSERT(cls);
821 TYPEINFO_ASSERT(interf);
822 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
824 if (!(cls->state & CLASS_LINKED))
825 if (!link_class(cls))
826 return typecheck_FAIL;
828 if (cls->flags & ACC_INTERFACE) {
829 /* cls is an interface */
831 return typecheck_TRUE;
833 /* check superinterfaces */
834 return interface_extends_interface(cls,interf);
837 TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
838 return CLASSINFO_IMPLEMENTS_INTERFACE(cls,interf->index);
841 /* mergedlist_implements_interface *********************************************
843 Check if all the classes in a given merged list implement a given resolved
847 merged...........the list of merged class types
848 interf...........the interface to check against
851 typecheck_TRUE...all classes implement INTERF
852 typecheck_FALSE..there is at least one class that does not implement
854 typecheck_MAYBE..check cannot be performed now because of unresolved
856 typecheck_FAIL...an exception has been thrown
858 *******************************************************************************/
860 static typecheck_result
861 mergedlist_implements_interface(typeinfo_mergedlist *merged,
865 classref_or_classinfo *mlist;
868 TYPEINFO_ASSERT(interf);
869 TYPEINFO_ASSERT((interf->flags & ACC_INTERFACE) != 0);
871 /* Check if there is an non-empty mergedlist. */
873 return typecheck_FALSE;
875 /* If all classinfos in the (non-empty) merged array implement the
876 * interface return true, otherwise false.
878 mlist = merged->list;
881 if (IS_CLASSREF(*mlist)) {
882 return typecheck_MAYBE;
884 r = classinfo_implements_interface((mlist++)->cls,interf);
885 if (r != typecheck_TRUE)
888 return typecheck_TRUE;
891 /* merged_implements_interface *************************************************
893 Check if a possible merged type implements a given resolved interface
897 typeclass........(common) class of the (merged) type
898 merged...........the list of merged class types
899 interf...........the interface to check against
902 typecheck_TRUE...the type implement INTERF
903 typecheck_FALSE..the type does not implement INTERF
904 typecheck_MAYBE..check cannot be performed now because of unresolved
906 typecheck_FAIL...an exception has been thrown
908 *******************************************************************************/
910 static typecheck_result
911 merged_implements_interface(classinfo *typeclass,typeinfo_mergedlist *merged,
916 /* primitive types don't support interfaces. */
918 return typecheck_FALSE;
920 /* the null type can be cast to any interface type. */
921 if (typeclass == pseudo_class_Null)
922 return typecheck_TRUE;
924 /* check if typeclass implements the interface. */
925 r = classinfo_implements_interface(typeclass,interf);
926 if (r != typecheck_FALSE)
929 /* check the mergedlist */
931 return typecheck_FALSE;
932 return mergedlist_implements_interface(merged,interf);
935 /* merged_is_subclass **********************************************************
937 Check if a possible merged type is a subclass of a given class.
938 A merged type is a subclass of a class C if all types in the merged list
939 are subclasses of C. A sufficient condition for this is that the
940 common type of the merged type is a subclass of C.
943 typeclass........(common) class of the (merged) type
944 MUST be a loaded and linked class
945 merged...........the list of merged class types
946 cls..............the class to theck against
949 typecheck_TRUE...the type is a subclass of CLS
950 typecheck_FALSE..the type is not a subclass of CLS
951 typecheck_MAYBE..check cannot be performed now because of unresolved
953 typecheck_FAIL...an exception has been thrown
955 *******************************************************************************/
957 static typecheck_result
958 merged_is_subclass(classinfo *typeclass,typeinfo_mergedlist *merged,
962 classref_or_classinfo *mlist;
964 TYPEINFO_ASSERT(cls);
966 /* primitive types aren't subclasses of anything. */
968 return typecheck_FALSE;
970 /* the null type can be cast to any reference type. */
971 if (typeclass == pseudo_class_Null)
972 return typecheck_TRUE;
974 TYPEINFO_ASSERT(typeclass->state & CLASS_LOADED);
975 TYPEINFO_ASSERT(typeclass->state & CLASS_LINKED);
977 /* check if the common typeclass is a subclass of CLS. */
978 if (class_issubclass(typeclass,cls))
979 return typecheck_TRUE;
981 /* check the mergedlist */
983 return typecheck_FALSE;
984 /* If all classinfos in the (non-empty) merged list are subclasses
985 * of CLS, return true, otherwise false.
986 * If there is at least one unresolved type in the list,
987 * return typecheck_MAYBE.
989 mlist = merged->list;
992 if (IS_CLASSREF(*mlist)) {
993 return typecheck_MAYBE;
995 if (!(mlist->cls->state & CLASS_LINKED))
996 if (!link_class(mlist->cls))
997 return typecheck_FAIL;
998 if (!class_issubclass(mlist->cls,cls))
999 return typecheck_FALSE;
1002 return typecheck_TRUE;
1005 /* typeinfo_is_assignable_to_class *********************************************
1007 Check if a type is assignable to a given class type.
1010 value............the type of the value
1011 dest.............the type of the destination
1014 typecheck_TRUE...the type is assignable
1015 typecheck_FALSE..the type is not assignable
1016 typecheck_MAYBE..check cannot be performed now because of unresolved
1018 typecheck_FAIL...an exception has been thrown
1020 *******************************************************************************/
1023 typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest)
1025 classref_or_classinfo c;
1029 TYPEINFO_ASSERT(value);
1031 c = value->typeclass;
1033 /* assignments of primitive values are not checked here. */
1034 if (!c.any && !dest.any)
1035 return typecheck_TRUE;
1037 /* primitive and reference types are not assignment compatible. */
1038 if (!c.any || !dest.any)
1039 return typecheck_FALSE;
1041 /* the null type can be assigned to any type */
1042 if (TYPEINFO_IS_NULLTYPE(*value))
1043 return typecheck_TRUE;
1045 /* uninitialized objects are not assignable */
1046 if (TYPEINFO_IS_NEWOBJECT(*value))
1047 return typecheck_FALSE;
1049 if (IS_CLASSREF(c)) {
1050 /* The value type is an unresolved class reference. */
1051 classname = c.ref->name;
1054 classname = c.cls->name;
1057 if (IS_CLASSREF(dest)) {
1058 /* the destination type is an unresolved class reference */
1059 /* In this case we cannot tell a lot about assignability. */
1061 /* the common case of value and dest type having the same classname */
1062 if (dest.ref->name == classname && !value->merged)
1063 return typecheck_TRUE;
1065 /* we cannot tell if value is assignable to dest, so we */
1066 /* leave it up to the resolving code to check this */
1067 return typecheck_MAYBE;
1070 /* { we know that dest is a loaded class } */
1072 if (IS_CLASSREF(c)) {
1073 /* the value type is an unresolved class reference */
1075 /* the common case of value and dest type having the same classname */
1076 if (dest.cls->name == classname)
1077 return typecheck_TRUE;
1079 /* we cannot tell if value is assignable to dest, so we */
1080 /* leave it up to the resolving code to check this */
1081 return typecheck_MAYBE;
1084 /* { we know that both c and dest are loaded classes } */
1085 /* (c may still have a merged list containing unresolved classrefs!) */
1087 TYPEINFO_ASSERT(!IS_CLASSREF(c));
1088 TYPEINFO_ASSERT(!IS_CLASSREF(dest));
1092 TYPEINFO_ASSERT(cls->state & CLASS_LOADED);
1093 TYPEINFO_ASSERT(dest.cls->state & CLASS_LOADED);
1095 /* maybe we need to link the classes */
1096 if (!(cls->state & CLASS_LINKED))
1097 if (!link_class(cls))
1098 return typecheck_FAIL;
1099 if (!(dest.cls->state & CLASS_LINKED))
1100 if (!link_class(dest.cls))
1101 return typecheck_FAIL;
1103 /* { we know that both c and dest are linked classes } */
1104 TYPEINFO_ASSERT(cls->state & CLASS_LINKED);
1105 TYPEINFO_ASSERT(dest.cls->state & CLASS_LINKED);
1107 if (dest.cls->flags & ACC_INTERFACE) {
1108 /* We are assigning to an interface type. */
1109 return merged_implements_interface(cls,value->merged,dest.cls);
1112 if (CLASSINFO_IS_ARRAY(dest.cls)) {
1113 arraydescriptor *arraydesc = dest.cls->vftbl->arraydesc;
1114 int dimension = arraydesc->dimension;
1115 classinfo *elementclass = (arraydesc->elementvftbl)
1116 ? arraydesc->elementvftbl->class : NULL;
1118 /* We are assigning to an array type. */
1119 if (!TYPEINFO_IS_ARRAY(*value))
1120 return typecheck_FALSE;
1122 /* {Both value and dest.cls are array types.} */
1124 /* value must have at least the dimension of dest.cls. */
1125 if (value->dimension < dimension)
1126 return typecheck_FALSE;
1128 if (value->dimension > dimension) {
1129 /* value has higher dimension so we need to check
1130 * if its component array can be assigned to the
1131 * element type of dest.cls */
1133 if (!elementclass) return typecheck_FALSE;
1135 if (elementclass->flags & ACC_INTERFACE) {
1136 /* We are assigning to an interface type. */
1137 return classinfo_implements_interface(pseudo_class_Arraystub,
1141 /* We are assigning to a class type. */
1142 return class_issubclass(pseudo_class_Arraystub,elementclass);
1145 /* {value and dest.cls have the same dimension} */
1147 if (value->elementtype != arraydesc->elementtype)
1148 return typecheck_FALSE;
1150 if (value->elementclass.any) {
1151 /* We are assigning an array of objects so we have to
1152 * check if the elements are assignable.
1155 if (elementclass->flags & ACC_INTERFACE) {
1156 /* We are assigning to an interface type. */
1158 return merged_implements_interface(value->elementclass.cls,
1163 /* We are assigning to a class type. */
1164 return merged_is_subclass(value->elementclass.cls,value->merged,elementclass);
1167 return typecheck_TRUE;
1170 /* {dest.cls is not an array} */
1171 /* {dest.cls is a loaded class} */
1173 /* If there are any unresolved references in the merged list, we cannot */
1174 /* tell if the assignment will be ok. */
1175 /* This can only happen when cls is java.lang.Object */
1176 if (cls == class_java_lang_Object && value->merged) {
1177 classref_or_classinfo *mlist = value->merged->list;
1178 int i = value->merged->count;
1180 if (IS_CLASSREF(*mlist++))
1181 return typecheck_MAYBE;
1184 /* We are assigning to a class type */
1185 if (cls->flags & ACC_INTERFACE)
1186 cls = class_java_lang_Object;
1188 return merged_is_subclass(cls,value->merged,dest.cls);
1191 /* typeinfo_is_assignable ******************************************************
1193 Check if a type is assignable to a given type.
1196 value............the type of the value
1197 dest.............the type of the destination, must not be a merged type
1200 typecheck_TRUE...the type is assignable
1201 typecheck_FALSE..the type is not assignable
1202 typecheck_MAYBE..check cannot be performed now because of unresolved
1204 typecheck_FAIL...an exception has been thrown
1206 *******************************************************************************/
1209 typeinfo_is_assignable(typeinfo *value,typeinfo *dest)
1211 TYPEINFO_ASSERT(value);
1212 TYPEINFO_ASSERT(dest);
1213 TYPEINFO_ASSERT(dest->merged == NULL);
1215 return typeinfo_is_assignable_to_class(value,dest->typeclass);
1218 /**********************************************************************/
1219 /* INITIALIZATION FUNCTIONS */
1220 /* The following functions fill in uninitialized typeinfo structures. */
1221 /**********************************************************************/
1223 /* typeinfo_init_classinfo *****************************************************
1225 Initialize a typeinfo to a resolved class.
1228 c................the class
1231 *info............is initialized
1234 true.............success
1235 false............an exception has been thrown
1237 *******************************************************************************/
1240 typeinfo_init_classinfo(typeinfo *info, classinfo *c)
1242 if ((info->typeclass.cls = c)->vftbl->arraydesc) {
1243 if (c->vftbl->arraydesc->elementvftbl)
1244 info->elementclass.cls = c->vftbl->arraydesc->elementvftbl->class;
1246 info->elementclass.any = NULL;
1247 info->dimension = c->vftbl->arraydesc->dimension;
1248 info->elementtype = c->vftbl->arraydesc->elementtype;
1251 info->elementclass.any = NULL;
1252 info->dimension = 0;
1253 info->elementtype = 0;
1255 info->merged = NULL;
1258 /* typeinfo_init_class *********************************************************
1260 Initialize a typeinfo to a possibly unresolved class type.
1263 c................the class type
1266 *info............is initialized
1269 true.............success
1270 false............an exception has been thrown
1272 *******************************************************************************/
1275 typeinfo_init_class(typeinfo *info,classref_or_classinfo c)
1281 TYPEINFO_ASSERT(c.any);
1282 TYPEINFO_ASSERT(info);
1284 /* if necessary, try to resolve lazily */
1285 if (!resolve_classref_or_classinfo(NULL /* XXX should now method */,
1286 c,resolveLazy,false,true,&cls))
1292 typeinfo_init_classinfo(info,cls);
1296 /* {the type could no be resolved lazily} */
1298 info->typeclass.ref = c.ref;
1299 info->elementclass.any = NULL;
1300 info->dimension = 0;
1301 info->merged = NULL;
1303 /* handle array type references */
1304 utf_ptr = c.ref->name->text;
1305 len = c.ref->name->blength;
1306 if (*utf_ptr == '[') {
1307 /* count dimensions */
1308 while (*utf_ptr == '[') {
1313 if (*utf_ptr == 'L') {
1316 info->elementtype = ARRAYTYPE_OBJECT;
1317 info->elementclass.ref = class_get_classref(c.ref->referer,utf_new(utf_ptr,len));
1320 /* an array with primitive element type */
1321 /* should have been resolved above */
1322 TYPEINFO_ASSERT(false);
1328 /* typeinfo_init_from_typedesc *************************************************
1330 Initialize a typeinfo from a typedesc.
1333 desc.............the typedesc
1336 *type............set to the TYPE_* constant of DESC (if type != NULL)
1337 *info............receives the typeinfo (if info != NULL)
1340 true.............success
1341 false............an exception has been thrown
1343 *******************************************************************************/
1346 typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info)
1348 TYPEINFO_ASSERT(desc);
1350 #ifdef TYPEINFO_VERBOSE
1351 fprintf(stderr,"typeinfo_init_from_typedesc(");
1352 descriptor_debug_print_typedesc(stderr,desc);
1353 fprintf(stderr,")\n");
1360 if (desc->type == TYPE_ADR) {
1361 TYPEINFO_ASSERT(desc->classref);
1362 if (!typeinfo_init_class(info,CLASSREF_OR_CLASSINFO(desc->classref)))
1366 TYPEINFO_INIT_PRIMITIVE(*info);
1372 /* typeinfos_init_from_methoddesc **********************************************
1374 Initialize an array of typeinfos and u1 TYPE_* values from a methoddesc.
1377 desc.............the methoddesc
1378 buflen...........number of parameters the buffer can hold
1379 twoword..........if true, use two parameter slots for two-word types
1382 *typebuf.........receives a TYPE_* constant for each parameter
1383 typebuf must be != NULL
1384 *infobuf.........receives a typeinfo for each parameter
1385 infobuf must be != NULL
1386 *returntype......receives a TYPE_* constant for the return type
1387 returntype may be NULL
1388 *returntypeinfo..receives a typeinfo for the return type
1389 returntypeinfo may be NULL
1392 true.............success
1393 false............an exception has been thrown
1396 If (according to BUFLEN) the buffers are to small to hold the
1397 parameter types, an internal error is thrown. This must be
1398 avoided by checking the number of parameters and allocating enough
1399 space before calling this function.
1401 *******************************************************************************/
1404 typeinfos_init_from_methoddesc(methoddesc *desc,u1 *typebuf,typeinfo *infobuf,
1405 int buflen,bool twoword,
1406 u1 *returntype,typeinfo *returntypeinfo)
1411 TYPEINFO_ASSERT(desc);
1412 TYPEINFO_ASSERT(typebuf);
1413 TYPEINFO_ASSERT(infobuf);
1415 #ifdef TYPEINFO_VERBOSE
1416 fprintf(stderr,"typeinfos_init_from_methoddesc(");
1417 descriptor_debug_print_methoddesc(stderr,desc);
1418 fprintf(stderr,")\n");
1421 /* check arguments */
1422 for (i=0; i<desc->paramcount; ++i) {
1423 if (++args > buflen) {
1424 *exceptionptr = new_internalerror("Buffer too small for method arguments.");
1428 if (!typeinfo_init_from_typedesc(desc->paramtypes + i,typebuf++,infobuf++))
1431 if (twoword && (typebuf[-1] == TYPE_LONG || typebuf[-1] == TYPE_DOUBLE)) {
1432 if (++args > buflen) {
1433 *exceptionptr = new_internalerror("Buffer too small for method arguments.");
1437 *typebuf++ = TYPE_VOID;
1438 TYPEINFO_INIT_PRIMITIVE(*infobuf);
1443 /* check returntype */
1445 if (!typeinfo_init_from_typedesc(&(desc->returntype),returntype,returntypeinfo))
1452 /* typedescriptor_init_from_typedesc *******************************************
1454 Initialize a typedescriptor from a typedesc.
1457 desc.............the typedesc
1460 *td..............receives the typedescriptor
1464 true.............success
1465 false............an exception has been thrown
1467 *******************************************************************************/
1470 typedescriptor_init_from_typedesc(typedescriptor *td,
1473 TYPEINFO_ASSERT(td);
1474 TYPEINFO_ASSERT(desc);
1476 td->type = desc->type;
1477 if (td->type == TYPE_ADR) {
1478 if (!typeinfo_init_class(&(td->info),CLASSREF_OR_CLASSINFO(desc->classref)))
1482 TYPEINFO_INIT_PRIMITIVE(td->info);
1487 /* typedescriptors_init_from_methoddesc ****************************************
1489 Initialize an array of typedescriptors from a methoddesc.
1492 desc.............the methoddesc
1493 buflen...........number of parameters the buffer can hold
1494 twoword..........if true, use two parameter slots for two-word types
1495 startindex.......the zero-based index of the first parameter to
1496 write to the array. In other words the number of
1497 parameters to skip at the beginning of the methoddesc.
1500 *td..............array receiving the typedescriptors.
1501 td[0] receives the typedescriptor of the
1502 (startindex+1)th parameter of the method
1503 *returntype......receives the typedescriptor of the return type.
1504 returntype may be NULL
1507 >= 0.............number of typedescriptors filled in TD
1508 -1...............an exception has been thrown
1511 If (according to BUFLEN) the buffer is to small to hold the
1512 parameter types, an internal error is thrown. This must be
1513 avoided by checking the number of parameters and allocating enough
1514 space before calling this function.
1516 *******************************************************************************/
1519 typedescriptors_init_from_methoddesc(typedescriptor *td,
1521 int buflen,bool twoword,int startindex,
1522 typedescriptor *returntype)
1527 /* check arguments */
1528 for (i=startindex; i<desc->paramcount; ++i) {
1529 if (++args > buflen) {
1530 *exceptionptr = new_internalerror("Buffer too small for method arguments.");
1534 if (!typedescriptor_init_from_typedesc(td,desc->paramtypes + i))
1538 if (twoword && (td[-1].type == TYPE_LONG || td[-1].type == TYPE_DOUBLE)) {
1539 if (++args > buflen) {
1540 *exceptionptr = new_internalerror("Buffer too small for method arguments.");
1544 td->type = TYPE_VOID;
1545 TYPEINFO_INIT_PRIMITIVE(td->info);
1550 /* check returntype */
1552 if (!typedescriptor_init_from_typedesc(returntype,&(desc->returntype)))
1559 /* typeinfo_init_component *****************************************************
1561 Initialize a typeinfo with the component type of a given array type.
1564 srcarray.........the typeinfo of the array type
1567 *dst.............receives the typeinfo of the component type
1570 true.............success
1571 false............an exception has been thrown
1573 *******************************************************************************/
1576 typeinfo_init_component(typeinfo *srcarray,typeinfo *dst)
1578 TYPEINFO_ASSERT(srcarray);
1579 TYPEINFO_ASSERT(dst);
1581 if (TYPEINFO_IS_NULLTYPE(*srcarray)) {
1582 TYPEINFO_INIT_NULLTYPE(*dst);
1586 if (!TYPEINFO_IS_ARRAY(*srcarray)) {
1587 /* XXX should we make that a verify error? */
1588 *exceptionptr = new_internalerror("Trying to access component of non-array");
1592 if (IS_CLASSREF(srcarray->typeclass)) {
1593 constant_classref *comp;
1594 comp = class_get_classref_component_of(srcarray->typeclass.ref);
1597 if (!typeinfo_init_class(dst,CLASSREF_OR_CLASSINFO(comp)))
1601 TYPEINFO_INIT_PRIMITIVE(*dst);
1607 if (!(srcarray->typeclass.cls->state & CLASS_LINKED)) {
1608 if (!link_class(srcarray->typeclass.cls)) {
1613 TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl);
1614 TYPEINFO_ASSERT(srcarray->typeclass.cls->vftbl->arraydesc);
1616 comp = srcarray->typeclass.cls->vftbl->arraydesc->componentvftbl;
1618 typeinfo_init_classinfo(dst,comp->class);
1620 TYPEINFO_INIT_PRIMITIVE(*dst);
1623 dst->merged = srcarray->merged; /* XXX should we do a deep copy? */
1627 /* typeinfo_clone **************************************************************
1629 Create a deep copy of a typeinfo struct.
1632 src..............the typeinfo to copy
1635 *dest............receives the copy
1638 If src == dest this function is a nop.
1640 *******************************************************************************/
1643 typeinfo_clone(typeinfo *src,typeinfo *dest)
1646 classref_or_classinfo *srclist,*destlist;
1654 count = src->merged->count;
1655 TYPEINFO_ALLOCMERGED(dest->merged,count);
1656 dest->merged->count = count;
1658 srclist = src->merged->list;
1659 destlist = dest->merged->list;
1661 *destlist++ = *srclist++;
1665 /**********************************************************************/
1666 /* MISCELLANEOUS FUNCTIONS */
1667 /**********************************************************************/
1669 /* typeinfo_free ***************************************************************
1671 Free memory referenced by the given typeinfo. The typeinfo itself is not
1675 info.............the typeinfo
1677 *******************************************************************************/
1680 typeinfo_free(typeinfo *info)
1682 TYPEINFO_FREEMERGED_IF_ANY(info->merged);
1683 info->merged = NULL;
1686 /**********************************************************************/
1687 /* MERGING FUNCTIONS */
1688 /* The following functions are used to merge the types represented by */
1689 /* two typeinfo structures into one typeinfo structure. */
1690 /**********************************************************************/
1694 typeinfo_merge_error(methodinfo *m,char *str,typeinfo *x,typeinfo *y) {
1695 #ifdef TYPEINFO_VERBOSE
1696 fprintf(stderr,"Error in typeinfo_merge: %s\n",str);
1697 fprintf(stderr,"Typeinfo x:\n");
1698 typeinfo_print(stderr,x,1);
1699 fprintf(stderr,"Typeinfo y:\n");
1700 typeinfo_print(stderr,y,1);
1704 *exceptionptr = new_verifyerror(m,str);
1707 /* Condition: clsx != clsy. */
1708 /* Returns: true if dest was changed (currently always true). */
1711 typeinfo_merge_two(typeinfo *dest,classref_or_classinfo clsx,classref_or_classinfo clsy)
1713 TYPEINFO_ASSERT(dest);
1714 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1715 TYPEINFO_ALLOCMERGED(dest->merged,2);
1716 dest->merged->count = 2;
1718 TYPEINFO_ASSERT(clsx.any != clsy.any);
1720 if (clsx.any < clsy.any) {
1721 dest->merged->list[0] = clsx;
1722 dest->merged->list[1] = clsy;
1725 dest->merged->list[0] = clsy;
1726 dest->merged->list[1] = clsx;
1732 /* Returns: true if dest was changed. */
1735 typeinfo_merge_add(typeinfo *dest,typeinfo_mergedlist *m,classref_or_classinfo cls)
1738 typeinfo_mergedlist *newmerged;
1739 classref_or_classinfo *mlist,*newlist;
1744 /* Check if cls is already in the mergedlist m. */
1746 if ((mlist++)->any == cls.any) { /* XXX check equal classrefs? */
1747 /* cls is in the list, so m is the resulting mergedlist */
1748 if (dest->merged == m)
1751 /* We have to copy the mergedlist */
1752 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1754 TYPEINFO_ALLOCMERGED(dest->merged,count);
1755 dest->merged->count = count;
1756 newlist = dest->merged->list;
1759 *newlist++ = *mlist++;
1765 /* Add cls to the mergedlist. */
1767 TYPEINFO_ALLOCMERGED(newmerged,count+1);
1768 newmerged->count = count+1;
1769 newlist = newmerged->list;
1772 if (mlist->any > cls.any)
1774 *newlist++ = *mlist++;
1779 *newlist++ = *mlist++;
1782 /* Put the new mergedlist into dest. */
1783 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1784 dest->merged = newmerged;
1789 /* Returns: true if dest was changed. */
1792 typeinfo_merge_mergedlists(typeinfo *dest,typeinfo_mergedlist *x,
1793 typeinfo_mergedlist *y)
1797 typeinfo_mergedlist *temp,*result;
1798 classref_or_classinfo *clsx,*clsy,*newlist;
1800 /* count the elements that will be in the resulting list */
1801 /* (Both lists are sorted, equal elements are counted only once.) */
1806 while (countx && county) {
1807 if (clsx->any == clsy->any) {
1813 else if (clsx->any < clsy->any) {
1823 count += countx + county;
1825 /* {The new mergedlist will have count entries.} */
1827 if ((x->count != count) && (y->count == count)) {
1828 temp = x; x = y; y = temp;
1830 /* {If one of x,y is already the result it is x.} */
1831 if (x->count == count) {
1832 /* x->merged is equal to the result */
1833 if (x == dest->merged)
1836 if (!dest->merged || dest->merged->count != count) {
1837 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1838 TYPEINFO_ALLOCMERGED(dest->merged,count);
1839 dest->merged->count = count;
1842 newlist = dest->merged->list;
1845 *newlist++ = *clsx++;
1850 /* {We have to merge two lists.} */
1852 /* allocate the result list */
1853 TYPEINFO_ALLOCMERGED(result,count);
1854 result->count = count;
1855 newlist = result->list;
1857 /* merge the sorted lists */
1862 while (countx && county) {
1863 if (clsx->any == clsy->any) {
1864 *newlist++ = *clsx++;
1869 else if (clsx->any < clsy->any) {
1870 *newlist++ = *clsx++;
1874 *newlist++ = *clsy++;
1879 *newlist++ = *clsx++;
1881 *newlist++ = *clsy++;
1883 /* replace the list in dest with the result list */
1884 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1885 dest->merged = result;
1890 /* typeinfo_merge_nonarrays ****************************************************
1892 Merge two non-array types.
1895 x................the first type
1896 y................the second type
1897 mergedx..........merged list of the first type, may be NULL
1898 mergedy..........merged list of the descond type, may be NULL
1901 *dest............receives the resulting merged list
1902 *result..........receives the resulting type
1905 typecheck_TRUE...*dest has been modified
1906 typecheck_FALSE..*dest has not been modified
1907 typecheck_FAIL...an exception has been thrown
1910 RESULT is an extra parameter so it can point to dest->typeclass or to
1913 *******************************************************************************/
1915 static typecheck_result
1916 typeinfo_merge_nonarrays(typeinfo *dest,
1917 classref_or_classinfo *result,
1918 classref_or_classinfo x,classref_or_classinfo y,
1919 typeinfo_mergedlist *mergedx,
1920 typeinfo_mergedlist *mergedy)
1922 classref_or_classinfo t;
1923 classinfo *tcls,*common;
1924 typeinfo_mergedlist *tmerged;
1930 TYPEINFO_ASSERT(dest && result && x.any && y.any);
1931 TYPEINFO_ASSERT(x.cls != pseudo_class_Null);
1932 TYPEINFO_ASSERT(y.cls != pseudo_class_Null);
1933 TYPEINFO_ASSERT(x.cls != pseudo_class_New);
1934 TYPEINFO_ASSERT(y.cls != pseudo_class_New);
1936 /*--------------------------------------------------*/
1938 /*--------------------------------------------------*/
1940 /* Common case 1: x and y are the same class or class reference */
1941 /* (This case is very simple unless *both* x and y really represent
1942 * merges of subclasses of clsx==clsy.)
1944 if ( (x.any == y.any) && (!mergedx || !mergedy) ) {
1946 /* DEBUG */ /* log_text("return simple x"); */
1947 changed = (dest->merged != NULL);
1948 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
1949 dest->merged = NULL;
1951 /* DEBUG */ /* log_text("returning"); */
1955 xname = (IS_CLASSREF(x)) ? x.ref->name : x.cls->name;
1956 yname = (IS_CLASSREF(y)) ? y.ref->name : y.cls->name;
1958 /* Common case 2: xname == yname, at least one unresolved */
1959 if ((IS_CLASSREF(x) || IS_CLASSREF(y)) && (xname == yname))
1961 /* use the loaded one if any */
1962 if (!IS_CLASSREF(y))
1964 goto return_simple_x;
1967 /*--------------------------------------------------*/
1968 /* non-trivial cases */
1969 /*--------------------------------------------------*/
1971 #ifdef TYPEINFO_VERBOSE
1974 fprintf(stderr,"merge_nonarrays:\n");
1975 fprintf(stderr," ");if(IS_CLASSREF(x))fprintf(stderr,"<ref>");utf_fprint(stderr,xname);fprintf(stderr,"\n");
1976 fprintf(stderr," ");if(IS_CLASSREF(y))fprintf(stderr,"<ref>");utf_fprint(stderr,yname);fprintf(stderr,"\n");
1978 typeinfo_init_class(&dbgx,x);
1979 dbgx.merged = mergedx;
1980 typeinfo_init_class(&dbgy,y);
1981 dbgy.merged = mergedy;
1982 typeinfo_print(stderr,&dbgx,4);
1983 fprintf(stderr," with:\n");
1984 typeinfo_print(stderr,&dbgy,4);
1988 TYPEINFO_ASSERT(IS_CLASSREF(x) || (x.cls->state & CLASS_LOADED));
1989 TYPEINFO_ASSERT(IS_CLASSREF(y) || (y.cls->state & CLASS_LOADED));
1991 /* If y is unresolved or an interface, swap x and y. */
1992 if (IS_CLASSREF(y) || (!IS_CLASSREF(x) && y.cls->flags & ACC_INTERFACE))
1994 t = x; x = y; y = t;
1995 tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
1998 /* {We know: If only one of x,y is unresolved it is x,} */
1999 /* { If both x,y are resolved and only one of x,y is an interface it is x.} */
2001 if (IS_CLASSREF(x)) {
2002 /* {We know: x and y have different class names} */
2004 /* Check if we are merging an unresolved type with java.lang.Object */
2005 if (y.cls == class_java_lang_Object && !mergedy) {
2007 goto return_simple_x;
2010 common = class_java_lang_Object;
2011 goto merge_with_simple_x;
2014 /* {We know: both x and y are resolved} */
2015 /* {We know: If only one of x,y is an interface it is x.} */
2017 TYPEINFO_ASSERT(!IS_CLASSREF(x) && !IS_CLASSREF(y));
2018 TYPEINFO_ASSERT(x.cls->state & CLASS_LOADED);
2019 TYPEINFO_ASSERT(y.cls->state & CLASS_LOADED);
2021 /* Handle merging of interfaces: */
2022 if (x.cls->flags & ACC_INTERFACE) {
2023 /* {x.cls is an interface and mergedx == NULL.} */
2025 if (y.cls->flags & ACC_INTERFACE) {
2026 /* We are merging two interfaces. */
2027 /* {mergedy == NULL} */
2029 /* {We know that x.cls!=y.cls (see common case at beginning.)} */
2030 result->cls = class_java_lang_Object;
2031 return typeinfo_merge_two(dest,x,y);
2034 /* {We know: x is an interface, y is a class.} */
2036 /* Check if we are merging an interface with java.lang.Object */
2037 if (y.cls == class_java_lang_Object && !mergedy) {
2039 goto return_simple_x;
2042 /* If the type y implements x then the result of the merge
2043 * is x regardless of mergedy.
2046 /* we may have to link the classes */
2047 if (!(x.cls->state & CLASS_LINKED))
2048 if (!link_class(x.cls))
2049 return typecheck_FAIL;
2050 if (!(y.cls->state & CLASS_LINKED))
2051 if (!link_class(y.cls))
2052 return typecheck_FAIL;
2054 TYPEINFO_ASSERT(x.cls->state & CLASS_LINKED);
2055 TYPEINFO_ASSERT(y.cls->state & CLASS_LINKED);
2057 if (CLASSINFO_IMPLEMENTS_INTERFACE(y.cls,x.cls->index))
2059 /* y implements x, so the result of the merge is x. */
2060 goto return_simple_x;
2063 r = mergedlist_implements_interface(mergedy,x.cls);
2064 if (r == typecheck_FAIL)
2066 if (r == typecheck_TRUE)
2068 /* y implements x, so the result of the merge is x. */
2069 goto return_simple_x;
2072 /* {We know: x is an interface, the type y a class or a merge
2073 * of subclasses and is not guaranteed to implement x.} */
2075 common = class_java_lang_Object;
2076 goto merge_with_simple_x;
2079 /* {We know: x and y are classes (not interfaces).} */
2081 /* we may have to link the classes */
2082 if (!(x.cls->state & CLASS_LINKED))
2083 if (!link_class(x.cls))
2084 return typecheck_FAIL;
2085 if (!(y.cls->state & CLASS_LINKED))
2086 if (!link_class(y.cls))
2087 return typecheck_FAIL;
2089 TYPEINFO_ASSERT(x.cls->state & CLASS_LINKED);
2090 TYPEINFO_ASSERT(y.cls->state & CLASS_LINKED);
2092 /* If *x is deeper in the inheritance hierarchy swap x and y. */
2093 if (x.cls->index > y.cls->index) {
2094 t = x; x = y; y = t;
2095 tmerged = mergedx; mergedx = mergedy; mergedy = tmerged;
2098 /* {We know: y is at least as deep in the hierarchy as x.} */
2100 /* Find nearest common anchestor for the classes. */
2103 while (tcls->index > common->index)
2104 tcls = tcls->super.cls;
2105 while (common != tcls) {
2106 common = common->super.cls;
2107 tcls = tcls->super.cls;
2110 /* {common == nearest common anchestor of x and y.} */
2112 /* If x.cls==common and x is a whole class (not a merge of subclasses)
2113 * then the result of the merge is x.
2115 if (x.cls == common && !mergedx) {
2116 goto return_simple_x;
2120 result->cls = common;
2122 return typeinfo_merge_mergedlists(dest,mergedx,mergedy);
2124 return typeinfo_merge_add(dest,mergedx,y);
2127 merge_with_simple_x:
2128 result->cls = common;
2130 return typeinfo_merge_add(dest,mergedy,x);
2132 return typeinfo_merge_two(dest,x,y);
2135 /* typeinfo_merge **************************************************************
2140 m................method for exception messages
2141 dest.............the first type
2142 y................the second type
2145 *dest............receives the result of the merge
2148 typecheck_TRUE...*dest has been modified
2149 typecheck_FALSE..*dest has not been modified
2150 typecheck_FAIL...an exception has been thrown
2153 1) *dest must be a valid initialized typeinfo
2156 *******************************************************************************/
2159 typeinfo_merge(methodinfo *m,typeinfo *dest,typeinfo* y)
2163 classref_or_classinfo common;
2164 classref_or_classinfo elementclass;
2170 /*--------------------------------------------------*/
2172 /*--------------------------------------------------*/
2174 /* Merging something with itself is a nop */
2176 return typecheck_FALSE;
2178 /* Merging two returnAddress types is ok. */
2179 /* Merging two different returnAddresses never happens, as the verifier */
2180 /* keeps them separate in order to check all the possible return paths */
2181 /* from JSR subroutines. */
2182 if (!dest->typeclass.any && !y->typeclass.any) {
2183 TYPEINFO_ASSERT(TYPEINFO_RETURNADDRESS(*dest) == TYPEINFO_RETURNADDRESS(*y));
2184 return typecheck_FALSE;
2187 /* Primitive types cannot be merged with reference types */
2188 /* This must be checked before calls to typeinfo_merge. */
2189 TYPEINFO_ASSERT(dest->typeclass.any && y->typeclass.any);
2191 /* handle uninitialized object types */
2192 if (TYPEINFO_IS_NEWOBJECT(*dest) || TYPEINFO_IS_NEWOBJECT(*y)) {
2193 if (!TYPEINFO_IS_NEWOBJECT(*dest) || !TYPEINFO_IS_NEWOBJECT(*y)) {
2194 typeinfo_merge_error(m,"Trying to merge uninitialized object type.",dest,y);
2195 return typecheck_FAIL;
2197 if (TYPEINFO_NEWOBJECT_INSTRUCTION(*dest) != TYPEINFO_NEWOBJECT_INSTRUCTION(*y)) {
2198 typeinfo_merge_error(m,"Trying to merge different uninitialized objects.",dest,y);
2199 return typecheck_FAIL;
2201 /* the same uninitialized object -- no change */
2202 return typecheck_FALSE;
2205 /*--------------------------------------------------*/
2207 /*--------------------------------------------------*/
2209 /* Common case: dest and y are the same class or class reference */
2210 /* (This case is very simple unless *both* dest and y really represent
2211 * merges of subclasses of class dest==class y.)
2213 if ((dest->typeclass.any == y->typeclass.any) && (!dest->merged || !y->merged)) {
2215 changed = (dest->merged != NULL);
2216 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
2217 dest->merged = NULL;
2221 /* Handle null types: */
2222 if (TYPEINFO_IS_NULLTYPE(*y)) {
2223 return typecheck_FALSE;
2225 if (TYPEINFO_IS_NULLTYPE(*dest)) {
2226 TYPEINFO_FREEMERGED_IF_ANY(dest->merged);
2227 TYPEINFO_CLONE(*y,*dest);
2228 return typecheck_TRUE;
2231 /* Common case: two types with the same name, at least one unresolved */
2232 if (IS_CLASSREF(dest->typeclass)) {
2233 if (IS_CLASSREF(y->typeclass)) {
2234 if (dest->typeclass.ref->name == y->typeclass.ref->name)
2238 /* XXX should we take y instead of dest here? */
2239 if (dest->typeclass.ref->name == y->typeclass.cls->name)
2244 if (IS_CLASSREF(y->typeclass)
2245 && (dest->typeclass.cls->name == y->typeclass.ref->name))
2251 /*--------------------------------------------------*/
2252 /* non-trivial cases */
2253 /*--------------------------------------------------*/
2255 #ifdef TYPEINFO_VERBOSE
2256 fprintf(stderr,"merge:\n");
2257 typeinfo_print(stderr,dest,4);
2258 typeinfo_print(stderr,y,4);
2261 /* This function uses x internally, so x and y can be swapped
2262 * without changing dest. */
2266 /* Handle merging of arrays: */
2267 if (TYPEINFO_IS_ARRAY(*x) && TYPEINFO_IS_ARRAY(*y)) {
2269 /* Make x the one with lesser dimension */
2270 if (x->dimension > y->dimension) {
2271 tmp = x; x = y; y = tmp;
2274 /* If one array (y) has higher dimension than the other,
2275 * interpret it as an array (same dim. as x) of Arraystubs. */
2276 if (x->dimension < y->dimension) {
2277 dimension = x->dimension;
2278 elementtype = ARRAYTYPE_OBJECT;
2279 elementclass.cls = pseudo_class_Arraystub;
2282 dimension = y->dimension;
2283 elementtype = y->elementtype;
2284 elementclass = y->elementclass;
2287 /* {The arrays are of the same dimension.} */
2289 if (x->elementtype != elementtype) {
2290 /* Different element types are merged, so the resulting array
2291 * type has one accessible dimension less. */
2292 if (--dimension == 0) {
2293 common.cls = pseudo_class_Arraystub;
2295 elementclass.any = NULL;
2298 common.cls = class_multiarray_of(dimension,pseudo_class_Arraystub,true);
2300 *exceptionptr = new_internalerror("XXX Coult not create array class");
2301 return typecheck_FAIL;
2304 elementtype = ARRAYTYPE_OBJECT;
2305 elementclass.cls = pseudo_class_Arraystub;
2309 /* {The arrays have the same dimension and elementtype.} */
2311 if (elementtype == ARRAYTYPE_OBJECT) {
2312 /* The elements are references, so their respective
2313 * types must be merged.
2315 r = typeinfo_merge_nonarrays(dest,
2319 x->merged,y->merged);
2320 TYPEINFO_ASSERT(r != typecheck_MAYBE);
2321 if (r == typecheck_FAIL)
2325 /* DEBUG */ /* log_text("finding resulting array class: "); */
2326 if (IS_CLASSREF(elementclass))
2327 common.ref = class_get_classref_multiarray_of(dimension,elementclass.ref);
2329 common.cls = class_multiarray_of(dimension,elementclass.cls,true);
2331 *exceptionptr = new_internalerror("XXX Coult not create array class");
2332 return typecheck_FAIL;
2335 /* DEBUG */ /* utf_display(common->name); printf("\n"); */
2338 common.any = y->typeclass.any;
2343 /* {We know that at least one of x or y is no array, so the
2344 * result cannot be an array.} */
2346 r = typeinfo_merge_nonarrays(dest,
2348 x->typeclass,y->typeclass,
2349 x->merged,y->merged);
2350 TYPEINFO_ASSERT(r != typecheck_MAYBE);
2351 if (r == typecheck_FAIL)
2357 elementclass.any = NULL;
2360 /* Put the new values into dest if neccessary. */
2362 if (dest->typeclass.any != common.any) {
2363 dest->typeclass.any = common.any;
2366 if (dest->dimension != dimension) {
2367 dest->dimension = dimension;
2370 if (dest->elementtype != elementtype) {
2371 dest->elementtype = elementtype;
2374 if (dest->elementclass.any != elementclass.any) {
2375 dest->elementclass.any = elementclass.any;
2383 /**********************************************************************/
2384 /* DEBUGGING HELPERS */
2385 /**********************************************************************/
2387 #ifdef TYPEINFO_DEBUG
2391 typeinfo_test_compare(classref_or_classinfo *a,classref_or_classinfo *b)
2393 if (a->any == b->any) return 0;
2394 if (a->any < b->any) return -1;
2399 typeinfo_test_parse(typeinfo *info,char *str)
2406 utf *desc = utf_new_char(str);
2408 num = typeinfo_count_method_args(desc,false);
2410 typebuf = DMNEW(u1,num);
2411 infobuf = DMNEW(typeinfo,num);
2413 typeinfo_init_from_method_args(desc,typebuf,infobuf,num,false,
2416 TYPEINFO_ALLOCMERGED(info->merged,num);
2417 info->merged->count = num;
2419 for (i=0; i<num; ++i) {
2420 if (typebuf[i] != TYPE_ADDRESS) {
2421 log_text("non-reference type in mergedlist");
2425 info->merged->list[i].any = infobuf[i].typeclass.any;
2427 qsort(info->merged->list,num,sizeof(classref_or_classinfo),
2428 (int(*)(const void *,const void *))&typeinfo_test_compare);
2431 typeinfo_init_from_method_args(desc,NULL,NULL,0,false,
2437 #define TYPEINFO_TEST_BUFLEN 4000
2440 typeinfo_equal(typeinfo *x,typeinfo *y)
2444 if (x->typeclass.any != y->typeclass.any) return false;
2445 if (x->dimension != y->dimension) return false;
2447 if (x->elementclass.any != y->elementclass.any) return false;
2448 if (x->elementtype != y->elementtype) return false;
2451 if (TYPEINFO_IS_NEWOBJECT(*x))
2452 if (TYPEINFO_NEWOBJECT_INSTRUCTION(*x)
2453 != TYPEINFO_NEWOBJECT_INSTRUCTION(*y))
2456 if (x->merged || y->merged) {
2457 if (!(x->merged && y->merged)) return false;
2458 if (x->merged->count != y->merged->count) return false;
2459 for (i=0; i<x->merged->count; ++i)
2460 if (x->merged->list[i].any != y->merged->list[i].any)
2467 typeinfo_testmerge(typeinfo *a,typeinfo *b,typeinfo *result,int *failed)
2470 bool changed,changed_should_be;
2473 TYPEINFO_CLONE(*a,dest);
2476 typeinfo_print_short(stdout,&dest);
2478 typeinfo_print_short(stdout,b);
2481 r = typeinfo_merge(NULL,&dest,b);
2482 if (r == typecheck_FAIL) {
2483 printf("EXCEPTION\n");
2486 changed = (r) ? 1 : 0;
2487 changed_should_be = (!typeinfo_equal(&dest,a)) ? 1 : 0;
2489 printf(" %s\n",(changed) ? "changed" : "=");
2491 if (typeinfo_equal(&dest,result)) {
2493 typeinfo_print_short(stdout,&dest);
2495 if (changed != changed_should_be) {
2496 printf("WRONG RETURN VALUE!\n");
2502 typeinfo_print_short(stdout,&dest);
2504 printf("SHOULD BE ");
2505 typeinfo_print_short(stdout,result);
2513 typeinfo_inc_dimension(typeinfo *info)
2515 if (info->dimension++ == 0) {
2516 info->elementtype = ARRAYTYPE_OBJECT;
2517 info->elementclass = info->typeclass;
2519 info->typeclass = class_array_of(info->typeclass,true);
2523 #define TYPEINFO_TEST_MAXDIM 10
2526 typeinfo_testrun(char *filename)
2528 char buf[TYPEINFO_TEST_BUFLEN];
2529 char bufa[TYPEINFO_TEST_BUFLEN];
2530 char bufb[TYPEINFO_TEST_BUFLEN];
2531 char bufc[TYPEINFO_TEST_BUFLEN];
2535 FILE *file = fopen(filename,"rt");
2539 log_text("could not open typeinfo test file");
2543 while (fgets(buf,TYPEINFO_TEST_BUFLEN,file)) {
2544 if (buf[0] == '#' || !strlen(buf))
2547 res = sscanf(buf,"%s\t%s\t%s\n",bufa,bufb,bufc);
2548 if (res != 3 || !strlen(bufa) || !strlen(bufb) || !strlen(bufc)) {
2549 log_text("Invalid line in typeinfo test file (none of empty, comment or test)");
2554 typeinfo_test_parse(&a,bufa);
2555 typeinfo_test_parse(&b,bufb);
2556 typeinfo_test_parse(&c,bufc);
2561 typeinfo_testmerge(&a,&b,&c,&failed); /* check result */
2562 typeinfo_testmerge(&b,&a,&c,&failed); /* check commutativity */
2564 if (TYPEINFO_IS_NULLTYPE(a)) break;
2565 if (TYPEINFO_IS_NULLTYPE(b)) break;
2566 if (TYPEINFO_IS_NULLTYPE(c)) break;
2568 maxdim = a.dimension;
2569 if (b.dimension > maxdim) maxdim = b.dimension;
2570 if (c.dimension > maxdim) maxdim = c.dimension;
2573 if (maxdim < TYPEINFO_TEST_MAXDIM) {
2574 typeinfo_inc_dimension(&a);
2575 typeinfo_inc_dimension(&b);
2576 typeinfo_inc_dimension(&c);
2578 } while (maxdim < TYPEINFO_TEST_MAXDIM);
2585 fprintf(stderr,"Failed typeinfo_merge tests: %d\n",failed);
2586 log_text("Failed test");
2594 log_text("Running typeinfo test file...");
2595 typeinfo_testrun("typeinfo.tst");
2596 log_text("Finished typeinfo test file.");
2601 typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc)
2603 typeinfo_init_from_descriptor(info,desc,desc+strlen(desc));
2607 #define TYPEINFO_MAXINDENT 80
2610 typeinfo_print_class(FILE *file,classref_or_classinfo c)
2612 /*fprintf(file,"<class %p>",c.any);*/
2615 fprintf(file,"<null>");
2618 if (IS_CLASSREF(c)) {
2619 fprintf(file,"<ref>");
2620 utf_fprint(file,c.ref->name);
2623 utf_fprint(file,c.cls->name);
2629 typeinfo_print(FILE *file,typeinfo *info,int indent)
2632 char ind[TYPEINFO_MAXINDENT + 1];
2636 if (indent > TYPEINFO_MAXINDENT) indent = TYPEINFO_MAXINDENT;
2638 for (i=0; i<indent; ++i)
2642 if (TYPEINFO_IS_PRIMITIVE(*info)) {
2643 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
2645 fprintf(file,"%sreturnAddress (L%03d)\n",ind,bptr->debug_nr);
2647 fprintf(file,"%sprimitive\n",ind);
2651 if (TYPEINFO_IS_NULLTYPE(*info)) {
2652 fprintf(file,"%snull\n",ind);
2656 if (TYPEINFO_IS_NEWOBJECT(*info)) {
2657 ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
2659 fprintf(file,"%sNEW(%p):",ind,(void*)ins);
2660 typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].target));
2664 fprintf(file,"%sNEW(this)",ind);
2669 fprintf(file,"%sClass: ",ind);
2670 typeinfo_print_class(file,info->typeclass);
2673 if (TYPEINFO_IS_ARRAY(*info)) {
2674 fprintf(file,"%sDimension: %d",ind,(int)info->dimension);
2675 fprintf(file,"\n%sElements: ",ind);
2676 switch (info->elementtype) {
2677 case ARRAYTYPE_INT : fprintf(file,"int\n"); break;
2678 case ARRAYTYPE_LONG : fprintf(file,"long\n"); break;
2679 case ARRAYTYPE_FLOAT : fprintf(file,"float\n"); break;
2680 case ARRAYTYPE_DOUBLE : fprintf(file,"double\n"); break;
2681 case ARRAYTYPE_BYTE : fprintf(file,"byte\n"); break;
2682 case ARRAYTYPE_CHAR : fprintf(file,"char\n"); break;
2683 case ARRAYTYPE_SHORT : fprintf(file,"short\n"); break;
2684 case ARRAYTYPE_BOOLEAN : fprintf(file,"boolean\n"); break;
2686 case ARRAYTYPE_OBJECT:
2687 typeinfo_print_class(file,info->elementclass);
2692 fprintf(file,"INVALID ARRAYTYPE!\n");
2697 fprintf(file,"%sMerged: ",ind);
2698 for (i=0; i<info->merged->count; ++i) {
2699 if (i) fprintf(file,", ");
2700 typeinfo_print_class(file,info->merged->list[i]);
2707 typeinfo_print_short(FILE *file,typeinfo *info)
2713 /*fprintf(file,"<typeinfo %p>",info);*/
2716 fprintf(file,"(typeinfo*)NULL");
2720 if (TYPEINFO_IS_PRIMITIVE(*info)) {
2721 bptr = (basicblock*) TYPEINFO_RETURNADDRESS(*info);
2723 fprintf(file,"ret(L%03d)",bptr->debug_nr);
2725 fprintf(file,"primitive");
2729 if (TYPEINFO_IS_NULLTYPE(*info)) {
2730 fprintf(file,"null");
2734 if (TYPEINFO_IS_NEWOBJECT(*info)) {
2735 ins = (instruction *)TYPEINFO_NEWOBJECT_INSTRUCTION(*info);
2737 /*fprintf(file,"<ins %p>",ins);*/
2738 fprintf(file,"NEW(%p):",(void*)ins);
2739 typeinfo_print_class(file,CLASSREF_OR_CLASSINFO(ins[-1].target));
2742 fprintf(file,"NEW(this)");
2746 typeinfo_print_class(file,info->typeclass);
2750 for (i=0; i<info->merged->count; ++i) {
2751 if (i) fprintf(file,",");
2752 typeinfo_print_class(file,info->merged->list[i]);
2759 typeinfo_print_type(FILE *file,int type,typeinfo *info)
2762 case TYPE_VOID: fprintf(file,"V"); break;
2763 case TYPE_INT: fprintf(file,"I"); break;
2764 case TYPE_FLOAT: fprintf(file,"F"); break;
2765 case TYPE_DOUBLE: fprintf(file,"D"); break;
2766 case TYPE_LONG: fprintf(file,"J"); break;
2768 typeinfo_print_short(file,info);
2777 typeinfo_print_stacktype(FILE *file,int type,typeinfo *info)
2779 TYPEINFO_ASSERT(file);
2780 TYPEINFO_ASSERT(type != TYPE_ADDRESS || info != NULL);
2781 if (type == TYPE_ADDRESS && TYPEINFO_IS_PRIMITIVE(*info)) {
2782 typeinfo_retaddr_set *set = (typeinfo_retaddr_set*)
2783 TYPEINFO_RETURNADDRESS(*info);
2785 fprintf(file,"ret(L%03d",((basicblock*)(set->addr))->debug_nr);
2788 fprintf(file,"|L%03d",((basicblock*)(set->addr))->debug_nr);
2793 fprintf(file,"ret(<NULL>");
2798 typeinfo_print_type(file,type,info);
2802 typedescriptor_print(FILE *file,typedescriptor *td)
2804 typeinfo_print_type(file,td->type,&(td->info));
2808 typevector_print(FILE *file,typevector *vec,int size)
2812 fprintf(file,"[%d]",vec->k);
2813 for (i=0; i<size; ++i) {
2814 fprintf(file," %d=",i);
2815 typedescriptor_print(file,vec->td + i);
2820 typevectorset_print(FILE *file,typevector *set,int size)
2825 fprintf(file,"[%d",set->k);
2828 fprintf(file,"|%d",vec->k);
2833 for (i=0; i<size; ++i) {
2834 fprintf(file," %d=",i);
2835 typedescriptor_print(file,set->td + i);
2839 typedescriptor_print(file,vec->td + i);
2845 #endif /* TYPEINFO_DEBUG */
2849 * These are local overrides for various environment variables in Emacs.
2850 * Please do not remove this and leave it at the end of the file, where
2851 * Emacs will automagically detect them.
2852 * ---------------------------------------------------------------------
2855 * indent-tabs-mode: t
2859 * vim:noexpandtab:sw=4:ts=4: