GNU header update.
[cacao.git] / src / vm / jit / verify / typeinfo.h
index 58b677b08d91e385d955209463d95c8f2130882e..076ead4f78437490b9583f83869faeeb653d9a82 100644 (file)
@@ -1,9 +1,9 @@
 /* typeinfo.h - type system used by the type checker
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
-   M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
-   P. Tomsich, J. Wenninger
+   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+   Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
@@ -26,7 +26,7 @@
 
    Authors: Edwin Steiner
 
-   $Id: typeinfo.h 706 2003-12-07 17:28:29Z twisti $
+   $Id: typeinfo.h 1735 2004-12-07 14:33:27Z twisti $
 
 */
 
 #ifndef _TYPEINFO_H
 #define _TYPEINFO_H
 
-#include <stdio.h>
-#include "global.h"
+#include "vm/global.h"
 
 /* resolve typedef cycles *****************************************************/
 
 typedef struct typeinfo typeinfo;
 typedef struct typeinfo_mergedlist typeinfo_mergedlist;
+typedef struct typedescriptor typedescriptor;
+typedef struct typevector typevector;
+typedef struct typeinfo_retaddr_set typeinfo_retaddr_set;
 
-/* global variables ***********************************************************/
-
-/* XXX move this documentation to global.h */
-/* The following classinfo pointers are used internally by the type system.
- * Please do not use them directly, use the TYPEINFO_ macros instead.
- */
+/* data structures for the type system ****************************************/
 
