#include <config.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <glib.h>
#include "metadata.h"
#include "tabledefs.h"
#include "mono-endian.h"
#include "cil-coff.h"
#include "tokentype.h"
+#include "metadata-internals.h"
+#include "class-internals.h"
#include "private.h"
#include "class.h"
-static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, const char *ptr, const char **rptr);
+static void do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
+ const char *ptr, const char **rptr);
+
+static gboolean do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only);
+static gboolean mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only);
+static gboolean _mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2,
+ gboolean signature_only);
/*
* Encoding of the "description" argument:
* mono_meta_table_name:
* @table: table index
*
- * Returns the name for the @table index
+ * Returns: the name for the @table index
*/
const char *
mono_meta_table_name (int table)
mono_metadata_compute_size (MonoImage *meta, int tableindex, guint32 *result_bitfield)
{
guint32 bitfield = 0;
- int size = 0, field_size;
+ int size = 0, field_size = 0;
int i, n, code;
int shift = 0;
const MonoMetaTable *table = tables [tableindex].table;
* @table: table code.
* @idx: index of element to retrieve from @table.
*
- * Returns a pointer to the @idx element in the metadata table
+ * Returns: a pointer to the @idx element in the metadata table
* whose code is @table.
*/
const char *
* @meta: metadata context
* @token: metadata token
*
- * Returns a pointer to the data in the metadata represented by the
+ * Returns: a pointer to the data in the metadata represented by the
* token #token.
*/
const char *
* mono_metadata_get_table:
* @table: table to retrieve
*
- * Returns the MonoMetaTable structure for table @table
+ * Returns: the MonoMetaTable structure for table @table
*/
const MonoMetaTable *
mono_metadata_get_table (MonoMetaTableEnum table)
* into the guint32 @res array that has res_size elements
*/
void
-mono_metadata_decode_row (MonoTableInfo *t, int idx, guint32 *res, int res_size)
+mono_metadata_decode_row (const MonoTableInfo *t, int idx, guint32 *res, int res_size)
{
guint32 bitfield = t->size_bitfield;
int i, count = mono_metadata_table_count (bitfield);
* row in the table @t.
*/
guint32
-mono_metadata_decode_row_col (MonoTableInfo *t, int idx, guint col)
+mono_metadata_decode_row_col (const MonoTableInfo *t, int idx, guint col)
{
guint32 bitfield = t->size_bitfield;
int i;
* and dimensions.
*/
MonoArrayType *
-mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
+mono_metadata_parse_array_full (MonoImage *m, MonoGenericContext *generic_context,
+ const char *ptr, const char **rptr)
{
int i;
MonoArrayType *array = g_new0 (MonoArrayType, 1);
MonoType *etype;
- etype = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
array->eklass = mono_class_from_mono_type (etype);
array->rank = mono_metadata_decode_value (ptr, &ptr);
return array;
}
+MonoArrayType *
+mono_metadata_parse_array (MonoImage *m, const char *ptr, const char **rptr)
+{
+ return mono_metadata_parse_array_full (m, NULL, ptr, rptr);
+}
+
/*
* mono_metadata_free_array:
* @array: array description
* private static
* private static literal
*/
-static MonoType
+static const MonoType
builtin_types[] = {
/* data, attrs, type, nmods, byref, pinned */
{{NULL}, 0, MONO_TYPE_VOID, 0, 0, 0},
{{NULL}, 0, MONO_TYPE_R8, 0, 1, 0},
{{NULL}, 0, MONO_TYPE_STRING, 0, 0, 0},
{{NULL}, 0, MONO_TYPE_STRING, 0, 1, 0},
+ {{NULL}, 0, MONO_TYPE_OBJECT, 0, 0, 0},
+ {{NULL}, 0, MONO_TYPE_OBJECT, 0, 1, 0},
{{NULL}, 0, MONO_TYPE_TYPEDBYREF, 0, 0, 0},
{{NULL}, 0, MONO_TYPE_I, 0, 0, 0},
{{NULL}, 0, MONO_TYPE_I, 0, 1, 0},
#define NBUILTIN_TYPES() (sizeof (builtin_types) / sizeof (builtin_types [0]))
static GHashTable *type_cache = NULL;
+static GHashTable *generic_inst_cache = NULL;
+static GHashTable *generic_class_cache = NULL;
+static int next_generic_inst_id = 0;
/*
* MonoTypes with modifies are never cached, so we never check or use that field.
return 1;
}
+static guint
+mono_generic_inst_hash (gconstpointer data)
+{
+ const MonoGenericInst *ginst = (const MonoGenericInst *) data;
+ return ginst->type_argc | (ginst->is_open << 8);
+}
+
+static gboolean
+mono_generic_inst_equal (gconstpointer ka, gconstpointer kb)
+{
+ const MonoGenericInst *a = (const MonoGenericInst *) ka;
+ const MonoGenericInst *b = (const MonoGenericInst *) kb;
+ int i;
+
+ if ((a->is_open != b->is_open) || (a->type_argc != b->type_argc))
+ return FALSE;
+ for (i = 0; i < a->type_argc; ++i) {
+ if (!do_mono_metadata_type_equal (a->type_argv [i], b->type_argv [i], FALSE))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static guint
+mono_generic_class_hash (gconstpointer data)
+{
+ const MonoGenericClass *gclass = (const MonoGenericClass *) data;
+ return mono_metadata_type_hash (&gclass->container_class->byval_arg);
+}
+
+static gboolean
+mono_generic_class_equal (gconstpointer ka, gconstpointer kb)
+{
+ const MonoGenericClass *a = (const MonoGenericClass *) ka;
+ const MonoGenericClass *b = (const MonoGenericClass *) kb;
+
+ return _mono_metadata_generic_class_equal (a, b, FALSE);
+}
+
/**
* mono_metadata_init:
*
int i;
type_cache = g_hash_table_new (mono_type_hash, mono_type_equal);
+ generic_inst_cache = g_hash_table_new (mono_generic_inst_hash, mono_generic_inst_equal);
+ generic_class_cache = g_hash_table_new (mono_generic_class_hash, mono_generic_class_equal);
for (i = 0; i < NBUILTIN_TYPES (); ++i)
- g_hash_table_insert (type_cache, &builtin_types [i], &builtin_types [i]);
+ g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
}
-/*
+/**
* mono_metadata_parse_type:
* @m: metadata context
* @mode: king of type that may be found at @ptr
* This function can be used to decode type descriptions in method signatures,
* field signatures, locals signatures etc.
*
+ * To parse a generic type, `generic_container' points to the current class'es
+ * (the `generic_container' field in the MonoClass) or the current generic method's
+ * (the `generic_container' field in the MonoMethodNormal) generic container.
+ * When we encounter any MONO_TYPE_VAR or MONO_TYPE_MVAR's, they're looked up in
+ * this MonoGenericContainer.
+ *
* Returns: a #MonoType structure representing the decoded type.
*/
MonoType*
-mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs, const char *ptr, const char **rptr)
+mono_metadata_parse_type_full (MonoImage *m, MonoGenericContext *generic_context, MonoParseTypeMode mode,
+ short opt_attrs, const char *ptr, const char **rptr)
{
MonoType *type, *cached;
+ MonoType stype;
gboolean byref = FALSE;
+ gboolean pinned = FALSE;
+ const char *tmp_ptr;
+ int count = 0;
+ gboolean found;
/*
* According to the spec, custom modifiers should come before the byref
* Also, this type seems to be different from 'object & modopt(...)'. Maybe
* it would be better to treat byref as real type constructor instead of
* a modifier...
+ * Also, pinned should come before anything else, but some MSV++ produced
+ * assemblies violate this (#bug 61990).
*/
- if (*ptr == MONO_TYPE_BYREF) {
- byref = TRUE;
- ++ptr;
- }
- switch (mode) {
- case MONO_PARSE_MOD_TYPE:
- case MONO_PARSE_PARAM:
- case MONO_PARSE_RET:
- case MONO_PARSE_LOCAL: /* should not have modifiers according to the spec, but ms tools disagree */
- case MONO_PARSE_FIELD: {
- /* count the modifiers */
- const char *tmp_ptr = ptr;
- int count = 0;
- while (mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr))
- count++;
- if (count) {
- type = g_malloc0 (sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
- type->num_mods = count;
- if (count > 64)
- g_warning ("got more than 64 modifiers in type");
- /* save them this time */
- count = 0;
- while (mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr))
- count++;
+ /* Count the modifiers first */
+ tmp_ptr = ptr;
+ found = TRUE;
+ while (found) {
+ switch (*tmp_ptr) {
+ case MONO_TYPE_PINNED:
+ case MONO_TYPE_BYREF:
+ ++tmp_ptr;
break;
- } /* fall through */
+ case MONO_TYPE_CMOD_REQD:
+ case MONO_TYPE_CMOD_OPT:
+ count ++;
+ mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
+ break;
+ default:
+ found = FALSE;
+ }
}
- case MONO_PARSE_TYPE:
- /*
- * Later we can avoid doing this allocation.
- */
- type = g_new0 (MonoType, 1);
- break;
- default:
- g_assert_not_reached ();
+
+ if (count) {
+ type = g_malloc0 (sizeof (MonoType) + ((gint32)count - MONO_ZERO_LEN_ARRAY) * sizeof (MonoCustomMod));
+ type->num_mods = count;
+ if (count > 64)
+ g_warning ("got more than 64 modifiers in type");
}
-
- type->attrs = opt_attrs;
- type->byref = byref;
- if (mode == MONO_PARSE_LOCAL) {
- /*
- * check for pinned flag
- */
- if (*ptr == MONO_TYPE_PINNED) {
- type->pinned = 1;
+ else {
+ type = &stype;
+ memset (type, 0, sizeof (MonoType));
+ }
+
+ /* Parse pinned, byref and custom modifiers */
+ found = TRUE;
+ count = 0;
+ while (found) {
+ switch (*ptr) {
+ case MONO_TYPE_PINNED:
+ pinned = TRUE;
+ ++ptr;
+ break;
+ case MONO_TYPE_BYREF:
+ byref = TRUE;
++ptr;
+ break;
+ case MONO_TYPE_CMOD_REQD:
+ case MONO_TYPE_CMOD_OPT:
+ mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
+ count ++;
+ break;
+ default:
+ found = FALSE;
}
}
+
+ type->attrs = opt_attrs;
+ type->byref = byref;
+ type->pinned = pinned ? 1 : 0;
+
+ do_mono_metadata_parse_type (type, m, generic_context, ptr, &ptr);
- switch (*ptr) {
- case MONO_TYPE_BYREF:
- if (mode == MONO_PARSE_FIELD)
- g_warning ("A field type cannot be byref");
- type->byref = 1;
- ptr++;
- /* follow through */
- default:
- /*if (*ptr == MONO_TYPE_VOID && mode != MONO_PARSE_RET)
- g_error ("void not allowed in param");*/
- do_mono_metadata_parse_type (type, m, ptr, &ptr);
- break;
- }
if (rptr)
*rptr = ptr;
- /* No need to use locking since nobody is modifying the hash table */
- if (mode != MONO_PARSE_PARAM && !type->num_mods && (cached = g_hash_table_lookup (type_cache, type))) {
- mono_metadata_free_type (type);
- return cached;
- } else {
- return type;
+
+ /* FIXME: remove the != MONO_PARSE_PARAM condition, this accounts for
+ * almost 10k (about 2/3rds) of all MonoType's we create.
+ */
+ if (mode != MONO_PARSE_PARAM && !type->num_mods) {
+ /* no need to free type here, because it is on the stack */
+ if ((type->type == MONO_TYPE_CLASS || type->type == MONO_TYPE_VALUETYPE) && !type->pinned && !type->attrs) {
+ if (type->byref)
+ return &type->data.klass->this_arg;
+ else
+ return &type->data.klass->byval_arg;
+ }
+ /* No need to use locking since nobody is modifying the hash table */
+ if ((cached = g_hash_table_lookup (type_cache, type)))
+ return cached;
}
+
+ /*printf ("%x%c %s\n", type->attrs, type->pinned ? 'p' : ' ', mono_type_full_name (type));*/
+
+ if (type == &stype)
+ type = g_memdup (&stype, sizeof (MonoType));
+ return type;
+}
+
+MonoType*
+mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
+ const char *ptr, const char **rptr)
+{
+ return mono_metadata_parse_type_full (m, NULL, mode, opt_attrs, ptr, rptr);
}
/*
* Returns: a MonoMethodSignature describing the signature.
*/
MonoMethodSignature *
-mono_metadata_parse_signature (MonoImage *image, guint32 token)
+mono_metadata_parse_signature_full (MonoImage *image, MonoGenericContext *generic_context, guint32 token)
{
MonoTableInfo *tables = image->tables;
guint32 idx = mono_metadata_token_index (token);
ptr = mono_metadata_blob_heap (image, sig);
mono_metadata_decode_blob_size (ptr, &ptr);
- return mono_metadata_parse_method_signature (image, FALSE, ptr, NULL);
+ return mono_metadata_parse_method_signature_full (image, generic_context, FALSE, ptr, NULL);
+}
+
+MonoMethodSignature *
+mono_metadata_parse_signature (MonoImage *image, guint32 token)
+{
+ return mono_metadata_parse_signature_full (image, NULL, token);
}
MonoMethodSignature*
/* later we want to allocate signatures with mempools */
sig = g_malloc0 (sizeof (MonoMethodSignature) + ((gint32)nparams - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
sig->param_count = nparams;
+ sig->sentinelpos = -1;
return sig;
}
+MonoMethodSignature*
+mono_metadata_signature_dup (MonoMethodSignature *sig)
+{
+ int sigsize;
+
+ sigsize = sizeof (MonoMethodSignature) + sig->param_count * sizeof (MonoType *);
+ return g_memdup (sig, sigsize);
+}
+
/*
* mono_metadata_parse_method_signature:
* @m: metadata context
* Returns: a MonoMethodSignature describing the signature.
*/
MonoMethodSignature *
-mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
+mono_metadata_parse_method_signature_full (MonoImage *m, MonoGenericContext *generic_context,
+ int def, const char *ptr, const char **rptr)
{
MonoMethodSignature *method;
int i, ret_attrs = 0, *pattrs = NULL;
guint32 hasthis = 0, explicit_this = 0, call_convention, param_count;
guint32 gen_param_count = 0;
+ gboolean is_open = FALSE;
+ MonoGenericContext *context = NULL;
if (*ptr & 0x10)
gen_param_count = 1;
method->explicit_this = explicit_this;
method->call_convention = call_convention;
method->generic_param_count = gen_param_count;
- if (call_convention != 0xa)
- method->ret = mono_metadata_parse_type (m, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
+
+ if (gen_param_count)
+ method->has_type_parameters = 1;
+
+ if (gen_param_count && (!generic_context || !generic_context->container->is_method)) {
+ MonoGenericContainer *container = g_new0 (MonoGenericContainer, 1);
+
+ if (generic_context)
+ container->parent = generic_context->container;
+ container->is_signature = 1;
+
+ context = &container->context;
+ container->context.container = container;
+
+ container->type_argc = gen_param_count;
+ container->type_params = g_new0 (MonoGenericParam, gen_param_count);
+
+ for (i = 0; i < gen_param_count; i++) {
+ container->type_params [i].owner = container;
+ container->type_params [i].num = i;
+ }
+ } else
+ context = generic_context;
+
+ if (call_convention != 0xa) {
+ method->ret = mono_metadata_parse_type_full (m, context, MONO_PARSE_RET, ret_attrs, ptr, &ptr);
+ is_open = mono_class_is_open_constructed_type (method->ret);
+ }
if (method->param_count) {
method->sentinelpos = -1;
method->sentinelpos = i;
ptr++;
}
- method->params [i] = mono_metadata_parse_type (m, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
+ method->params [i] = mono_metadata_parse_type_full (
+ m, context, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
+ if (!is_open)
+ is_open = mono_class_is_open_constructed_type (method->params [i]);
}
}
+
+ method->has_type_parameters = is_open;
+
+ if (def && (method->call_convention == MONO_CALL_VARARG))
+ method->sentinelpos = method->param_count;
+
g_free (pattrs);
if (rptr)
return method;
}
+MonoMethodSignature *
+mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, const char **rptr)
+{
+ return mono_metadata_parse_method_signature_full (m, NULL, def, ptr, rptr);
+}
+
/*
* mono_metadata_free_method_signature:
* @sig: signature to destroy
g_free (sig);
}
-static void
-do_mono_metadata_parse_generic_inst (MonoType *type, MonoImage *m, const char *ptr, const char **rptr)
+MonoGenericInst *
+mono_metadata_lookup_generic_inst (MonoGenericInst *ginst)
{
- MonoGenericInst *ginst = g_new0 (MonoGenericInst, 1);
- MonoType *cached;
- int i, count;
+ MonoGenericInst *cached;
+ int i;
+
+ cached = g_hash_table_lookup (generic_inst_cache, ginst);
+ if (cached) {
+ for (i = 0; i < ginst->type_argc; i++)
+ mono_metadata_free_type (ginst->type_argv [i]);
+ g_free (ginst->type_argv);
+ g_free (ginst);
+ return cached;
+ }
- type->data.generic_inst = ginst;
+ ginst->id = ++next_generic_inst_id;
+ g_hash_table_insert (generic_inst_cache, ginst, ginst);
- ginst->context = g_new0 (MonoGenericContext, 1);
- ginst->context->ginst = ginst;
+ return ginst;
+}
- ginst->klass = g_new0 (MonoClass, 1);
+MonoGenericClass *
+mono_metadata_lookup_generic_class (MonoGenericClass *gclass)
+{
+ MonoGenericClass *cached;
+ int i;
- ginst->generic_type = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
- ginst->type_argc = count = mono_metadata_decode_value (ptr, &ptr);
- ginst->type_argv = g_new0 (MonoType*, count);
+ cached = g_hash_table_lookup (generic_class_cache, gclass);
+ if (cached)
+ return cached;
- /*
- * Create the klass before parsing the type arguments.
- * This is required to support "recursive" definitions.
- * See mcs/tests/gen-23.cs for an example.
- */
+ g_hash_table_insert (generic_class_cache, gclass, gclass);
+ return NULL;
+}
+
+MonoGenericInst *
+mono_metadata_inflate_generic_inst (MonoGenericInst *ginst, MonoGenericContext *context)
+{
+ MonoGenericInst *nginst, *cached;
+ int i;
+
+ nginst = g_new0 (MonoGenericInst, 1);
+ nginst->type_argc = ginst->type_argc;
+ nginst->type_argv = g_new0 (MonoType*, nginst->type_argc);
+
+ for (i = 0; i < nginst->type_argc; i++) {
+ MonoType *t = ginst->type_argv [i];
- ginst->init_pending = TRUE;
+ nginst->type_argv [i] = mono_class_inflate_generic_type (t, context);
- mono_class_create_generic (ginst);
+ if (!nginst->is_open)
+ nginst->is_open = mono_class_is_open_constructed_type (nginst->type_argv [i]);
+ }
+
+ return mono_metadata_lookup_generic_inst (nginst);
+}
+
+MonoGenericInst *
+mono_metadata_parse_generic_inst (MonoImage *m, MonoGenericContext *generic_context,
+ int count, const char *ptr, const char **rptr)
+{
+ MonoGenericInst *ginst;
+ int i;
+
+ ginst = g_new0 (MonoGenericInst, 1);
+ ginst->type_argc = count;
+ ginst->type_argv = g_new0 (MonoType*, count);
for (i = 0; i < ginst->type_argc; i++) {
- MonoType *t = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ MonoType *t = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
ginst->type_argv [i] = t;
if (!ginst->is_open)
ginst->is_open = mono_class_is_open_constructed_type (t);
}
+ if (rptr)
+ *rptr = ptr;
+
+ return mono_metadata_lookup_generic_inst (ginst);
+}
+
+static void
+do_mono_metadata_parse_generic_class (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
+ const char *ptr, const char **rptr)
+{
+ MonoGenericClass *gclass = g_new0 (MonoGenericClass, 1);
+ MonoGenericContainer *container;
+ MonoGenericClass *cached;
+ MonoGenericInst *ginst;
+ MonoClass *gklass;
+ MonoType *gtype;
+ int i, count;
+
+ type->data.generic_class = gclass;
+
+ gclass->context = g_new0 (MonoGenericContext, 1);
+ gclass->context->gclass = gclass;
+
+ gclass->klass = g_new0 (MonoClass, 1);
+
+ gtype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_TYPE, 0, ptr, &ptr);
+ gclass->container_class = gklass = mono_class_from_mono_type (gtype);
+
+ g_assert ((gclass->context->container = gklass->generic_container) != NULL);
+ count = mono_metadata_decode_value (ptr, &ptr);
+
+ /*
+ * Create the klass before parsing the type arguments.
+ * This is required to support "recursive" definitions.
+ * See mcs/tests/gen-23.cs for an example.
+ */
+
+ gclass->init_pending = TRUE;
+
+ mono_class_create_generic (gclass);
+
+ gclass->inst = mono_metadata_parse_generic_inst (m, generic_context, count, ptr, &ptr);
+
+ mono_class_create_generic_2 (gclass);
if (rptr)
*rptr = ptr;
* instantiated type. This happens for instance if we're part of a method or
* local variable signature.
*
- * It's important to return the same MonoGenericInst * for each particualar
+ * It's important to return the same MonoGenericClass * for each particualar
* instantiation of a generic type (ie "Stack<Int32>") to make static fields
* work.
*
* type.
*/
- cached = g_hash_table_lookup (m->generic_inst_cache, ginst);
+ cached = g_hash_table_lookup (generic_class_cache, gclass);
if (cached) {
- g_free (ginst->klass);
- g_free (ginst->type_argv);
- g_free (ginst);
+ g_free (gclass->klass);
+ g_free (gclass);
- type->data.generic_inst = cached->data.generic_inst;
+ type->data.generic_class = cached;
return;
} else {
- cached = g_new0 (MonoType, 1);
- cached->type = MONO_TYPE_GENERICINST;
- cached->data.generic_inst = ginst;
-
- g_hash_table_insert (m->generic_inst_cache, ginst, cached);
+ g_hash_table_insert (generic_class_cache, gclass, gclass);
mono_stats.generic_instance_count++;
- mono_stats.generics_metadata_size += sizeof (MonoGenericInst) +
+ mono_stats.generics_metadata_size += sizeof (MonoGenericClass) +
sizeof (MonoGenericContext) +
- ginst->type_argc * sizeof (MonoType);
+ gclass->inst->type_argc * sizeof (MonoType);
}
- ginst->init_pending = FALSE;
+ gclass->init_pending = FALSE;
}
+/*
+ * do_mono_metadata_parse_generic_param:
+ * @generic_container: Our MonoClass's or MonoMethodNormal's MonoGenericContainer;
+ * see mono_metadata_parse_type_full() for details.
+ * Internal routine to parse a generic type parameter.
+ */
static MonoGenericParam *
-mono_metadata_parse_generic_param (MonoImage *m, const char *ptr, const char **rptr)
+mono_metadata_parse_generic_param (MonoImage *m, MonoGenericContext *generic_context,
+ gboolean is_mvar, const char *ptr, const char **rptr)
{
- MonoGenericParam *generic_param = g_new0 (MonoGenericParam, 1);
-
- generic_param->num = mono_metadata_decode_value (ptr, &ptr);
+ MonoGenericContainer *generic_container;
+ int index;
+ index = mono_metadata_decode_value (ptr, &ptr);
if (rptr)
*rptr = ptr;
- return generic_param;
+ g_assert (generic_context);
+ if (generic_context->gmethod)
+ generic_container = generic_context->gmethod->container;
+ else if (generic_context->gclass)
+ generic_container = generic_context->gclass->container_class->generic_container;
+ else
+ generic_container = generic_context->container;
+
+ if (!is_mvar) {
+ g_assert (generic_container);
+ if (generic_container->parent) {
+ /*
+ * The current MonoGenericContainer is a generic method -> its `parent'
+ * points to the containing class'es container.
+ */
+ generic_container = generic_container->parent;
+ }
+ g_assert (generic_container && !generic_container->is_method);
+ g_assert (index < generic_container->type_argc);
+
+ return &generic_container->type_params [index];
+ } else {
+ g_assert (generic_container && (generic_container->is_method || generic_container->is_signature));
+ g_assert (index < generic_container->type_argc);
+
+ return &generic_container->type_params [index];
+ }
}
/*
* This extracts a Type as specified in Partition II (22.2.12)
*/
static void
-do_mono_metadata_parse_type (MonoType *type, MonoImage *m, const char *ptr, const char **rptr)
+do_mono_metadata_parse_type (MonoType *type, MonoImage *m, MonoGenericContext *generic_context,
+ const char *ptr, const char **rptr)
{
type->type = mono_metadata_decode_value (ptr, &ptr);
break;
}
case MONO_TYPE_SZARRAY: {
- MonoType *etype = mono_metadata_parse_type (m, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+ MonoType *etype = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
type->data.klass = mono_class_from_mono_type (etype);
+ mono_metadata_free_type (etype);
break;
}
case MONO_TYPE_PTR:
- type->data.type = mono_metadata_parse_type (m, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
+ type->data.type = mono_metadata_parse_type_full (m, generic_context, MONO_PARSE_MOD_TYPE, 0, ptr, &ptr);
break;
case MONO_TYPE_FNPTR:
- type->data.method = mono_metadata_parse_method_signature (m, 0, ptr, &ptr);
+ type->data.method = mono_metadata_parse_method_signature_full (m, generic_context, 0, ptr, &ptr);
break;
case MONO_TYPE_ARRAY:
- type->data.array = mono_metadata_parse_array (m, ptr, &ptr);
+ type->data.array = mono_metadata_parse_array_full (m, generic_context, ptr, &ptr);
break;
case MONO_TYPE_MVAR:
+ type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, TRUE, ptr, &ptr);
+ break;
+
case MONO_TYPE_VAR:
- type->data.generic_param = mono_metadata_parse_generic_param (m, ptr, &ptr);
+ type->data.generic_param = mono_metadata_parse_generic_param (m, generic_context, FALSE, ptr, &ptr);
break;
case MONO_TYPE_GENERICINST:
- do_mono_metadata_parse_generic_inst (type, m, ptr, &ptr);
+ do_mono_metadata_parse_generic_class (type, m, generic_context, ptr, &ptr);
break;
default:
{
if (type >= builtin_types && type < builtin_types + NBUILTIN_TYPES ())
return;
+
switch (type->type){
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ if (!type->data.klass)
+ break;
+ /* fall through */
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_VALUETYPE:
+ if (type == &type->data.klass->byval_arg || type == &type->data.klass->this_arg)
+ return;
+ break;
case MONO_TYPE_PTR:
mono_metadata_free_type (type->data.type);
break;
* @ptr: Points to the beginning of the Section Data (25.3)
*/
static void
-parse_section_data (MonoMethodHeader *mh, const unsigned char *ptr)
+parse_section_data (MonoImage *m, MonoMethodHeader *mh, const unsigned char *ptr)
{
unsigned char sect_data_flags;
const unsigned char *sptr;
mh->clauses = g_new0 (MonoExceptionClause, mh->num_clauses);
for (i = 0; i < mh->num_clauses; ++i) {
MonoExceptionClause *ec = &mh->clauses [i];
-
+ guint32 tof_value;
if (is_fat) {
- /* we could memcpy and byteswap */
ec->flags = read32 (p);
p += 4;
ec->try_offset = read32 (p);
p += 4;
ec->handler_len = read32 (p);
p += 4;
- ec->token_or_filter = read32 (p);
+ tof_value = read32 (p);
p += 4;
} else {
ec->flags = read16 (p);
p += 2;
ec->handler_len = *p;
++p;
- ec->token_or_filter = read32 (p);
+ tof_value = read32 (p);
p += 4;
}
+ if (ec->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+ ec->data.filter_offset = tof_value;
+ } else if (ec->flags == MONO_EXCEPTION_CLAUSE_NONE) {
+ ec->data.catch_class = tof_value? mono_class_get (m, tof_value): 0;
+ } else {
+ ec->data.catch_class = NULL;
+ }
/* g_print ("try %d: %x %04x-%04x %04x\n", i, ec->flags, ec->try_offset, ec->try_offset+ec->try_len, ec->try_len); */
}
* Returns: a MonoMethodHeader.
*/
MonoMethodHeader *
-mono_metadata_parse_mh (MonoImage *m, const char *ptr)
+mono_metadata_parse_mh_full (MonoImage *m, MonoGenericContext *generic_context, const char *ptr)
{
MonoMethodHeader *mh;
unsigned char flags = *(const unsigned char *) ptr;
mh = g_malloc0 (sizeof (MonoMethodHeader) + (len - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
mh->num_locals = len;
for (i = 0; i < len; ++i)
- mh->locals [i] = mono_metadata_parse_type (m, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
+ mh->locals [i] = mono_metadata_parse_type_full (
+ m, generic_context, MONO_PARSE_LOCAL, 0, locals_ptr, &locals_ptr);
} else {
mh = g_new0 (MonoMethodHeader, 1);
}
mh->max_stack = max_stack;
mh->init_locals = init_locals;
if (fat_flags & METHOD_HEADER_MORE_SECTS)
- parse_section_data (mh, (const unsigned char*)ptr);
+ parse_section_data (m, mh, (const unsigned char*)ptr);
return mh;
}
+MonoMethodHeader *
+mono_metadata_parse_mh (MonoImage *m, const char *ptr)
+{
+ return mono_metadata_parse_mh_full (m, NULL, ptr);
+}
+
/*
* mono_metadata_free_mh:
* @mh: a method header
return 1;
}
-/*
+static int
+declsec_locator (const void *a, const void *b)
+{
+ locator_t *loc = (locator_t *) a;
+ const char *bb = (const char *) b;
+ guint32 table_index = (bb - loc->t->base) / loc->t->row_size;
+ guint32 col;
+
+ col = mono_metadata_decode_row_col (loc->t, table_index, loc->col_idx);
+
+ if (loc->idx == col) {
+ loc->result = table_index;
+ return 0;
+ }
+ if (loc->idx < col)
+ return -1;
+ else
+ return 1;
+}
+
+/**
* mono_metadata_typedef_from_field:
* @meta: metadata context
* @index: FieldDef token
*
- * Returns the 1-based index into the TypeDef table of the type that
- * declared the field described by @index.
- * Returns 0 if not found.
+ * Returns: the 1-based index into the TypeDef table of the type that
+ * declared the field described by @index, or 0 if not found.
*/
guint32
mono_metadata_typedef_from_field (MonoImage *meta, guint32 index)
* @meta: metadata context
* @index: MethodDef token
*
- * Returns the 1-based index into the TypeDef table of the type that
- * declared the method described by @index.
- * Returns 0 if not found.
+ * Returns: the 1-based index into the TypeDef table of the type that
+ * declared the method described by @index. 0 if not found.
*/
guint32
mono_metadata_typedef_from_method (MonoImage *meta, guint32 index)
* @meta: metadata context
* @index: typedef token
*
- * Returns and array of interfaces that the @index typedef token implements.
+ * Returns: and array of interfaces that the @index typedef token implements.
* The number of elemnts in the array is returned in @count.
*/
MonoClass**
-mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
+mono_metadata_interfaces_from_typedef_full (MonoImage *meta, guint32 index, guint *count, MonoGenericContext *context)
{
MonoTableInfo *tdef = &meta->tables [MONO_TABLE_INTERFACEIMPL];
locator_t loc;
if (cols [MONO_INTERFACEIMPL_CLASS] != loc.idx)
break;
result = g_renew (MonoClass*, result, i + 1);
- result [i] = mono_class_get (meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]));
+ result [i] = mono_class_get_full (
+ meta, mono_metadata_token_from_dor (cols [MONO_INTERFACEIMPL_INTERFACE]), context);
*count = ++i;
++start;
}
return result;
}
+MonoClass**
+mono_metadata_interfaces_from_typedef (MonoImage *meta, guint32 index, guint *count)
+{
+ return mono_metadata_interfaces_from_typedef_full (meta, index, count, NULL);
+}
+
/*
* mono_metadata_nested_in_typedef:
* @meta: metadata context
*
* Returns: the 1-based index into the TypeDef table of the first type
* that is nested inside the type described by @index. The search starts at
- * @start_index.
- * Returns 0 if no such type is found.
+ * @start_index. returns 0 if no such type is found.
*/
guint32
mono_metadata_nesting_typedef (MonoImage *meta, guint32 index, guint32 start_index)
* @meta: metadata context
* @index: token representing a type
*
- * Returns the info stored in the ClassLAyout table for the given typedef token
+ * Returns: the info stored in the ClassLAyout table for the given typedef token
* into the @packing and @size pointers.
* Returns 0 if the info is not found.
*/
return loc.result + 1;
}
+/*
+ * mono_metadata_declsec_from_index:
+ * @meta: metadata context
+ * @index: token representing the parent
+ *
+ * Returns: the 0-based index into the DeclarativeSecurity table of the first
+ * attribute which belongs to the metadata object described by @index.
+ * Returns -1 if no such attribute is found.
+ */
+guint32
+mono_metadata_declsec_from_index (MonoImage *meta, guint32 index)
+{
+ MonoTableInfo *tdef = &meta->tables [MONO_TABLE_DECLSECURITY];
+ locator_t loc;
+
+ if (!tdef->base)
+ return -1;
+
+ loc.idx = index;
+ loc.col_idx = MONO_DECL_SECURITY_PARENT;
+ loc.t = tdef;
+
+ if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, declsec_locator))
+ return -1;
+
+ /* Find the first entry by searching backwards */
+ while ((loc.result > 0) && (mono_metadata_decode_row_col (tdef, loc.result - 1, MONO_DECL_SECURITY_PARENT) == index))
+ loc.result --;
+
+ return loc.result;
+}
+
#ifdef DEBUG
static void
mono_backtrace (int limit)
case MONO_TYPE_TYPEDBYREF:
return mono_class_value_size (mono_defaults.typed_reference_class, align);
case MONO_TYPE_GENERICINST: {
- MonoGenericInst *ginst = t->data.generic_inst;
- MonoClass *iclass = mono_class_from_mono_type (ginst->generic_type);
- return mono_type_size (&iclass->byval_arg, align);
+ MonoGenericClass *gclass = t->data.generic_class;
+
+ g_assert (!gclass->inst->is_open && !gclass->klass->generic_container);
+
+ if (gclass->container_class->valuetype) {
+ if (gclass->container_class->enumtype)
+ return mono_type_size (gclass->container_class->enum_basetype, align);
+ else
+ return mono_class_value_size (gclass->klass, align);
+ } else {
+ *align = __alignof__(gpointer);
+ return sizeof (gpointer);
+ }
}
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
return sizeof (gpointer);
case MONO_TYPE_TYPEDBYREF:
*align = __alignof__(gpointer);
- return sizeof (gpointer) * 2;
+ return sizeof (gpointer) * 3;
case MONO_TYPE_R4:
*align = __alignof__(float);
return sizeof (float);
}
}
case MONO_TYPE_GENERICINST: {
- MonoGenericInst *ginst = t->data.generic_inst;
- MonoClass *iclass = mono_class_from_mono_type (ginst->generic_type);
- return mono_type_stack_size (&iclass->byval_arg, align);
+ MonoGenericClass *gclass = t->data.generic_class;
+
+ g_assert (!gclass->inst->is_open && !gclass->klass->generic_container);
+
+ if (gclass->container_class->valuetype) {
+ if (gclass->container_class->enumtype)
+ return mono_type_stack_size (gclass->container_class->enum_basetype, align);
+ else {
+ guint32 size = mono_class_value_size (gclass->klass, align);
+
+ *align = *align + __alignof__(gpointer) - 1;
+ *align &= ~(__alignof__(gpointer) - 1);
+
+ size += sizeof (gpointer) - 1;
+ size &= ~(sizeof (gpointer) - 1);
+
+ return size;
+ }
+ } else {
+ *align = __alignof__(gpointer);
+ return sizeof (gpointer);
+ }
}
default:
g_error ("type 0x%02x unknown", t->type);
return 0;
}
-guint
-mono_metadata_generic_inst_hash (MonoGenericInst *ginst)
+gboolean
+mono_metadata_generic_class_is_valuetype (MonoGenericClass *gclass)
{
- return mono_metadata_type_hash (ginst->generic_type);
+ return gclass->container_class->valuetype;
}
-gboolean
-mono_metadata_generic_inst_equal (MonoGenericInst *g1, MonoGenericInst *g2)
+static gboolean
+_mono_metadata_generic_class_equal (const MonoGenericClass *g1, const MonoGenericClass *g2, gboolean signature_only)
{
int i;
- if (g1->type_argc != g2->type_argc)
+ if ((g1->inst->type_argc != g2->inst->type_argc) || (g1->is_dynamic != g2->is_dynamic))
return FALSE;
- if (!mono_metadata_type_equal (g1->generic_type, g2->generic_type))
+ if (!mono_metadata_class_equal (g1->container_class, g2->container_class, signature_only))
return FALSE;
- for (i = 0; i < g1->type_argc; ++i) {
- if (!mono_metadata_type_equal (g1->type_argv [i], g2->type_argv [i]))
+ for (i = 0; i < g1->inst->type_argc; ++i) {
+ if (!do_mono_metadata_type_equal (g1->inst->type_argv [i], g2->inst->type_argv [i], signature_only))
return FALSE;
}
return TRUE;
}
+guint
+mono_metadata_generic_method_hash (MonoGenericMethod *gmethod)
+{
+ return gmethod->inst->id;
+}
+
+gboolean
+mono_metadata_generic_method_equal (MonoGenericMethod *g1, MonoGenericMethod *g2)
+{
+ return (g1->container == g2->container) && (g1->inst == g2->inst);
+}
+
+
/*
* mono_metadata_type_hash:
* @t1: a type
case MONO_TYPE_ARRAY:
return ((hash << 5) - hash) ^ mono_metadata_type_hash (&t1->data.array->eklass->byval_arg);
case MONO_TYPE_GENERICINST:
- return ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (t1->data.generic_inst);
+ return ((hash << 5) - hash) ^ mono_generic_class_hash (t1->data.generic_class);
}
return hash;
}
static gboolean
-mono_metadata_class_equal (MonoClass *c1, MonoClass *c2)
+mono_metadata_generic_param_equal (MonoGenericParam *p1, MonoGenericParam *p2, gboolean signature_only)
+{
+ if (p1 == p2)
+ return TRUE;
+ if (p1->num != p2->num)
+ return FALSE;
+
+ g_assert (p1->owner && p2->owner);
+ if (p1->owner == p2->owner)
+ return TRUE;
+
+ /*
+ * If `signature_only' is true, we're comparing two (method) signatures.
+ * In this case, the owner of two type parameters doesn't need to match.
+ */
+
+ return signature_only;
+}
+
+static gboolean
+mono_metadata_class_equal (MonoClass *c1, MonoClass *c2, gboolean signature_only)
{
if (c1 == c2)
return TRUE;
- if (c1->generic_inst && c2->generic_inst)
- return mono_metadata_generic_inst_equal (c1->generic_inst, c2->generic_inst);
+ if (c1->generic_class && c2->generic_class)
+ return _mono_metadata_generic_class_equal (c1->generic_class, c2->generic_class, signature_only);
if ((c1->byval_arg.type == MONO_TYPE_VAR) && (c2->byval_arg.type == MONO_TYPE_VAR))
- return c1->byval_arg.data.generic_param->num == c2->byval_arg.data.generic_param->num;
+ return mono_metadata_generic_param_equal (
+ c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, FALSE);
if ((c1->byval_arg.type == MONO_TYPE_MVAR) && (c2->byval_arg.type == MONO_TYPE_MVAR))
- return c1->byval_arg.data.generic_param->num == c2->byval_arg.data.generic_param->num;
+ return mono_metadata_generic_param_equal (
+ c1->byval_arg.data.generic_param, c2->byval_arg.data.generic_param, signature_only);
return FALSE;
}
* Determine if @t1 and @t2 represent the same type.
* Returns: #TRUE if @t1 and @t2 are equal.
*/
-gboolean
-mono_metadata_type_equal (MonoType *t1, MonoType *t2)
+static gboolean
+do_mono_metadata_type_equal (MonoType *t1, MonoType *t2, gboolean signature_only)
{
if (t1->type != t2->type ||
t1->byref != t2->byref)
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS:
case MONO_TYPE_SZARRAY:
- return mono_metadata_class_equal (t1->data.klass, t2->data.klass);
+ return mono_metadata_class_equal (t1->data.klass, t2->data.klass, signature_only);
case MONO_TYPE_PTR:
- return mono_metadata_type_equal (t1->data.type, t2->data.type);
+ return do_mono_metadata_type_equal (t1->data.type, t2->data.type, signature_only);
case MONO_TYPE_ARRAY:
if (t1->data.array->rank != t2->data.array->rank)
return FALSE;
- return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass);
+ return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass, signature_only);
case MONO_TYPE_GENERICINST:
- return mono_metadata_generic_inst_equal (t1->data.generic_inst,
- t2->data.generic_inst);
+ return _mono_metadata_generic_class_equal (
+ t1->data.generic_class, t2->data.generic_class, signature_only);
case MONO_TYPE_VAR:
+ return mono_metadata_generic_param_equal (
+ t1->data.generic_param, t2->data.generic_param, FALSE);
case MONO_TYPE_MVAR:
- return t1->data.generic_param->num == t2->data.generic_param->num;
+ return mono_metadata_generic_param_equal (
+ t1->data.generic_param, t2->data.generic_param, signature_only);
default:
g_error ("implement type compare for %0x!", t1->type);
return FALSE;
return FALSE;
}
-/*
+gboolean
+mono_metadata_type_equal (MonoType *t1, MonoType *t2)
+{
+ return do_mono_metadata_type_equal (t1, t2, FALSE);
+}
+
+/**
* mono_metadata_signature_equal:
* @sig1: a signature
* @sig2: another signature
sig1->param_count != sig2->param_count)
return FALSE;
+ /*
+ * We're just comparing the signatures of two methods here:
+ *
+ * If we have two generic methods `void Foo<U> (U u)' and `void Bar<V> (V v)',
+ * U and V are equal here.
+ *
+ * That's what the `signature_only' argument of do_mono_metadata_type_equal() is for.
+ */
+
for (i = 0; i < sig1->param_count; i++) {
MonoType *p1 = sig1->params[i];
MonoType *p2 = sig2->params[i];
- //if (p1->attrs != p2->attrs)
- // return FALSE;
-
- if (!mono_metadata_type_equal (p1, p2))
+ /* if (p1->attrs != p2->attrs)
+ return FALSE;
+ */
+ if (!do_mono_metadata_type_equal (p1, p2, TRUE))
return FALSE;
}
- if (!mono_metadata_type_equal (sig1->ret, sig2->ret))
+ if (!do_mono_metadata_type_equal (sig1->ret, sig2->ret, TRUE))
return FALSE;
return TRUE;
}
guint32 index = mono_metadata_token_index (token);
tdef = &meta->tables [MONO_TABLE_CONSTANT];
- index <<= HASCONSTANT_BITS;
+ index <<= MONO_HASCONSTANT_BITS;
switch (mono_metadata_token_table (token)) {
case MONO_TABLE_FIELD:
- index |= HASCONSTANT_FIEDDEF;
+ index |= MONO_HASCONSTANT_FIEDDEF;
break;
case MONO_TABLE_PARAM:
- index |= HASCONSTANT_PARAM;
+ index |= MONO_HASCONSTANT_PARAM;
break;
case MONO_TABLE_PROPERTY:
- index |= HASCONSTANT_PROPERTY;
+ index |= MONO_HASCONSTANT_PROPERTY;
break;
default:
g_warning ("Not a valid token for the constant table: 0x%08x", token);
loc.t = msemt;
loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
- loc.idx = ((index + 1) << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT; /* Method association coded index */
+ loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT; /* Method association coded index */
if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
return 0;
loc.t = msemt;
loc.col_idx = MONO_METHOD_SEMA_ASSOCIATION;
- loc.idx = ((index + 1) << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY; /* Method association coded index */
+ loc.idx = ((index + 1) << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY; /* Method association coded index */
if (!bsearch (&loc, msemt->base, msemt->rows, msemt->row_size, table_locator))
return 0;
loc.t = tdef;
loc.col_idx = MONO_IMPLMAP_MEMBER;
- loc.idx = ((method_idx + 1) << MEMBERFORWD_BITS) | MEMBERFORWD_METHODDEF;
+ loc.idx = ((method_idx + 1) << MONO_MEMBERFORWD_BITS) | MONO_MEMBERFORWD_METHODDEF;
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
return 0;
* token.
*/
MonoType *
-mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
+mono_type_create_from_typespec_full (MonoImage *image, MonoGenericContext *generic_context, guint32 type_spec)
{
guint32 idx = mono_metadata_token_index (type_spec);
MonoTableInfo *t;
ptr++;
}
- do_mono_metadata_parse_type (type, image, ptr, &ptr);
+ do_mono_metadata_parse_type (type, image, generic_context, ptr, &ptr);
mono_loader_unlock ();
return type;
}
+MonoType *
+mono_type_create_from_typespec (MonoImage *image, guint32 type_spec)
+{
+ return mono_type_create_from_typespec_full (image, NULL, type_spec);
+}
+
MonoMarshalSpec *
mono_metadata_parse_marshal_spec (MonoImage *image, const char *ptr)
{
return res;
}
+void
+mono_metadata_free_marshal_spec (MonoMarshalSpec *spec)
+{
+ if (spec->native == MONO_NATIVE_CUSTOM) {
+ g_free (spec->data.custom_data.custom_name);
+ g_free (spec->data.custom_data.cookie);
+ }
+ g_free (spec);
+}
+
guint32
mono_type_to_unmanaged (MonoType *type, MonoMarshalSpec *mspec, gboolean as_field,
gboolean unicode, MonoMarshalConv *conv)
loc.t = tdef;
loc.col_idx = MONO_FIELD_MARSHAL_PARENT;
- loc.idx = ((idx + 1) << HAS_FIELD_MARSHAL_BITS) | (is_field? HAS_FIELD_MARSHAL_FIELDSREF: HAS_FIELD_MARSHAL_PARAMDEF);
+ loc.idx = ((idx + 1) << MONO_HAS_FIELD_MARSHAL_BITS) | (is_field? MONO_HAS_FIELD_MARSHAL_FIELDSREF: MONO_HAS_FIELD_MARSHAL_PARAMDEF);
if (!bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator))
return NULL;
static MonoMethod*
method_from_method_def_or_ref (MonoImage *m, guint32 tok)
{
- guint32 idx = tok >> METHODDEFORREF_BITS;
- switch (tok & METHODDEFORREF_MASK) {
- case METHODDEFORREF_METHODDEF:
+ guint32 idx = tok >> MONO_METHODDEFORREF_BITS;
+ switch (tok & MONO_METHODDEFORREF_MASK) {
+ case MONO_METHODDEFORREF_METHODDEF:
return mono_get_method (m, MONO_TOKEN_METHOD_DEF | idx, NULL);
- case METHODDEFORREF_METHODREF:
+ case MONO_METHODDEFORREF_METHODREF:
return mono_get_method (m, MONO_TOKEN_MEMBER_REF | idx, NULL);
}
g_assert_not_reached ();
}
static MonoClass**
-get_constraints (MonoImage *image, int owner)
+get_constraints (MonoImage *image, int owner, MonoGenericContext *context)
{
MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
guint32 cols [MONO_GENPARCONSTRAINT_SIZE];
mono_metadata_decode_row (tdef, i, cols, MONO_GENPARCONSTRAINT_SIZE);
if (cols [MONO_GENPARCONSTRAINT_GENERICPAR] == owner) {
token = mono_metadata_token_from_dor (cols [MONO_GENPARCONSTRAINT_CONSTRAINT]);
- klass = mono_class_get (image, token);
+ klass = mono_class_get_full (image, token, context);
cons = g_list_append (cons, klass);
++found;
} else {
return res;
}
-MonoGenericParam *
-mono_metadata_load_generic_params (MonoImage *image, guint32 token, guint32 *num)
+MonoGenericContainer *
+mono_metadata_load_generic_params (MonoImage *image, guint32 token, MonoGenericContainer *parent_container)
{
MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM];
guint32 cols [MONO_GENERICPARAM_SIZE];
- guint32 i, owner, last_num, n;
+ guint32 i, owner = 0, last_num, n;
+ MonoGenericContainer *container;
+ MonoGenericClass *gclass;
MonoGenericParam *params;
if (mono_metadata_token_table (token) == MONO_TABLE_TYPEDEF)
owner = MONO_TYPEORMETHOD_METHOD;
else {
g_error ("wrong token %x to load_generics_params", token);
+ return NULL;
}
owner |= mono_metadata_token_index (token) << MONO_TYPEORMETHOD_BITS;
- if (num)
- *num = 0;
if (!tdef->base)
return NULL;
if (cols [MONO_GENERICPARAM_OWNER] == owner)
break;
}
- last_num = 0;
+ last_num = i;
if (i >= tdef->rows)
return NULL;
params = NULL;
n = 0;
+ container = g_new0 (MonoGenericContainer, 1);
do {
n++;
params = g_realloc (params, sizeof (MonoGenericParam) * n);
+ params [n - 1].owner = container;
params [n - 1].pklass = NULL;
params [n - 1].method = NULL;
params [n - 1].flags = cols [MONO_GENERICPARAM_FLAGS];
params [n - 1].num = cols [MONO_GENERICPARAM_NUMBER];
params [n - 1].name = mono_metadata_string_heap (image, cols [MONO_GENERICPARAM_NAME]);
- params [n - 1].constraints = get_constraints (image, i + 1);
if (++i >= tdef->rows)
break;
mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE);
} while (cols [MONO_GENERICPARAM_OWNER] == owner);
-
- if (num)
- *num = n;
- return params;
+
+ container->type_argc = n;
+ container->type_params = params;
+ container->parent = parent_container;
+
+ if (mono_metadata_token_table (token) == MONO_TABLE_METHOD)
+ container->is_method = 1;
+
+ container->context.container = container;
+
+ for (i = 0; i < n; i++)
+ params [i].constraints = get_constraints (image, last_num + i + 1, &container->context);
+
+ return container;
+}
+
+gboolean
+mono_type_is_byref (MonoType *type)
+{
+ return type->byref;
+}
+
+int
+mono_type_get_type (MonoType *type)
+{
+ return type->type;
+}
+
+/* For MONO_TYPE_FNPTR */
+MonoMethodSignature*
+mono_type_get_signature (MonoType *type)
+{
+ return type->data.method;
+}
+
+/* For MONO_TYPE_CLASS, VALUETYPE */
+MonoClass*
+mono_type_get_class (MonoType *type)
+{
+ return type->data.klass;
+}
+
+/* For MONO_TYPE_ARRAY */
+MonoArrayType*
+mono_type_get_array_type (MonoType *type)
+{
+ return type->data.array;
+}
+
+MonoClass*
+mono_type_get_modifiers (MonoType *type, gboolean *is_required, gpointer *iter)
+{
+ /* FIXME: implement */
+ return NULL;
+}
+
+MonoType*
+mono_signature_get_return_type (MonoMethodSignature *sig)
+{
+ return sig->ret;
+}
+
+MonoType*
+mono_signature_get_params (MonoMethodSignature *sig, gpointer *iter)
+{
+ MonoType** type;
+ if (!iter)
+ return NULL;
+ if (!*iter) {
+ /* start from the first */
+ if (sig->param_count) {
+ *iter = &sig->params [0];
+ return sig->params [0];
+ } else {
+ /* no method */
+ return NULL;
+ }
+ }
+ type = *iter;
+ type++;
+ if (type < &sig->params [sig->param_count]) {
+ *iter = type;
+ return *type;
+ }
+ return NULL;
+}
+
+guint32
+mono_signature_get_param_count (MonoMethodSignature *sig)
+{
+ return sig->param_count;
+}
+
+guint32
+mono_signature_get_call_conv (MonoMethodSignature *sig)
+{
+ return sig->call_convention;
+}
+
+int
+mono_signature_vararg_start (MonoMethodSignature *sig)
+{
+ return sig->sentinelpos;
+}
+
+gboolean
+mono_signature_is_instance (MonoMethodSignature *sig)
+{
+ return sig->hasthis;
+}
+
+gboolean
+mono_signature_explicit_this (MonoMethodSignature *sig)
+{
+ return sig->explicit_this;
}