|
|
@@ -21,12 +21,46 @@
|
|
|
#include <mono/metadata/metadata.h>
|
|
|
#include <mono/metadata/tabledefs.h>
|
|
|
#include <mono/metadata/tokentype.h>
|
|
|
+#include <mono/cli/cli.h>
|
|
|
#include <mono/cli/class.h>
|
|
|
#include <mono/cli/types.h>
|
|
|
#include <mono/cli/object.h>
|
|
|
|
|
|
#define CSIZE(x) (sizeof (x) / 4)
|
|
|
|
|
|
+static void
|
|
|
+typedef_from_typeref (MonoImage *image, guint32 type_token, MonoImage **rimage, guint32 *index)
|
|
|
+{
|
|
|
+ guint32 cols[MONO_TYPEDEF_SIZE];
|
|
|
+ MonoMetadata *m = &image->metadata;
|
|
|
+ MonoTableInfo *t = &m->tables[MONO_TABLE_TYPEREF];
|
|
|
+ guint32 idx, i;
|
|
|
+ const char *name, *nspace;
|
|
|
+
|
|
|
+ mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, 3);
|
|
|
+ g_assert ((cols [0] & 0x3) == 2);
|
|
|
+ idx = cols [0] >> 2;
|
|
|
+ name = mono_metadata_string_heap (m, cols [1]);
|
|
|
+ nspace = mono_metadata_string_heap (m, cols [2]);
|
|
|
+ /* load referenced assembly */
|
|
|
+ image = image->references [idx-1]->image;
|
|
|
+ m = &image->metadata;
|
|
|
+ t = &m->tables [MONO_TABLE_TYPEDEF];
|
|
|
+ /* dumb search for now */
|
|
|
+ for (i=0; i < t->rows; ++i) {
|
|
|
+ mono_metadata_decode_row (t, i, cols, MONO_TYPEDEF_SIZE);
|
|
|
+
|
|
|
+ if (!strcmp (name, mono_metadata_string_heap (m, cols [1])) &&
|
|
|
+ !strcmp (nspace, mono_metadata_string_heap (m, cols [2]))) {
|
|
|
+ *rimage = image;
|
|
|
+ *index = MONO_TOKEN_TYPE_DEF | (i + 1);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ g_assert_not_reached ();
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* class_compute_field_layout:
|
|
|
* @m: pointer to the metadata.
|
|
|
@@ -116,7 +150,7 @@ class_compute_field_layout (MonoMetadata *m, MonoClass *class)
|
|
|
|
|
|
/**
|
|
|
* @image: context where the image is created
|
|
|
- * @tidx: index of the type to create
|
|
|
+ * @type_token: typedef token
|
|
|
*/
|
|
|
static MonoClass *
|
|
|
mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
|
|
|
@@ -126,37 +160,34 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
|
|
|
MonoClass stack_class;
|
|
|
MonoClass *class = &stack_class;
|
|
|
guint32 cols [MONO_TYPEDEF_SIZE], parent_token;
|
|
|
- guint tidx = type_token & 0xffffff;
|
|
|
+ guint tidx = mono_metadata_token_index (type_token);
|
|
|
const char *name, *nspace;
|
|
|
|
|
|
+ g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
|
|
|
+
|
|
|
memset (class, 0, sizeof (MonoClass));
|
|
|
|
|
|
mono_metadata_decode_row (tt, tidx-1, cols, CSIZE (cols));
|
|
|
name = mono_metadata_string_heap (m, cols[1]);
|
|
|
nspace = mono_metadata_string_heap (m, cols[2]);
|
|
|
/*g_print ("Init class %s\n", name);*/
|
|
|
-
|
|
|
- /*
|
|
|
- * If root of the hierarchy
|
|
|
- */
|
|
|
- if (!strcmp (name, "Object") && !strcmp (nspace, "System")) {
|
|
|
+
|
|
|
+ /* if root of the hierarchy */
|
|
|
+ if (!strcmp (nspace, "System") && !strcmp (name, "Object")) {
|
|
|
class->instance_size = sizeof (MonoObject);
|
|
|
class->parent = NULL;
|
|
|
} else {
|
|
|
parent_token = mono_metadata_token_from_dor (cols [3]);
|
|
|
class->parent = mono_class_get (image, parent_token);
|
|
|
class->instance_size = class->parent->instance_size;
|
|
|
+ class->valuetype = class->parent->valuetype;
|
|
|
}
|
|
|
+ if (!strcmp (nspace, "System") && !strcmp (name, "ValueType"))
|
|
|
+ class->valuetype = 1;
|
|
|
|
|
|
- /* reserve space to store vector pointer in arrays */
|
|
|
- if (!strcmp (name, "Object") && !strcmp (nspace, "Array")) {
|
|
|
- class->instance_size += sizeof (gpointer);
|
|
|
- g_assert (class->instance_size != sizeof (MonoArrayObject));
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
+ g_assert (class->instance_size);
|
|
|
class->image = image;
|
|
|
- class->type_token = tidx;
|
|
|
+ class->type_token = type_token;
|
|
|
class->flags = cols [0];
|
|
|
class->class_size = sizeof (MonoClass);
|
|
|
|
|
|
@@ -196,11 +227,171 @@ mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
|
|
|
class_compute_field_layout (m, class);
|
|
|
}
|
|
|
|
|
|
+ /* reserve space to store vector pointer in arrays */
|
|
|
+ if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
|
|
|
+ class->instance_size += 2 * sizeof (gpointer);
|
|
|
+ g_assert (class->field.count == 0);
|
|
|
+ g_assert (class->instance_size == sizeof (MonoArrayObject));
|
|
|
+ }
|
|
|
+
|
|
|
class = g_malloc0 (class->class_size);
|
|
|
*class = stack_class;
|
|
|
return class;
|
|
|
}
|
|
|
|
|
|
+static guint32
|
|
|
+mono_type_to_tydedef (MonoImage *image, MonoType *type, MonoImage **rimage)
|
|
|
+{
|
|
|
+ MonoImage *corlib, *res;
|
|
|
+ guint32 etype;
|
|
|
+
|
|
|
+ res = corlib = mono_get_corlib ();
|
|
|
+
|
|
|
+ switch (type->type) {
|
|
|
+ case MONO_TYPE_BOOLEAN:
|
|
|
+ etype = mono_typedef_from_name (corlib, "Boolean", "System", NULL);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_CHAR:
|
|
|
+ etype = mono_typedef_from_name (corlib, "Char", "System", NULL);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_I1:
|
|
|
+ etype = mono_typedef_from_name (corlib, "Byte", "System", NULL);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_I2:
|
|
|
+ etype = mono_typedef_from_name (corlib, "Int16", "System", NULL);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_U2:
|
|
|
+ etype = mono_typedef_from_name (corlib, "UInt16", "System", NULL);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_I4:
|
|
|
+ etype = mono_typedef_from_name (corlib, "Int32", "System", NULL);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_U4:
|
|
|
+ etype = mono_typedef_from_name (corlib, "UInt32", "System", NULL);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_I8:
|
|
|
+ etype = mono_typedef_from_name (corlib, "Int64", "System", NULL);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_U8:
|
|
|
+ etype = mono_typedef_from_name (corlib, "UInt64", "System", NULL);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_R8:
|
|
|
+ etype = mono_typedef_from_name (corlib, "Double", "System", NULL);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_STRING:
|
|
|
+ etype = mono_typedef_from_name (corlib, "String", "System", NULL);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_CLASS:
|
|
|
+ etype = type->data.token;
|
|
|
+ res = image;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ g_warning ("implement me %08x\n", type->type);
|
|
|
+ g_assert_not_reached ();
|
|
|
+ }
|
|
|
+
|
|
|
+ *rimage = res;
|
|
|
+ return etype;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * @image: context where the image is created
|
|
|
+ * @type_spec: typespec token
|
|
|
+ * @at: an optional pointer to return the array type
|
|
|
+ */
|
|
|
+static MonoClass *
|
|
|
+mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
|
|
|
+{
|
|
|
+ MonoMetadata *m = &image->metadata;
|
|
|
+ guint32 idx = mono_metadata_token_index (type_spec);
|
|
|
+ MonoTableInfo *t;
|
|
|
+ guint32 cols [MONO_TYPESPEC_SIZE];
|
|
|
+ const char *ptr;
|
|
|
+ guint32 len, etype;
|
|
|
+ MonoType *type;
|
|
|
+ MonoClass *class;
|
|
|
+ MonoImage *rimage;
|
|
|
+
|
|
|
+ t = &m->tables [MONO_TABLE_TYPESPEC];
|
|
|
+
|
|
|
+ mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
|
|
|
+ ptr = mono_metadata_blob_heap (m, cols [MONO_TYPESPEC_SIGNATURE]);
|
|
|
+ len = mono_metadata_decode_value (ptr, &ptr);
|
|
|
+ type = mono_metadata_parse_type (m, ptr, &ptr);
|
|
|
+
|
|
|
+ switch (type->type) {
|
|
|
+ case MONO_TYPE_ARRAY:
|
|
|
+ etype = mono_type_to_tydedef (image, type->data.array->type, &rimage);
|
|
|
+ class = mono_array_class_get (rimage, etype, type->data.array->rank);
|
|
|
+ break;
|
|
|
+ case MONO_TYPE_SZARRAY:
|
|
|
+ g_assert (!type->custom_mod);
|
|
|
+ etype = mono_type_to_tydedef (image, type->data.type, &rimage);
|
|
|
+ class = mono_array_class_get (rimage, etype, 1);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ g_assert_not_reached ();
|
|
|
+ }
|
|
|
+
|
|
|
+ mono_metadata_free_type (type);
|
|
|
+
|
|
|
+ return class;
|
|
|
+}
|
|
|
+
|
|
|
+MonoClass *
|
|
|
+mono_array_class_get (MonoImage *image, guint32 etype, guint32 rank)
|
|
|
+{
|
|
|
+ MonoClass *class, *eclass;
|
|
|
+ static MonoClass *parent = NULL;
|
|
|
+ MonoArrayClass *aclass;
|
|
|
+ guint32 esize, key;
|
|
|
+
|
|
|
+ g_assert (rank <= 255);
|
|
|
+
|
|
|
+ if (!parent) {
|
|
|
+ guint32 arr_token;
|
|
|
+ MonoImage *corlib;
|
|
|
+
|
|
|
+ mono_get_array_class_info (&arr_token, &corlib);
|
|
|
+ parent = mono_class_get (corlib, arr_token);
|
|
|
+ g_assert (parent != NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ eclass = mono_class_get (image, etype);
|
|
|
+ g_assert (eclass != NULL);
|
|
|
+
|
|
|
+ image = eclass->image;
|
|
|
+
|
|
|
+ esize = eclass->instance_size;
|
|
|
+
|
|
|
+ g_assert (!eclass->type_token ||
|
|
|
+ mono_metadata_token_table (eclass->type_token) == MONO_TABLE_TYPEDEF);
|
|
|
+
|
|
|
+ key = ((rank & 0xff) << 24) | (eclass->type_token & 0xffffff);
|
|
|
+ if ((class = g_hash_table_lookup (image->array_cache, GUINT_TO_POINTER (key))))
|
|
|
+ return class;
|
|
|
+
|
|
|
+ if (eclass->valuetype)
|
|
|
+ esize -= sizeof (MonoObject);
|
|
|
+
|
|
|
+ aclass = g_new0 (MonoArrayClass, 1);
|
|
|
+ class = (MonoClass *)aclass;
|
|
|
+
|
|
|
+ class->image = image;
|
|
|
+ class->type_token = 0;
|
|
|
+ class->flags = TYPE_ATTRIBUTE_CLASS;
|
|
|
+ class->parent = parent;
|
|
|
+ class->instance_size = class->parent->instance_size;
|
|
|
+ class->class_size = sizeof (MonoArrayClass);
|
|
|
+
|
|
|
+ aclass->rank = rank;
|
|
|
+ aclass->etype_token = eclass->type_token;
|
|
|
+ aclass->esize = esize;
|
|
|
+
|
|
|
+ g_hash_table_insert (image->array_cache, GUINT_TO_POINTER (key), class);
|
|
|
+ return class;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* Auxiliary routine to mono_class_get_field
|
|
|
*
|
|
|
@@ -243,43 +434,11 @@ mono_class_get_field (MonoClass *class, guint32 field_token)
|
|
|
return mono_class_get_field_idx (class, idx - 1);
|
|
|
}
|
|
|
|
|
|
-void
|
|
|
-typedef_from_typeref (MonoImage *image, guint32 type_token, MonoImage **rimage, guint32 *index)
|
|
|
-{
|
|
|
- guint32 cols[MONO_TYPEDEF_SIZE];
|
|
|
- MonoMetadata *m = &image->metadata;
|
|
|
- MonoTableInfo *t = &m->tables[MONO_TABLE_TYPEREF];
|
|
|
- guint32 idx, i;
|
|
|
- const char *name, *nspace;
|
|
|
-
|
|
|
- mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, 3);
|
|
|
- g_assert ((cols [0] & 0x3) == 2);
|
|
|
- idx = cols [0] >> 2;
|
|
|
- name = mono_metadata_string_heap (m, cols [1]);
|
|
|
- nspace = mono_metadata_string_heap (m, cols [2]);
|
|
|
- /* load referenced assembly */
|
|
|
- image = image->references [idx-1]->image;
|
|
|
- m = &image->metadata;
|
|
|
- t = &m->tables [MONO_TABLE_TYPEDEF];
|
|
|
- /* dumb search for now */
|
|
|
- for (i=0; i < t->rows; ++i) {
|
|
|
- mono_metadata_decode_row (t, i, cols, MONO_TYPEDEF_SIZE);
|
|
|
-
|
|
|
- if (!strcmp (name, mono_metadata_string_heap (m, cols [1])) &&
|
|
|
- !strcmp (nspace, mono_metadata_string_heap (m, cols [2]))) {
|
|
|
- *rimage = image;
|
|
|
- *index = i + 1;
|
|
|
- return;
|
|
|
- }
|
|
|
- }
|
|
|
- g_assert_not_reached ();
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
/**
|
|
|
* mono_class_get:
|
|
|
* @image: the image where the class resides
|
|
|
* @type_token: the token for the class
|
|
|
+ * @at: an optional pointer to return the array element type
|
|
|
*
|
|
|
* Returns: the MonoClass that represents @type_token in @image
|
|
|
*/
|
|
|
@@ -288,23 +447,26 @@ mono_class_get (MonoImage *image, guint32 type_token)
|
|
|
{
|
|
|
MonoClass *class;
|
|
|
|
|
|
- if ((type_token & 0xff000000) == MONO_TOKEN_TYPE_DEF
|
|
|
- && (class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
|
|
|
- return class;
|
|
|
-
|
|
|
switch (type_token & 0xff000000){
|
|
|
case MONO_TOKEN_TYPE_DEF:
|
|
|
+ if ((class = g_hash_table_lookup (image->class_cache,
|
|
|
+ GUINT_TO_POINTER (type_token))))
|
|
|
+ return class;
|
|
|
+
|
|
|
class = mono_class_create_from_typedef (image, type_token);
|
|
|
break;
|
|
|
|
|
|
case MONO_TOKEN_TYPE_REF: {
|
|
|
typedef_from_typeref (image, type_token, &image, &type_token);
|
|
|
- class = mono_class_create_from_typedef (image, type_token);
|
|
|
- break;
|
|
|
+ return mono_class_get (image, type_token);
|
|
|
}
|
|
|
case MONO_TOKEN_TYPE_SPEC:
|
|
|
- g_error ("Can not handle class creation of TypeSpecs yet");
|
|
|
-
|
|
|
+ if ((class = g_hash_table_lookup (image->class_cache,
|
|
|
+ GUINT_TO_POINTER (type_token))))
|
|
|
+ return class;
|
|
|
+
|
|
|
+ class = mono_class_create_from_typespec (image, type_token);
|
|
|
+ break;
|
|
|
default:
|
|
|
g_assert_not_reached ();
|
|
|
}
|