-/*
- * pseudo_class_Arraystub
- *     (extends Object implements Cloneable, java.io.Serializable)
+/* The typeinfo structure stores detailed information on address types.
+ * (stack elements, variables, etc. with type == TYPE_ADR.)
  *
- *     If two arrays of incompatible component types are merged,
- *     the resulting reference has no accessible components.
- *     The result does, however, implement the interfaces Cloneable
- *     and java.io.Serializable. This pseudo class is used internally
- *     to represent such results. (They are *not* considered arrays!)
+ * There are two kinds of address types which can are distinguished by
+ * the value of the typeclass field:
  *
- * pseudo_class_Null
+ * 1) typeclass == NULL: returnAddress type
+ *                       use TYPEINFO_IS_PRIMITIVE to test for this
  *
- *     This pseudo class is used internally to represent the
- *     null type.
- */
-
-/* data structures for the type system ****************************************/
-
-/* The typeinfo structure stores detailed information on reference types.
- * (stack elements, variables, etc. with type == TYPE_ADR.)
- * XXX: exclude ReturnAddresses?
+ * 2) typeclass != NULL: reference type
+ *                       use TYPEINFO_IS_REFERENCE to test for this
  *
- * For primitive types either there is no typeinfo allocated or the
- * typeclass pointer in the typeinfo struct is NULL.
+ * Note: For non-address types either there is no typeinfo allocated
+ * or the fields of the typeinfo struct contain undefined values!
  *
  * CAUTION: The typeinfo structure should be considered opaque outside of
  *          typeinfo.[ch]. Please use the macros and functions defined here to
@@ -84,38 +71,69 @@ typedef struct typeinfo_mergedlist typeinfo_mergedlist;
  *
  * A) typeclass == NULL
  *
- *        In this case the other fields of the structure
- *        are INVALID.
+ *        This is a returnAddress type. The interpretation of the
+ *        elementclass field depends on wether this typeinfo describes
+ *        a stack slot or a local variable:
+ *
+ *        stack slot: elementclass is a pointer to a
+ *            typeinfo_retaddr_set which contains a return target for
+ *            every vector in the current set of local variable vectors.
+ *        local variable: elementclass is the return target (when cast
+ *            to basicblock *)
+ *
+ *        Use TYPEINFO_IS_PRIMITIVE to check for this.
+ *        Use TYPEINFO_RETURNADDRESS to access the pointer in elementclass.
+ *        Don't access other fields of the struct.
  *
  * B) typeclass == pseudo_class_Null
  *
- *        XXX
+ *        This is the null-reference type. Use TYPEINFO_IS_NULLTYPE to check for this.
+ *        Don't access other fields of the struct.
+ *
+ * C) typeclass == pseudo_class_New
  *
- * C) typeclass is an array class
+ *        This is a 'uninitialized object' type. elementclass can be
+ *        cast to instruction* and points to the NEW instruction
+ *        responsible for creating this type.
  *
- *        XXX
+ *        Use TYPEINFO_NEWOBJECT_INSTRUCTION to access the pointer in
+ *        elementclass.
+ *        Don't access other fields of the struct.
  *
  * D) typeclass == pseudo_class_Arraystub
  *
- *        XXX
+ *        See global.h for a describes of pseudo_class_Arraystub.
+ *        Otherwise like a normal class reference type.
+ *        Don't access other fields of the struct.
+ *
+ * E) typeclass is an array class
  *
- * E) typeclass is an interface
+ *        An array reference.
+ *            elementclass...typeclass of the element type
+ *            dimension......dimension of the array (>=1)
+ *            elementtype....element type (ARRAYTYPE_...)
+ *            merged.........mergedlist of the element type
  *
- *        XXX
+ * F) typeclass is an interface
  *
- * F) typeclass is a (non-pseudo-)class != java.lang.Object
+ *        An interface reference type.
+ *        Don't access other fields of the struct.
  *
- *        XXX
+ * G) typeclass is a (non-pseudo-,non-array-)class != java.lang.Object
+ *
+ *        A class reference type.
  *        All classinfos in u.merged.list (if any) are
- *        subclasses of typeclass.
+ *        subclasses of typeclass (no interfaces or array classes).
+ *        Don't access other fields of the struct.
  *
- * G) typeclass is java.lang.Object
+ * H) typeclass is java.lang.Object
  *
- *        XXX
+ *        The most general kind of reference type.
  *        In this case u.merged.count and u.merged.list
  *        are valid and may be non-zero.
- *        The classinfos in u.merged.list (if any) can be
- *        classes, interfaces or pseudo classes.
+ *        The classinfos in u.merged.list (if any) may be
+ *        classes, interfaces and pseudo classes.
+ *        Don't access other fields of the struct.
  */
 
 /* The following algorithm is used to determine if the type described
@@ -123,7 +141,7 @@ typedef struct typeinfo_mergedlist typeinfo_mergedlist;
  *
  *     1) If typeclass is X or a subinterface of X the answer is "yes".
  *     2) If typeclass is a (pseudo) class implementing X the answer is "yes".
- *     3) XXX If typeclass is not an array and u.merged.count>0
+ *     3) If typeclass is not an array and u.merged.count>0
  *        and all classes/interfaces in u.merged.list implement X
  *        the answer is "yes".
  *     4) If none of the above is true the answer is "no".
@@ -135,35 +153,73 @@ typedef struct typeinfo_mergedlist typeinfo_mergedlist;
  *          access typeinfo structures!
  */
 struct typeinfo {
-        classinfo           *typeclass;
-        classinfo           *elementclass; /* valid if dimension>0 */
-        typeinfo_mergedlist *merged;
-        u1                   dimension;
-        u1                   elementtype;  /* valid if dimension>0 */
+       classinfo           *typeclass;
+       classinfo           *elementclass; /* valid if dimension>0 */ /* various uses! */
+       typeinfo_mergedlist *merged;
+       u1                   dimension;
+       u1                   elementtype;  /* valid if dimension>0 */
 };
 
 struct typeinfo_mergedlist {
-        s4         count;
-        classinfo *list[1]; /* variable length! */
+       s4         count;
+       classinfo *list[1];       /* variable length!                        */
+};
+
+struct typeinfo_retaddr_set {
+       typeinfo_retaddr_set *alt;  /* next alternative in set               */
+       void                 *addr; /* return address                        */
+};
+
+struct typedescriptor {
+       typeinfo        info;     /* valid if type == TYPE_ADR               */
+       u1              type;     /* basic type (TYPE_INT, ...)              */
+};
+
+/* typevectors are used to store the types of local variables */
+
+struct typevector {
+       typevector      *alt;     /* next alternative in typevector set */
+       int              k;       /* for lining up with the stack set   */
+       typedescriptor   td[1];   /* variable length!                   */
 };
 
 /****************************************************************************/
 /* MACROS                                                                   */
 /****************************************************************************/
 
-/* XXX wrap macro blocks in do { } while(0) */
-
-/* NOTE: These macros take typeinfo *structs* not pointers as arguments.
- *       You have to dereference any pointers.
+/* NOTE: The TYPEINFO macros take typeinfo *structs*, not pointers as
+ *       arguments.  You have to dereference any pointers.
  */
 
