#include <mono/metadata/metadata.h>
#include <mono/metadata/tabledefs.h>
#include <mono/metadata/tokentype.h>
-#include <mono/cli/class.h>
-#include <mono/cli/types.h>
-#include <mono/cli/object.h>
+#include <mono/metadata/class.h>
+#include <mono/metadata/object.h>
#define CSIZE(x) (sizeof (x) / 4)
-/*
- * mono_field_type_size:
- * @t: the type to return the size of
- *
- * Returns: the number of bytes required to hold an instance of this
- * type in memory
- */
-int
-mono_field_type_size (MonoFieldType *ft)
+static MonoClass *
+mono_class_create_from_typeref (MonoImage *image, guint32 type_token)
{
- MonoType *t = ft->type;
+ guint32 cols [MONO_TYPEREF_SIZE];
+ MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
+ guint32 idx;
+ const char *name, *nspace;
+ MonoClass *res;
- switch (t->type){
- case ELEMENT_TYPE_BOOLEAN:
- return sizeof (m_boolean);
-
- case ELEMENT_TYPE_CHAR:
- return sizeof (m_char);
-
- case ELEMENT_TYPE_I1:
- case ELEMENT_TYPE_U1:
- return 1;
-
- case ELEMENT_TYPE_I2:
- case ELEMENT_TYPE_U2:
- return 2;
-
- case ELEMENT_TYPE_I4:
- case ELEMENT_TYPE_U4:
- case ELEMENT_TYPE_R4:
- return 4;
-
- case ELEMENT_TYPE_I8:
- case ELEMENT_TYPE_U8:
- case ELEMENT_TYPE_R8:
- return 8;
-
- case ELEMENT_TYPE_I:
- return sizeof (m_i);
-
- case ELEMENT_TYPE_U:
- return sizeof (m_u);
-
- case ELEMENT_TYPE_STRING:
- return sizeof (m_string);
-
- case ELEMENT_TYPE_OBJECT:
- return sizeof (m_object);
-
- case ELEMENT_TYPE_VALUETYPE:
- g_error ("FIXME: Add computation of size for ELEMENT_TYPE_VALUETYPE");
-
- case ELEMENT_TYPE_CLASS:
- g_error ("FIXME: Add computation of size for ELEMENT_TYPE_CLASS");
- break;
-
- case ELEMENT_TYPE_SZARRAY:
- g_error ("FIXME: Add computation of size for ELEMENT_TYPE_SZARRAY");
- break;
-
- case ELEMENT_TYPE_PTR:
- g_error ("FIXME: Add computation of size for ELEMENT_TYPE_PTR");
- break;
-
- case ELEMENT_TYPE_FNPTR:
- g_error ("FIXME: Add computation of size for ELEMENT_TYPE_FNPTR");
- break;
-
- case ELEMENT_TYPE_ARRAY:
- g_error ("FIXME: Add computation of size for ELEMENT_TYPE_ARRAY");
- break;
- default:
- g_error ("type 0x%02x unknown", t->type);
- }
- return 0;
+ mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
+ g_assert ((cols [MONO_TYPEREF_SCOPE] & 0x3) == 2);
+ idx = cols [MONO_TYPEREF_SCOPE] >> 2;
+
+ if (!image->references || !image->references [idx-1]) {
+ /*
+ * detected a reference to mscorlib, we simply return a reference to a dummy
+ * until we have a better solution.
+ */
+ res = mono_class_from_name (image, "System", "MonoDummy");
+ /* prevent method loading */
+ res->dummy = 1;
+ /* some storage if the type is used - very ugly hack */
+ res->instance_size = 2*sizeof (gpointer);
+ return res;
+ }
+
+ name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
+ nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
+
+ /* load referenced assembly */
+ image = image->references [idx-1]->image;
+
+ return mono_class_from_name (image, nspace, name);
}
/**
* a good job at it. This is temporary to get the code for Paolo.
*/
static void
-class_compute_field_layout (metadata_t *m, MonoClass *class)
+class_compute_field_layout (MonoClass *class)
{
+ MonoImage *m = class->image;
const int top = class->field.count;
guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
- metadata_tableinfo_t *t = &m->tables [META_TABLE_FIELD];
- int i;
-
+ MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
+ int i, j;
+
/*
* Fetch all the field information.
*/
mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
sig = mono_metadata_blob_heap (m, cols [2]);
mono_metadata_decode_value (sig, &sig);
-
/* FIELD signature == 0x06 */
g_assert (*sig == 0x06);
-
class->fields [i].type = mono_metadata_parse_field_type (
- m, sig, &sig);
- class->fields [i].flags = cols [0];
+ m, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
}
-
/*
* Compute field layout and total size.
*/
case TYPE_ATTRIBUTE_AUTO_LAYOUT:
case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
for (i = 0; i < top; i++){
- int size;
+ int size, align;
- size = mono_field_type_size (class->fields [i].type);
- size += (size % 4);
- if (class->fields [i].flags & FIELD_ATTRIBUTE_STATIC) {
+ size = mono_type_size (class->fields [i].type, &align);
+ if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) {
class->fields [i].offset = class->class_size;
+ class->class_size += (class->class_size % align);
class->class_size += size;
} else {
class->fields [i].offset = class->instance_size;
+ class->instance_size += (class->instance_size % align);
class->instance_size += size;
}
}
break;
case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
- g_error ("TODO: Explicit layout not supported yet");
+ for (i = 0; i < top; i++){
+ guint32 cols [2];
+ int size, align;
+ int idx = class->field.first + i;
+
+ t = &m->tables [MONO_TABLE_FIELDLAYOUT];
+
+ for (j = 0; j < t->rows; j++) {
+
+ mono_metadata_decode_row (t, j, cols, CSIZE (cols));
+ if (cols [1] == idx) {
+ g_warning ("TODO: Explicit layout not supported yet");
+ }
+ }
+
+ size = mono_type_size (class->fields [i].type, &align);
+ if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) {
+ class->fields [i].offset = class->class_size;
+ class->class_size += (class->class_size % align);
+ class->class_size += size;
+ } else {
+ class->fields [i].offset = class->instance_size;
+ class->instance_size += (class->instance_size % align);
+ class->instance_size += size;
+ }
+ }
+ break;
+ }
+}
+
+void
+mono_class_metadata_init (MonoClass *class)
+{
+ int i;
+
+ if (class->metadata_inited)
+ return;
+
+ if (class->parent) {
+ if (!class->parent->metadata_inited)
+ mono_class_metadata_init (class->parent);
+ class->instance_size = class->parent->instance_size;
+ class->class_size = class->parent->class_size;
+ }
+
+ class->metadata_inited = 1;
+
+ /*
+ * Computes the size used by the fields, and their locations
+ */
+ if (class->field.count > 0){
+ class->fields = g_new (MonoClassField, class->field.count);
+ class_compute_field_layout (class);
}
+
+ if (!class->method.count)
+ return;
+
+ class->methods = g_new (MonoMethod*, class->method.count);
+ for (i = class->method.first; i < class->method.last; ++i)
+ class->methods [i - class->method.first] =
+ mono_get_method (class->image,
+ MONO_TOKEN_METHOD_DEF | (i + 1),
+ 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)
{
- metadata_t *m = &image->metadata;
- metadata_tableinfo_t *tt = &m->tables [META_TABLE_TYPEDEF];
- MonoClass stack_class;
- MonoClass *class = &stack_class;
- guint32 cols [6], parent_token;
- guint tidx = type_token & 0xffffff;
- const char *name;
-
+ MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
+ MonoClass *class;
+ guint32 cols [MONO_TYPEDEF_SIZE], parent_token;
+ guint tidx = mono_metadata_token_index (type_token);
+ const char *name, *nspace;
+
+ g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
+
+ class = g_malloc0 (sizeof (MonoClass));
+
+ class->this_arg.byref = 1;
+ class->this_arg.data.klass = class;
+ class->this_arg.type = MONO_TYPE_CLASS;
+
mono_metadata_decode_row (tt, tidx-1, cols, CSIZE (cols));
- name = mono_metadata_string_heap (m, cols[1]);
+ class->name = name = mono_metadata_string_heap (image, cols[1]);
+ class->name_space = nspace = mono_metadata_string_heap (image, cols[2]);
+
+ class->image = image;
+ class->type_token = type_token;
+ class->flags = cols [0];
+
/*g_print ("Init class %s\n", name);*/
- /*
- * If root of the hierarchy
- */
- if (cols [3] == 0){
- class->instance_size = sizeof (MonoObject);
+ /* if root of the hierarchy */
+ if (!strcmp (nspace, "System") && !strcmp (name, "Object")) {
class->parent = NULL;
- } else {
+ class->instance_size = sizeof (MonoObject);
+ } else if (!(cols [0] & TYPE_ATTRIBUTE_INTERFACE)) {
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;
+ class->enumtype = class->parent->enumtype;
}
-
- class->image = image;
- class->type_token = tidx;
- class->flags = cols [0];
- class->class_size = sizeof (MonoClass);
+
+ if (!strcmp (nspace, "System")) {
+ if (!strcmp (name, "ValueType")) {
+ class->valuetype = 1;
+ } else if (!strcmp (name, "Enum")) {
+ class->valuetype = 1;
+ class->enumtype = 1;
+ }
+ }
+ if (class->valuetype)
+ class->this_arg.type = MONO_TYPE_VALUETYPE;
/*
* Compute the field and method lists
*/
- class->field.first = cols [4] - 1;
- class->method.first = cols [5] - 1;
+ class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
+ class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
- if (tt->rows > tidx + 1){
- guint32 cols_next [6];
+ if (tt->rows > tidx){
+ guint32 cols_next [MONO_TYPEDEF_SIZE];
- mono_metadata_decode_row (tt, tidx + 1, cols_next, CSIZE (cols_next));
- class->field.last = cols_next [4] - 1;
- class->method.last = cols_next [5] - 1;
+ mono_metadata_decode_row (tt, tidx, cols_next, CSIZE (cols_next));
+ class->field.last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
+ class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
} else {
- class->field.last = m->tables [META_TABLE_FIELD].rows;
- class->method.last = m->tables [META_TABLE_METHOD].rows;
+ class->field.last = image->tables [MONO_TABLE_FIELD].rows;
+ class->method.last = image->tables [MONO_TABLE_METHOD].rows;
}
- if (cols [4] && cols [4] <= m->tables [META_TABLE_FIELD].rows)
+ if (cols [MONO_TYPEDEF_FIELD_LIST] &&
+ cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
class->field.count = class->field.last - class->field.first;
else
class->field.count = 0;
- if (cols [5] <= m->tables [META_TABLE_METHOD].rows)
+ if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
class->method.count = class->method.last - class->method.first;
else
class->method.count = 0;
- /*
- * Computes the size used by the fields, and their locations
- */
- if (class->field.count > 0){
- class->fields = g_new (MonoClassField, class->field.count);
- 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);
+ }
+
+ class->interfaces = mono_metadata_interfaces_from_typedef (image, type_token);
+ return class;
+}
+
+MonoClass *
+mono_class_from_mono_type (MonoType *type)
+{
+ switch (type->type) {
+ case MONO_TYPE_OBJECT:
+ return mono_defaults.object_class;
+ case MONO_TYPE_VOID:
+ return mono_defaults.void_class;
+ case MONO_TYPE_BOOLEAN:
+ return mono_defaults.boolean_class;
+ case MONO_TYPE_CHAR:
+ return mono_defaults.char_class;
+ case MONO_TYPE_I1:
+ return mono_defaults.byte_class;
+ case MONO_TYPE_U1:
+ return mono_defaults.sbyte_class;
+ case MONO_TYPE_I2:
+ return mono_defaults.int16_class;
+ case MONO_TYPE_U2:
+ return mono_defaults.uint16_class;
+ case MONO_TYPE_I4:
+ return mono_defaults.int32_class;
+ case MONO_TYPE_U4:
+ return mono_defaults.uint32_class;
+ case MONO_TYPE_I:
+ return mono_defaults.int_class;
+ case MONO_TYPE_U:
+ return mono_defaults.uint_class;
+ case MONO_TYPE_I8:
+ return mono_defaults.int64_class;
+ case MONO_TYPE_U8:
+ return mono_defaults.uint64_class;
+ case MONO_TYPE_R4:
+ return mono_defaults.single_class;
+ case MONO_TYPE_R8:
+ return mono_defaults.double_class;
+ case MONO_TYPE_STRING:
+ return mono_defaults.string_class;
+ case MONO_TYPE_ARRAY:
+ return mono_defaults.array_class;
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_PTR:
+ /* Not really sure about these. */
+ return mono_class_from_mono_type (type->data.type);
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_VALUETYPE:
+ return type->data.klass;
+ default:
+ g_warning ("implement me %02x\n", type->type);
+ g_assert_not_reached ();
+ }
+
+ return NULL;
+}
+
+/**
+ * @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)
+{
+ guint32 idx = mono_metadata_token_index (type_spec);
+ MonoTableInfo *t;
+ guint32 cols [MONO_TYPESPEC_SIZE];
+ const char *ptr;
+ guint32 len;
+ MonoType *type;
+ MonoClass *class, *eclass;
+
+ t = &image->tables [MONO_TABLE_TYPESPEC];
+
+ mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
+ ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
+ len = mono_metadata_decode_value (ptr, &ptr);
+ type = mono_metadata_parse_type (image, MONO_PARSE_TYPE, 0, ptr, &ptr);
+
+ switch (type->type) {
+ case MONO_TYPE_ARRAY:
+ eclass = mono_class_from_mono_type (type->data.array->type);
+ class = mono_array_class_get (eclass, type->data.array->rank);
+ break;
+ case MONO_TYPE_SZARRAY:
+ eclass = mono_class_from_mono_type (type->data.type);
+ class = mono_array_class_get (eclass, 1);
+ break;
+ default:
+ g_warning ("implement me: %08x", type->type);
+ g_assert_not_reached ();
}
- class = g_malloc0 (class->class_size);
- *class = stack_class;
+ mono_metadata_free_type (type);
+
+ return class;
+}
+
+/**
+ * mono_array_class_get:
+ * @eclass: element type class
+ * @rank: the dimension of the array class
+ *
+ * Returns: a class object describing the array with element type @etype and
+ * dimension @rank.
+ */
+MonoClass *
+mono_array_class_get (MonoClass *eclass, guint32 rank)
+{
+ MonoImage *image;
+ MonoClass *class;
+ static MonoClass *parent = NULL;
+ MonoArrayClass *aclass;
+ guint32 key;
+
+ g_assert (rank <= 255);
+
+ if (!parent)
+ parent = mono_defaults.array_class;
+
+ image = eclass->image;
+
+ 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;
+
+ aclass = g_new0 (MonoArrayClass, 1);
+ class = (MonoClass *)aclass;
+
+ class->image = image;
+ class->name_space = "System";
+ class->name = "Array";
+ class->type_token = 0;
+ class->flags = TYPE_ATTRIBUTE_CLASS;
+ class->parent = parent;
+ class->instance_size = mono_class_instance_size (class->parent);
+ class->class_size = 0;
+
+ aclass->rank = rank;
+ aclass->element_class = eclass;
+
+ g_hash_table_insert (image->array_cache, GUINT_TO_POINTER (key), class);
return class;
}
+/**
+ * mono_class_instance_size:
+ * @klass: a class
+ *
+ * Returns: the size of an object instance
+ */
+gint32
+mono_class_instance_size (MonoClass *klass)
+{
+
+ if (!klass->metadata_inited)
+ mono_class_metadata_init (klass);
+
+ return klass->instance_size;
+}
+
+/**
+ * mono_class_value_size:
+ * @klass: a class
+ *
+ * This function is used for value types, and return the
+ * space and the alignment to store that kind of value object.
+ *
+ * Returns: the size of a value of kind @klass
+ */
+gint32
+mono_class_value_size (MonoClass *klass, guint32 *align)
+{
+ gint32 size;
+
+ /* fixme: check disable, because we still have external revereces to
+ * mscorlib and Dummy Objects
+ */
+ /*g_assert (klass->valuetype);*/
+
+ size = mono_class_instance_size (klass) - sizeof (MonoObject);
+
+ if (align) {
+ if (size <= 4)
+ *align = 4;
+ else
+ *align = 8;
+ }
+
+ return size;
+}
+
+/**
+ * mono_class_data_size:
+ * @klass: a class
+ *
+ * Returns: the size of the static class data
+ */
+gint32
+mono_class_data_size (MonoClass *klass)
+{
+
+ if (!klass->metadata_inited)
+ mono_class_metadata_init (klass);
+
+ return klass->class_size;
+}
+
/*
* Auxiliary routine to mono_class_get_field
*
{
int idx = mono_metadata_token_index (field_token);
- if (mono_metadata_token_code (field_token) == TOKEN_TYPE_MEMBER_REF)
+ if (mono_metadata_token_code (field_token) == MONO_TOKEN_MEMBER_REF)
g_error ("Unsupported Field Token is a MemberRef, implement me");
- g_assert (mono_metadata_token_code (field_token) == TOKEN_TYPE_FIELD_DEF);
+ g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
return mono_class_get_field_idx (class, idx - 1);
}
-static void
-typedef_from_typeref (MonoImage *image, guint32 type_token, MonoImage **rimage, guint32 *index)
+MonoClassField *
+mono_class_get_field_from_name (MonoClass *klass, const char *name)
{
- guint32 cols[6];
- metadata_t *m = &image->metadata;
- metadata_tableinfo_t *t = &m->tables[META_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 [META_TABLE_TYPEDEF];
- /* dumb search for now */
- for (i=0; i < t->rows; ++i) {
- mono_metadata_decode_row (t, i, cols, 6);
- if (strcmp (name, mono_metadata_string_heap (m, cols [1])) == 0
- && strcmp (nspace, mono_metadata_string_heap (m, cols [2])) == 0) {
- *rimage = image;
- *index = i + 1;
- return;
- }
+ int i;
+ guint32 token;
+ MonoTableInfo *t = &klass->image->tables [MONO_TABLE_FIELD];
+
+ for (i = 0; i < klass->field.count; ++i) {
+ token = mono_metadata_decode_row_col (t, klass->field.first + i, MONO_FIELD_NAME);
+ if (strcmp (name, mono_metadata_string_heap (klass->image, token)) == 0)
+ return &klass->fields [i];
}
- g_assert_not_reached ();
-
+ return NULL;
}
/**
* 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
*/
{
MonoClass *class;
- if ((type_token & 0xff000000) == TOKEN_TYPE_TYPE_DEF
- && (class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
- return class;
-
switch (type_token & 0xff000000){
- case TOKEN_TYPE_TYPE_DEF:
- class = mono_class_create_from_typedef (image, type_token);
- break;
-
- case TOKEN_TYPE_TYPE_REF: {
- typedef_from_typeref (image, type_token, &image, &type_token);
+ 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:
+ return mono_class_create_from_typeref (image, type_token);
+ case MONO_TOKEN_TYPE_SPEC:
+ 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;
- }
- case TOKEN_TYPE_TYPE_SPEC:
- g_error ("Can not handle class creation of TypeSpecs yet");
-
default:
g_assert_not_reached ();
}
return class;
}
+MonoClass *
+mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
+{
+ GHashTable *nspace_table;
+ guint32 token;
+
+ nspace_table = g_hash_table_lookup (image->name_cache, name_space);
+ if (!nspace_table)
+ return 0;
+ token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
+
+ if (!token) {
+ g_warning ("token not found for %s.%s in image %s", name_space, name, image->name);
+ return NULL;
+ }
+
+ token = MONO_TOKEN_TYPE_DEF | token;
+
+ return mono_class_get (image, token);
+}
+
+/**
+ * mono_array_element_size:
+ * @ac: pointer to a #MonoArrayClass
+ *
+ * Returns: the size of single array element.
+ */
+gint32
+mono_array_element_size (MonoArrayClass *ac)
+{
+ gint32 esize;
+
+ esize = mono_class_instance_size (ac->element_class);
+
+ if (ac->element_class->valuetype)
+ esize -= sizeof (MonoObject);
+
+ return esize;
+}