Authors: Edwin Steiner
- $Id: typeinfo.h 719 2003-12-08 14:26:05Z edwin $
+ $Id: typeinfo.h 1621 2004-11-30 13:06:55Z 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
*
* 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 interface
+ * E) typeclass is an array class
*
- * XXX
+ * 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
*
- * F) typeclass is a (non-pseudo-)class != java.lang.Object
+ * F) typeclass is an interface
*
- * XXX
+ * An interface reference type.
+ * Don't access other fields of the struct.
+ *
+ * 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
*
* 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".
* 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 */
/****************************************************************************/
-/* 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_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)
( TYPEINFO_IS_ARRAY(info) \
&& TYPEINFO_IS_ARRAY_OF_REFS_NOCHECK(info) )
+#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) \
(info).dimension = 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) \
do {(info).typeclass = (cinfo); \
(info).elementclass = NULL; \
typeinfo_init_from_descriptor(&(info), \
(fi)->descriptor->text,utf_end((fi)->descriptor));
-/* macros for writing types (destination must have been initialized) ********/
-/* XXX delete them? */
-#if 0
-
-#define TYPEINFO_PUT_NULLTYPE(info) \
- do {(info).typeclass = pseudo_class_Null;} while(0)
-
-#define TYPEINFO_PUT_NON_ARRAY_CLASSINFO(info,cinfo) \
- do {(info).typeclass = (cinfo);} while(0)
-
-#define TYPEINFO_PUT_CLASSINFO(info,cls) \
- do {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; \
- }} while(0)
-
-/* srcarray must be an array (not checked) */
-#define TYPEINFO_PUT_COMPONENT(srcarray,dst) \
- do {typeinfo_put_component(&(srcarray),&(dst));} while(0)
-
-#endif
-
/* macros for copying types (destinition is not checked or freed) ***********/
/* TYPEINFO_COPY makes a shallow copy, the merged pointer is simply copied. */
/* 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);
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 *************************************************/
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);
#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 */