+/* typevectors **************************************************************/
+
+#define TYPEVECTOR_SIZE(size)                                          \
+    ((sizeof(typevector) - sizeof(typedescriptor))     \
+     + (size)*sizeof(typedescriptor))
+
+#define DNEW_TYPEVECTOR(size)                                          \
+    ((typevector*)dump_alloc(TYPEVECTOR_SIZE(size)))
+
+#define DMNEW_TYPEVECTOR(num,size)                                             \
+    ((void*)dump_alloc((num) * TYPEVECTOR_SIZE(size)))
+
+#define MGET_TYPEVECTOR(array,index,size) \
+    ((typevector*) (((u1*)(array)) + TYPEVECTOR_SIZE(size) * (index)))
+
+#define COPY_TYPEVECTORSET(src,dst,size)                                               \
+    do {memcpy(dst,src,TYPEVECTOR_SIZE(size));                                 \
+        dst->k = 0;                                             \
+        if ((src)->alt) {                                                                              \
+               (dst)->alt = typevectorset_copy((src)->alt,1,size);     \
+        }} while(0)
+
 /* internally used macros ***************************************************/
 
 /* internal, don't use this explicitly! */
 #define TYPEINFO_ALLOCMERGED(mergedlist,count)                  \
-            {(mergedlist) = (typeinfo_mergedlist*)dump_alloc(   \
-                sizeof(typeinfo_mergedlist)                     \
-                + ((count)-1)*sizeof(classinfo*));}
+    do {(mergedlist) = (typeinfo_mergedlist*)dump_alloc(        \
+            sizeof(typeinfo_mergedlist)                         \
+            + ((count)-1)*sizeof(classinfo*));} while(0)
 
 /* internal, don't use this explicitly! */
 #define TYPEINFO_FREEMERGED(mergedlist)
