-/* typeinfo.h - type system used by the type checker
+/* src/vm/jit/verify/typeinfo.h - type system used by the type checker
- 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
+ Copyright (C) 1996-2005, 2006, 2007 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.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA.
-
- Contact: cacao@complang.tuwien.ac.at
-
- Authors: Edwin Steiner
-
- $Id: typeinfo.h 1735 2004-12-07 14:33:27Z twisti $
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA.
*/
-
#ifndef _TYPEINFO_H
#define _TYPEINFO_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;
+
+#include "config.h"
+#include "vm/types.h"
+
+#include "vm/global.h"
+
+#include "vmcore/references.h"
+
+
+/* configuration **************************************************************/
+
+/*
+ * TYPECHECK_STATISTICS activates gathering statistical information.
+ * TYPEINFO_DEBUG activates debug checks and debug helpers in typeinfo.c
+ * TYPECHECK_DEBUG activates debug checks in typecheck.c
+ * TYPEINFO_DEBUG_TEST activates the typeinfo test at startup.
+ * TYPECHECK_VERBOSE_IMPORTANT activates important debug messages
+ * TYPECHECK_VERBOSE activates all debug messages
+ * TYPEINFO_VERBOSE activates debug prints in typeinfo.c
+ */
+#ifdef ENABLE_VERIFIER
+#ifndef NDEBUG
+/*#define TYPECHECK_STATISTICS*/
+#define TYPEINFO_DEBUG
+/*#define TYPEINFO_VERBOSE*/
+#define TYPECHECK_DEBUG
+/*#define TYPEINFO_DEBUG_TEST*/
+/*#define TYPECHECK_VERBOSE*/
+/*#define TYPECHECK_VERBOSE_IMPORTANT*/
+#if defined(TYPECHECK_VERBOSE) || defined(TYPECHECK_VERBOSE_IMPORTANT)
+#define TYPECHECK_VERBOSE_OPT
+#endif
+#endif
+#endif
+
+#ifdef TYPECHECK_VERBOSE_OPT
+extern bool opt_typecheckverbose;
+#endif
+
+/* types **********************************************************************/
+
+/* typecheck_result - return type for boolean and tristate functions */
+/* which may also throw exceptions (typecheck_FAIL). */
+
+/* NOTE: Use the enum values, not the uppercase #define macros! */
+#define TYPECHECK_MAYBE 0x02
+#define TYPECHECK_FAIL 0x04
+
+typedef enum {
+ typecheck_FALSE = false,
+ typecheck_TRUE = true,
+ typecheck_MAYBE = TYPECHECK_MAYBE,
+ typecheck_FAIL = TYPECHECK_FAIL
+} typecheck_result;
+
+/* check that typecheck_MAYBE is not ambiguous */
+#if TYPECHECK_MAYBE == true
+#error "`typecheck_MAYBE` must not be the same as `true`"
+#endif
+#if TYPECHECK_MAYBE == false
+#error "`typecheck_MAYBE` must not be the same as `false`"
+#endif
+
+/* check that typecheck_FAIL is not ambiguous */
+#if (true & TYPECHECK_FAIL) != 0
+#error "`true` must not have bit 0x02 set (conflicts with typecheck_FAIL)"
+#endif
/* data structures for the type system ****************************************/
/* The typeinfo structure stores detailed information on address types.
* (stack elements, variables, etc. with type == TYPE_ADR.)
*
- * There are two kinds of address types which can are distinguished by
+ * There are two kinds of address types which can be distinguished by
* the value of the typeclass field:
*
* 1) typeclass == NULL: returnAddress type
*
* Note: For non-address types either there is no typeinfo allocated
* or the fields of the typeinfo struct contain undefined values!
+ * DO NOT access the typeinfo for non-address types!
*
* CAUTION: The typeinfo structure should be considered opaque outside of
* typeinfo.[ch]. Please use the macros and functions defined here to
*
* A) typeclass == NULL
*
- * 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 *)
+ * This is a returnAddress type.
*
* Use TYPEINFO_IS_PRIMITIVE to check for this.
* Use TYPEINFO_RETURNADDRESS to access the pointer in elementclass.
*
* B) typeclass == pseudo_class_Null
*
- * This is the null-reference type. Use TYPEINFO_IS_NULLTYPE to check for this.
+ * 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
*
- * This is a 'uninitialized object' type. elementclass can be
+ * This is an 'uninitialized object' type. elementclass can be
* cast to instruction* and points to the NEW instruction
* responsible for creating this type.
*
*
* D) typeclass == pseudo_class_Arraystub
*
- * See global.h for a describes of pseudo_class_Arraystub.
+ * This type is used to represent the result of merging array types
+ * with incompatible component types. An arraystub allows no access
+ * to its components (since their type is undefined), but it allows
+ * operations which act directly on an arbitrary array type (such as
+ * requesting the array size).
+ *
+ * NOTE: An array stub does *not* count as an array. It has dimension
+ * zero.
+ *
* Otherwise like a normal class reference type.
* Don't access other fields of the struct.
*
* elementtype....element type (ARRAYTYPE_...)
* merged.........mergedlist of the element type
*
- * F) typeclass is an interface
+ * Use TYPEINFO_IS_ARRAY to check for this case.
+ *
+ * The elementclass may be one of the following:
+ * 1) pseudo_class_Arraystub
+ * 2) an unresolved type
+ * 3) a loaded interface
+ * 4) a loaded (non-pseudo-,non-array-)class != (BOOTSTRAP)java.lang.Object
+ * Note: `merged` may be used
+ * 5) (BOOTSTRAP)java.lang.Object
+ * Note: `merged` may be used
+ *
+ * For the semantics of the merged field in cases 4) and 5) consult the
+ * corresponding descriptions with `elementclass` replaced by `typeclass`.
+ *
+ * F) typeclass is an unresolved type (a symbolic class/interface reference)
+ *
+ * The type has not been resolved yet. (Meaning it corresponds to an
+ * unloaded class or interface).
+ * Don't access other fields of the struct.
+ *
+ * G) typeclass is a loaded interface
*
* An interface reference type.
* Don't access other fields of the struct.
*
- * G) typeclass is a (non-pseudo-,non-array-)class != java.lang.Object
+ * H) typeclass is a loaded (non-pseudo-,non-array-)class != (BOOTSTRAP)java.lang.Object
*
- * A class reference type.
- * All classinfos in u.merged.list (if any) are
- * subclasses of typeclass (no interfaces or array classes).
+ * A loaded class type.
+ * All classref_or_classinfos in u.merged.list (if any) are
+ * loaded subclasses of typeclass (no interfaces, array classes, or
+ * unresolved types).
* Don't access other fields of the struct.
*
- * H) typeclass is java.lang.Object
+ * I) typeclass is (BOOTSTRAP)java.lang.Object
*
* 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) may be
- * classes, interfaces and pseudo classes.
+ * The classref_or_classinfos in u.merged.list (if any) may be
+ * classes, interfaces, pseudo classes or unresolved types.
* Don't access other fields of the struct.
*/
/* The following algorithm is used to determine if the type described
- * by this typeinfo struct supports the interface X:
+ * by this typeinfo struct supports the interface X: * XXX add MAYBE *
*
* 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".
* access typeinfo structures!
*/
struct typeinfo {
- classinfo *typeclass;
- classinfo *elementclass; /* valid if dimension>0 */ /* various uses! */
- typeinfo_mergedlist *merged;
- u1 dimension;
- u1 elementtype; /* valid if dimension>0 */
+ classref_or_classinfo typeclass;
+ classref_or_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;
+ classref_or_classinfo list[1]; /* variable length! */
};
-struct typeinfo_retaddr_set {
- typeinfo_retaddr_set *alt; /* next alternative in set */
- void *addr; /* return address */
-};
+/* a type descriptor stores a basic type and the typeinfo */
+/* this is used for storing the type of a local variable, and for */
+/* storing types in the signature of a method */
struct typedescriptor {
- typeinfo info; /* valid if type == TYPE_ADR */
+ typeinfo typeinfo; /* 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 */
/****************************************************************************/
/* typevectors **************************************************************/
#define TYPEVECTOR_SIZE(size) \
- ((sizeof(typevector) - sizeof(typedescriptor)) \
- + (size)*sizeof(typedescriptor))
+ ((size) * sizeof(varinfo))
#define DNEW_TYPEVECTOR(size) \
- ((typevector*)dump_alloc(TYPEVECTOR_SIZE(size)))
+ ((varinfo*)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)
+ ((varinfo*) (((u1*)(array)) + TYPEVECTOR_SIZE(size) * (index)))
/* internally used macros ***************************************************/
/* macros for type queries **************************************************/
#define TYPEINFO_IS_PRIMITIVE(info) \
- ((info).typeclass == NULL)
+ ((info).typeclass.any == NULL)
#define TYPEINFO_IS_REFERENCE(info) \
- ((info).typeclass != NULL)
+ ((info).typeclass.any != NULL)
#define TYPEINFO_IS_NULLTYPE(info) \
- ((info).typeclass == pseudo_class_Null)
+ ((info).typeclass.cls == pseudo_class_Null)
#define TYPEINFO_IS_NEWOBJECT(info) \
- ((info).typeclass == pseudo_class_New)
+ ((info).typeclass.cls == pseudo_class_New)
+
+#define TYPEINFO_IS_JAVA_LANG_CLASS(info) \
+ ((info).typeclass.cls == class_java_lang_Class)
/* only use this if TYPEINFO_IS_PRIMITIVE returned true! */
#define TYPEINFO_RETURNADDRESS(info) \
- ((void *)(info).elementclass)
+ ((info).elementclass.any)
/* only use this if TYPEINFO_IS_NEWOBJECT returned true! */
#define TYPEINFO_NEWOBJECT_INSTRUCTION(info) \
- ((void *)(info).elementclass)
+ ((info).elementclass.any)
+
+/* only use this if TYPEINFO_IS_JAVA_LANG_CLASS returned true! */
+#define TYPEINFO_JAVA_LANG_CLASS_CLASSREF(info) \
+ ((info).elementclass.ref)
/* macros for array type queries ********************************************/
#define TYPEINFO_IS_OBJECT_ARRAY(info) \
( TYPEINFO_IS_SIMPLE_ARRAY(info) \
- && ((info).elementclass != NULL) )
+ && ((info).elementclass.any != NULL) )
/* assumes that info describes an array type */
#define TYPEINFO_IS_ARRAY_OF_REFS_NOCHECK(info) \
- ( ((info).elementclass != NULL) \
+ ( ((info).elementclass.any != NULL) \
|| ((info).dimension >= 2) )
#define TYPEINFO_IS_ARRAY_OF_REFS(info) \
&& TYPEINFO_IS_ARRAY_OF_REFS_NOCHECK(info) )
#define TYPE_IS_RETURNADDRESS(type,info) \
- ( ((type)==TYPE_ADDRESS) \
+ ( ((type)==TYPE_RET) \
&& TYPEINFO_IS_PRIMITIVE(info) )
#define TYPE_IS_REFERENCE(type,info) \
- ( ((type)==TYPE_ADDRESS) \
+ ( ((type)==TYPE_ADR) \
&& !TYPEINFO_IS_PRIMITIVE(info) )
#define TYPEDESC_IS_RETURNADDRESS(td) \
- TYPE_IS_RETURNADDRESS((td).type,(td).info)
+ TYPE_IS_RETURNADDRESS((td).type,(td).typeinfo)
#define TYPEDESC_IS_REFERENCE(td) \
- TYPE_IS_REFERENCE((td).type,(td).info)
+ TYPE_IS_REFERENCE((td).type,(td).typeinfo)
/* queries allowing the null type ********************************************/
/* macros for initializing typeinfo structures ******************************/
#define TYPEINFO_INIT_PRIMITIVE(info) \
- do {(info).typeclass = NULL; \
- (info).elementclass = NULL; \
+ do {(info).typeclass.any = NULL; \
+ (info).elementclass.any = NULL; \
(info).merged = NULL; \
(info).dimension = 0; \
(info).elementtype = 0;} while(0)
#define TYPEINFO_INIT_RETURNADDRESS(info,adr) \
- do {(info).typeclass = NULL; \
- (info).elementclass = (classinfo*) (adr); \
+ do {(info).typeclass.any = NULL; \
+ (info).elementclass.any = (adr); \
(info).merged = NULL; \
(info).dimension = 0; \
(info).elementtype = 0;} while(0)
#define TYPEINFO_INIT_NON_ARRAY_CLASSINFO(info,cinfo) \
- do {(info).typeclass = (cinfo); \
- (info).elementclass = NULL; \
+ do {(info).typeclass.cls = (cinfo); \
+ (info).elementclass.any = NULL; \
(info).merged = NULL; \
(info).dimension = 0; \
(info).elementtype = 0;} while(0)
+#define TYPEINFO_INIT_JAVA_LANG_CLASS(info,c) \
+ do {(info).typeclass.any = class_java_lang_Class; \
+ (info).elementclass = (c); \
+ (info).merged = NULL; \
+ (info).dimension = 0; \
+ (info).elementtype = 0;} while(0)
+
#define TYPEINFO_INIT_NULLTYPE(info) \
- TYPEINFO_INIT_CLASSINFO(info,pseudo_class_Null)
+ TYPEINFO_INIT_NON_ARRAY_CLASSINFO(info,pseudo_class_Null)
#define TYPEINFO_INIT_NEWOBJECT(info,instr) \
- do {(info).typeclass = pseudo_class_New; \
- (info).elementclass = (classinfo*) (instr);\
+ do {(info).typeclass.cls = pseudo_class_New; \
+ (info).elementclass.any = (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) \
- 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; \
- } \
- else { \
- (info).elementclass = NULL; \
- (info).dimension = 0; \
- (info).elementtype = 0; \
- } \
- (info).merged = NULL;} while(0)
-
-#define TYPEINFO_INIT_FROM_FIELDINFO(info,fi) \
- typeinfo_init_from_descriptor(&(info), \
- (fi)->descriptor->text,utf_end((fi)->descriptor));
+ typeinfo_init_classinfo(&(info),primitivetype_table[arraytype].arrayclass);
/* macros for copying types (destinition is not checked or freed) ***********/
/* 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);
+bool typevector_checktype(varinfo *set,int index,int type);
+bool typevector_checkreference(varinfo *set,int index);
+bool typevector_checkretaddr(varinfo *set,int index);
/* 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);
+void typevector_store(varinfo *set,int index,int type,typeinfo *info);
+void typevector_store_retaddr(varinfo *set,int index,typeinfo *info);
+bool typevector_init_object(varinfo *set,void *ins,classref_or_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);
+varinfo *typevector_copy(varinfo *src,int size);
+void typevector_copy_inplace(varinfo *src,varinfo *dst,int size);
+typecheck_result typevector_merge(methodinfo *m,varinfo *dst,varinfo *y,int size);
/* inquiry functions (read-only) ********************************************/
bool typeinfo_is_primitive_array(typeinfo *info,int arraytype);
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);
+typecheck_result typeinfo_is_assignable(typeinfo *value,typeinfo *dest);
+typecheck_result typeinfo_is_assignable_to_class(typeinfo *value,classref_or_classinfo dest);
/* initialization functions *************************************************/
-void typeinfo_init_from_descriptor(typeinfo *info,char *utf_ptr,char *end_ptr);
-void typeinfo_init_component(typeinfo *srcarray,typeinfo *dst);
-
-int typeinfo_count_method_args(utf *d,bool twoword); /* this not included */
-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);
+/* RETURN VALUE (bool):
+ * true.............ok,
+ * false............an exception has been thrown.
+ *
+ * RETURN VALUE (int):
+ * >= 0.............ok,
+ * -1...............an exception has been thrown.
+ */
+void typeinfo_init_classinfo(typeinfo *info,classinfo *c);
+bool typeinfo_init_class(typeinfo *info,classref_or_classinfo c);
+bool typeinfo_init_component(typeinfo *srcarray,typeinfo *dst);
+
+bool typeinfo_init_from_typedesc(typedesc *desc,u1 *type,typeinfo *info);
+bool typeinfos_init_from_methoddesc(methoddesc *desc,u1 *typebuf,
+ typeinfo *infobuf,
+ int buflen,bool twoword,
+ u1 *returntype,typeinfo *returntypeinfo);
+bool typedescriptor_init_from_typedesc(typedescriptor *td,
+ typedesc *desc);
+bool typeinfo_init_varinfo_from_typedesc(varinfo *var,
+ typedesc *desc);
+int typedescriptors_init_from_methoddesc(typedescriptor *td,
+ methoddesc *desc,
+ int buflen,bool twoword,int startindex,
+ typedescriptor *returntype);
+bool typeinfo_init_varinfos_from_methoddesc(varinfo *vars,
+ methoddesc *desc,
+ int buflen, int startindex,
+ s4 *map,
+ typedescriptor *returntype);
void typeinfo_clone(typeinfo *src,typeinfo *dest);
-/* functions for the type system ********************************************/
+/* freeing memory ***********************************************************/
void typeinfo_free(typeinfo *info);
-bool typeinfo_merge(typeinfo *dest,typeinfo* y);
+/* functions for merging types **********************************************/
+
+typecheck_result typeinfo_merge(methodinfo *m,typeinfo *dest,typeinfo* y);
/* debugging helpers ********************************************************/
#include <stdio.h>
void typeinfo_test();
-void typeinfo_init_from_fielddescriptor(typeinfo *info,char *desc);
+void typeinfo_print_class(FILE *file,classref_or_classinfo c);
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);
+void typevector_print(FILE *file,varinfo *vec,int size);
#endif /* TYPEINFO_DEBUG */