@@ -182,6 +238,17 @@ struct typeinfo_mergedlist {
 #define TYPEINFO_IS_NULLTYPE(info)                              \
             ((info).typeclass == pseudo_class_Null)
 
+#define TYPEINFO_IS_NEWOBJECT(info)                             \
+            ((info).typeclass == pseudo_class_New)
+
+/* only use this if TYPEINFO_IS_PRIMITIVE returned true! */
+#define TYPEINFO_RETURNADDRESS(info)                            \
+            ((void *)(info).elementclass)
+
+/* only use this if TYPEINFO_IS_NEWOBJECT returned true! */
+#define TYPEINFO_NEWOBJECT_INSTRUCTION(info)                    \
+            ((void *)(info).elementclass)
+
 /* macros for array type queries ********************************************/
 
 #define TYPEINFO_IS_ARRAY(info)                                 \
@@ -211,7 +278,21 @@ struct typeinfo_mergedlist {
             ( TYPEINFO_IS_ARRAY(info)                           \
               && TYPEINFO_IS_ARRAY_OF_REFS_NOCHECK(info) )
 
-/* queries allowing null types **********************************************/
+#define TYPE_IS_RETURNADDRESS(type,info)                        \
+            ( ((type)==TYPE_ADDRESS)                            \
+              && TYPEINFO_IS_PRIMITIVE(info) )
+
+#define TYPE_IS_REFERENCE(type,info)                            \
+            ( ((type)==TYPE_ADDRESS)                            \
+              && !TYPEINFO_IS_PRIMITIVE(info) )
+
+#define TYPEDESC_IS_RETURNADDRESS(td)                           \
+            TYPE_IS_RETURNADDRESS((td).type,(td).info)
+
+#define TYPEDESC_IS_REFERENCE(td)                               \
+            TYPE_IS_REFERENCE((td).type,(td).info)
+
+/* queries allowing the null type ********************************************/
 
 #define TYPEINFO_MAYBE_ARRAY(info)                              \
     (TYPEINFO_IS_ARRAY(info) || TYPEINFO_IS_NULLTYPE(info))
@@ -222,93 +303,106 @@ struct typeinfo_mergedlist {
 #define TYPEINFO_MAYBE_ARRAY_OF_REFS(info)                      \
     (TYPEINFO_IS_ARRAY_OF_REFS(info) || TYPEINFO_IS_NULLTYPE(info))
 
-
 /* macros for initializing typeinfo structures ******************************/
 
 #define TYPEINFO_INIT_PRIMITIVE(info)                           \
-            {(info).typeclass = NULL;                           \
+         do {(info).typeclass = NULL;                           \
              (info).elementclass = NULL;                        \
              (info).merged = NULL;                              \
              (info).dimension = 0;                              \
-             (info).elementtype = 0;}
+             (info).elementtype = 0;} while(0)
+
+#define TYPEINFO_INIT_RETURNADDRESS(info,adr)                   \
+         do {(info).typeclass = NULL;                           \
+             (info).elementclass = (classinfo*) (adr);          \
+             (info).merged = NULL;                              \
+             (info).dimension = 0;                              \
+             (info).elementtype = 0;} while(0)
 
 #define TYPEINFO_INIT_NON_ARRAY_CLASSINFO(info,cinfo)   \
-            {(info).typeclass = (cinfo);                \
+         do {(info).typeclass = (cinfo);                \
              (info).elementclass = NULL;                \
              (info).merged = NULL;                      \
              (info).dimension = 0;                      \
-             (info).elementtype = 0;}
+             (info).elementtype = 0;} while(0)
 
 #define TYPEINFO_INIT_NULLTYPE(info)                            \
             TYPEINFO_INIT_CLASSINFO(info,pseudo_class_Null)
 
+#define TYPEINFO_INIT_NEWOBJECT(info,instr)             \
+         do {(info).typeclass = pseudo_class_New;       \
+             (info).elementclass = (classinfo*) (instr);\
+             (info).merged = NULL;                      \
+             (info).dimension = 0;                      \
+             (info).elementtype = 0;} while(0)
+
 #define TYPEINFO_INIT_PRIMITIVE_ARRAY(info,arraytype)                   \
     TYPEINFO_INIT_CLASSINFO(info,primitivetype_table[arraytype].arrayclass);
 
 #define TYPEINFO_INIT_CLASSINFO(info,cls)                               \
-        {if (((info).typeclass = (cls))->vftbl->arraydesc) {              \
-                if ((cls)->vftbl->arraydesc->elementvftbl)                \
+        do {if (((info).typeclass = (cls))->vftbl->arraydesc) {         \
+                if ((cls)->vftbl->arraydesc->elementvftbl)              \
                     (info).elementclass = (cls)->vftbl->arraydesc->elementvftbl->class; \
                 else                                                    \
                     (info).elementclass = NULL;                         \
-                (info).dimension = (cls)->vftbl->arraydesc->dimension;    \
-                (info).elementtype = (cls)->vftbl->arraydesc->elementtype;\
+                (info).dimension = (cls)->vftbl->arraydesc->dimension;  \
+                (info).elementtype = (cls)->vftbl->arraydesc->elementtype; \
             }                                                           \
             else {                                                      \
                 (info).elementclass = NULL;                             \
                 (info).dimension = 0;                                   \
                 (info).elementtype = 0;                                 \
             }                                                           \
-            (info).merged = NULL;}
+            (info).merged = NULL;} while(0)
 
 #define TYPEINFO_INIT_FROM_FIELDINFO(info,fi)                   \
             typeinfo_init_from_descriptor(&(info),              \
                 (fi)->descriptor->text,utf_end((fi)->descriptor));
 
-/* macros for freeing typeinfo structures ***********************************/
-
-#define TYPEINFO_FREE(info)                                     \
-            {TYPEINFO_FREEMERGED_IF_ANY((info).merged);         \
-             (info).merged = NULL;}
-
-/* macros for writing types (destination must have been initialized) ********/
-/* XXX delete them? */
-
-#define TYPEINFO_PUT_NULLTYPE(info)                             \
-            {(info).typeclass = pseudo_class_Null;}
-
-#define TYPEINFO_PUT_NON_ARRAY_CLASSINFO(info,cinfo)            \
-            {(info).typeclass = (cinfo);}
-
-#define TYPEINFO_PUT_CLASSINFO(info,cls)                                \
-        {if (((info).typeclass = (cls))->vftbl->arraydesc) {              \
-                if ((cls)->vftbl->arraydesc->elementvftbl)                \
-                    (info).elementclass = (cls)->vftbl->arraydesc->elementvftbl->class; \
-                (info).dimension = (cls)->vftbl->arraydesc->dimension;    \
-                (info).elementtype = (cls)->vftbl->arraydesc->elementtype; \
-            }}
-
-/* srcarray must be an array (not checked) */
-#define TYPEINFO_PUT_COMPONENT(srcarray,dst)                    \
-            {typeinfo_put_component(&(srcarray),&(dst));}
-
 /* macros for copying types (destinition is not checked or freed) ***********/
 
 /* TYPEINFO_COPY makes a shallow copy, the merged pointer is simply copied. */
 #define TYPEINFO_COPY(src,dst)                                  \
-            {(dst) = (src);}
+    do {(dst) = (src);} while(0)
 
 /* TYPEINFO_CLONE makes a deep copy, the merged list (if any) is duplicated
  * into a newly allocated array.
  */
 #define TYPEINFO_CLONE(src,dst)                                 \
-            {(dst) = (src);                                     \
-             if ((dst).merged) typeinfo_clone(&(src),&(dst));}
+    do {(dst) = (src);                                          \
+        if ((dst).merged) typeinfo_clone(&(src),&(dst));} while(0)
 
 /****************************************************************************/
 /* FUNCTIONS                                                                */
 /****************************************************************************/
 
+/* typevector functions *****************************************************/
+
+/* element read-only access */
+bool typevectorset_checktype(typevector *set,int index,int type);
+bool typevectorset_checkreference(typevector *set,int index);
+bool typevectorset_checkretaddr(typevector *set,int index);
+int typevectorset_copymergedtype(typevector *set,int index,typeinfo *dst);
+typeinfo *typevectorset_mergedtypeinfo(typevector *set,int index,typeinfo *temp);
+int typevectorset_mergedtype(typevector *set,int index,typeinfo *temp,typeinfo **result);
+
+/* element write access */
+void typevectorset_store(typevector *set,int index,int type,typeinfo *info);
+void typevectorset_store_retaddr(typevector *set,int index,typeinfo *info);
+void typevectorset_store_twoword(typevector *set,int index,int type);
+void typevectorset_init_object(typevector *set,void *ins,classinfo *initclass,int size);
+
+/* vector functions */
+bool typevector_separable_from(typevector *a,typevector *b,int size);
+bool typevector_merge(typevector *dst,typevector *y,int size);
+
+/* vector set functions */
+typevector *typevectorset_copy(typevector *src,int k,int size);
+bool typevectorset_separable_with(typevector *set,typevector *add,int size);
+bool typevectorset_collapse(typevector *dst,int size);
+void typevectorset_add(typevector *dst,typevector *v,int size);
+typevector *typevectorset_select(typevector **set,int retindex,void *retaddr);
+
 /* inquiry functions (read-only) ********************************************/
 
 bool typeinfo_is_array(typeinfo *info);
@@ -317,6 +411,7 @@ bool typeinfo_is_array_of_refs(typeinfo *info);
 
 bool typeinfo_implements_interface(typeinfo *info,classinfo *interf);
 bool typeinfo_is_assignable(typeinfo *value,typeinfo *dest);
+bool typeinfo_is_assignable_to_classinfo(typeinfo *value,classinfo *dest);
 
 /* initialization functions *************************************************/
 
@@ -328,6 +423,10 @@ void typeinfo_init_from_method_args(utf *desc,u1 *typebuf,
                                     typeinfo *infobuf,
                                     int buflen,bool twoword,
                                     int *returntype,typeinfo *returntypeinfo);
+int  typedescriptors_init_from_method_args(typedescriptor *td,
+                                                                                  utf *desc,
+                                                                                  int buflen,bool twoword,
+                                                                                  typedescriptor *returntype);
 
 void typeinfo_clone(typeinfo *src,typeinfo *dest);
 
@@ -341,13 +440,19 @@ bool typeinfo_merge(typeinfo *dest,typeinfo* y);
 
 #ifdef TYPEINFO_DEBUG
 
+#include <stdio.h>
+
 void typeinfo_test();
 void typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc);
 void typeinfo_print(FILE *file,typeinfo *info,int indent);
 void typeinfo_print_short(FILE *file,typeinfo *info);
 void typeinfo_print_type(FILE *file,int type,typeinfo *info);
+void typeinfo_print_stacktype(FILE *file,int type,typeinfo *info);
+void typedescriptor_print(FILE *file,typedescriptor *td);
+void typevector_print(FILE *file,typevector *vec,int size);
+void typevectorset_print(FILE *file,typevector *set,int size);
 
-#endif // TYPEINFO_DEBUG
+#endif /* TYPEINFO_DEBUG */
 
 #endif /* _TYPEINFO_H */