#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"
/* soon to be removed */
{ MONO_MT_TABLE_IDX, "Kind" },
- { MONO_MT_TABLE_IDX, "DeprecatedConstraint" },
{ MONO_MT_END, NULL }
};
mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs, const char *ptr, const char **rptr)
{
MonoType *type, *cached;
+ gboolean byref = FALSE;
+ gboolean pinned = FALSE;
+ const char *tmp_ptr;
+ int count = 0;
+ gboolean found;
- 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++;
+ /*
+ * According to the spec, custom modifiers should come before the byref
+ * flag, but the IL produced by ilasm from the following signature:
+ * object modopt(...) &
+ * starts with a byref flag, followed by the modifiers. (bug #49802)
+ * 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).
+ */
+
+ /* 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:
+
+ 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");
+ }
+ else
/*
* Later we can avoid doing this allocation.
*/
type = g_new0 (MonoType, 1);
- break;
- default:
- g_assert_not_reached ();
- }
-
- type->attrs = opt_attrs;
- if (mode == MONO_PARSE_LOCAL) {
- /*
- * check for pinned flag
- */
- if (*ptr == MONO_TYPE_PINNED) {
- type->pinned = 1;
+
+ /* 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:
+ count ++;
+ mono_metadata_parse_custom_mod (m, &(type->modifiers [count]), ptr, &ptr);
+ break;
+ default:
+ found = FALSE;
}
}
+
+ type->attrs = opt_attrs;
+ type->byref = byref;
+ type->pinned = pinned ? 1 : 0;
+
+ do_mono_metadata_parse_type (type, m, 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;
guint32 sig;
const char *ptr;
- if (image->assembly->dynamic)
+ if (image->dynamic)
return mono_lookup_dynamic_token (image, token);
g_assert (mono_metadata_token_table(token) == MONO_TABLE_STANDALONESIG);
/* 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
method->params [i] = mono_metadata_parse_type (m, MONO_PARSE_PARAM, pattrs [i], ptr, &ptr);
}
}
+
+ if (def && (method->call_convention == MONO_CALL_VARARG))
+ method->sentinelpos = method->param_count;
+
g_free (pattrs);
if (rptr)
g_free (sig);
}
-static MonoGenericInst *
-mono_metadata_parse_generic_inst (MonoImage *m, const char *ptr, const char **rptr)
+static void
+do_mono_metadata_parse_generic_inst (MonoType *type, MonoImage *m, const char *ptr, const char **rptr)
{
- MonoGenericInst *generic_inst = g_new0 (MonoGenericInst, 1);
+ MonoGenericInst *ginst = g_new0 (MonoGenericInst, 1);
+ MonoType *cached;
int i, count;
-
- generic_inst->generic_type = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
- generic_inst->type_argc = count = mono_metadata_decode_value (ptr, &ptr);
- generic_inst->type_argv = g_new0 (MonoType*, count);
- for (i = 0; i < generic_inst->type_argc; i++)
- generic_inst->type_argv [i] = mono_metadata_parse_type (m, MONO_PARSE_TYPE, 0, ptr, &ptr);
-
+ type->data.generic_inst = ginst;
+
+ ginst->context = g_new0 (MonoGenericContext, 1);
+ ginst->context->ginst = ginst;
+
+ ginst->klass = g_new0 (MonoClass, 1);
+
+ 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);
+
+ /*
+ * Create the klass before parsing the type arguments.
+ * This is required to support "recursive" definitions.
+ * See mcs/tests/gen-23.cs for an example.
+ */
+
+ ginst->init_pending = TRUE;
+
+ mono_class_create_generic (ginst);
+
+ for (i = 0; i < ginst->type_argc; i++) {
+ MonoType *t = mono_metadata_parse_type (m, 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 generic_inst;
+ /*
+ * We may be called multiple times on different metadata to create the same
+ * 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
+ * instantiation of a generic type (ie "Stack<Int32>") to make static fields
+ * work.
+ *
+ * According to the spec ($26.1.5), a static variable in a generic class
+ * declaration is shared amongst all instances of the same closed constructed
+ * type.
+ */
+
+ cached = g_hash_table_lookup (m->generic_inst_cache, ginst);
+ if (cached) {
+ g_free (ginst->klass);
+ g_free (ginst->type_argv);
+ g_free (ginst);
+
+ type->data.generic_inst = cached->data.generic_inst;
+ 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);
+
+ mono_stats.generic_instance_count++;
+ mono_stats.generics_metadata_size += sizeof (MonoGenericInst) +
+ sizeof (MonoGenericContext) +
+ ginst->type_argc * sizeof (MonoType);
+ }
+
+ ginst->init_pending = FALSE;
}
static MonoGenericParam *
case MONO_TYPE_SZARRAY: {
MonoType *etype = mono_metadata_parse_type (m, 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:
break;
case MONO_TYPE_GENERICINST:
- type->data.generic_inst = mono_metadata_parse_generic_inst (m, ptr, &ptr);
+ do_mono_metadata_parse_generic_inst (type, m, ptr, &ptr);
break;
default:
guint32 result;
} locator_t;
-#define CSIZE(x) (sizeof (x) / 4)
-
/*
* How the row locator works.
*
case MONO_TYPE_TYPEDBYREF:
return mono_class_value_size (mono_defaults.typed_reference_class, align);
case MONO_TYPE_GENERICINST: {
- MonoClass *iclass = mono_class_from_mono_type (t);
+ MonoGenericInst *ginst = t->data.generic_inst;
+ MonoClass *iclass = mono_class_from_mono_type (ginst->generic_type);
return mono_type_size (&iclass->byval_arg, align);
}
case MONO_TYPE_VAR:
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: {
- MonoClass *iclass = mono_class_from_mono_type (t);
+ 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);
}
default:
return 0;
}
+guint
+mono_metadata_generic_inst_hash (MonoGenericInst *ginst)
+{
+ return mono_metadata_type_hash (ginst->generic_type);
+}
+
+gboolean
+mono_metadata_generic_inst_equal (MonoGenericInst *g1, MonoGenericInst *g2)
+{
+ int i;
+
+ if (g1->type_argc != g2->type_argc)
+ return FALSE;
+ if (!mono_metadata_type_equal (g1->generic_type, g2->generic_type))
+ return FALSE;
+ for (i = 0; i < g1->type_argc; ++i) {
+ if (!mono_metadata_type_equal (g1->type_argv [i], g2->type_argv [i]))
+ return FALSE;
+ }
+ return TRUE;
+}
+
/*
* 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_type_hash (t1->data.generic_inst->generic_type);
+ return ((hash << 5) - hash) ^ mono_metadata_generic_inst_hash (t1->data.generic_inst);
}
return hash;
}
+static gboolean
+mono_metadata_class_equal (MonoClass *c1, MonoClass *c2)
+{
+ 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->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;
+ 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 FALSE;
+}
+
/*
* mono_metadata_type_equal:
* @t1: a type
case MONO_TYPE_VALUETYPE:
case MONO_TYPE_CLASS:
case MONO_TYPE_SZARRAY:
- return t1->data.klass == t2->data.klass;
+ return mono_metadata_class_equal (t1->data.klass, t2->data.klass);
case MONO_TYPE_PTR:
return mono_metadata_type_equal (t1->data.type, t2->data.type);
case MONO_TYPE_ARRAY:
if (t1->data.array->rank != t2->data.array->rank)
return FALSE;
- return t1->data.array->eklass == t2->data.array->eklass;
- case MONO_TYPE_GENERICINST: {
- int i;
- if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
- return FALSE;
- if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
- return FALSE;
- for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
- if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
- return FALSE;
- }
- return TRUE;
- }
+ return mono_metadata_class_equal (t1->data.array->eklass, t2->data.array->eklass);
+ case MONO_TYPE_GENERICINST:
+ return mono_metadata_generic_inst_equal (t1->data.generic_inst,
+ t2->data.generic_inst);
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
- return t1->data.generic_param == t2->data.generic_param;
+ return t1->data.generic_param->num == t2->data.generic_param->num;
default:
g_error ("implement type compare for %0x!", t1->type);
return FALSE;
MonoType *p1 = sig1->params[i];
MonoType *p2 = sig2->params[i];
- //if (p1->attrs != p2->attrs)
- // return FALSE;
-
+ /* if (p1->attrs != p2->attrs)
+ return FALSE;
+ */
if (!mono_metadata_type_equal (p1, p2))
return FALSE;
}
{
char *p = buf;
- if (value <= 127)
+ if (value < 0x80)
*p++ = value;
- else if (value <= 16384) {
+ else if (value < 0x4000) {
p [0] = 0x80 | (value >> 8);
p [1] = value & 0xff;
p += 2;
* mono_metadata_get_constant_index:
* @meta: the Image the field is defined in
* @index: the token that may have a row defined in the constants table
+ * @hint: possible position for the row
*
* @token must be a FieldDef, ParamDef or PropertyDef token.
*
- * Returns: the index into the Constsnts table or 0 if not found.
+ * Returns: the index into the Constants table or 0 if not found.
*/
guint32
-mono_metadata_get_constant_index (MonoImage *meta, guint32 token)
+mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
{
MonoTableInfo *tdef;
locator_t loc;
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.col_idx = MONO_CONSTANT_PARENT;
loc.t = tdef;
+ if ((hint > 0) && (hint < tdef->rows) && (mono_metadata_decode_row_col (tdef, hint - 1, MONO_CONSTANT_PARENT) == index))
+ return hint;
+
if (tdef->base && bsearch (&loc, tdef->base, tdef->rows, tdef->row_size, table_locator)) {
return loc.result + 1;
}
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;
guint32 len;
MonoType *type;
+ mono_loader_lock ();
+
+ if ((type = g_hash_table_lookup (image->typespec_cache, GUINT_TO_POINTER (type_spec)))) {
+ mono_loader_unlock ();
+ return type;
+ }
+
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);
+
+ type = g_new0 (MonoType, 1);
+
+ g_hash_table_insert (image->typespec_cache, GUINT_TO_POINTER (type_spec), type);
+
+ if (*ptr == MONO_TYPE_BYREF) {
+ type->byref = 1;
+ ptr++;
+ }
+
+ do_mono_metadata_parse_type (type, image, ptr, &ptr);
+
+ mono_loader_unlock ();
return type;
}
case MONO_NATIVE_IUNKNOWN:
*conv = MONO_MARSHAL_CONV_OBJECT_IUNKNOWN;
return MONO_NATIVE_IUNKNOWN;
+ case MONO_NATIVE_FUNC:
+ if (t == MONO_TYPE_CLASS && (type->data.klass == mono_defaults.multicastdelegate_class ||
+ type->data.klass == mono_defaults.delegate_class ||
+ type->data.klass->parent == mono_defaults.multicastdelegate_class)) {
+ *conv = MONO_MARSHAL_CONV_DEL_FTN;
+ return MONO_NATIVE_FUNC;
+ }
+ else
+ /* Fall through */
+ ;
default:
g_error ("cant marshal object as native type %02x", mspec->native);
}
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 ();
}
MonoGenericParam *
-mono_metadata_load_generic_params (MonoImage *image, guint32 token, guint32 *num, MonoMethod *method)
+mono_metadata_load_generic_params (MonoImage *image, guint32 token, guint32 *num)
{
MonoTableInfo *tdef = &image->tables [MONO_TABLE_GENERICPARAM];
guint32 cols [MONO_GENERICPARAM_SIZE];
if (i >= tdef->rows)
return NULL;
params = NULL;
- n = 1;
+ n = 0;
do {
+ n++;
params = g_realloc (params, sizeof (MonoGenericParam) * n);
params [n - 1].pklass = NULL;
- params [n - 1].method = method;
+ 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]);
if (++i >= tdef->rows)
break;
mono_metadata_decode_row (tdef, i, cols, MONO_GENERICPARAM_SIZE);
- n++;
} while (cols [MONO_GENERICPARAM_OWNER] == owner);
if (num)
return params;
}
+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;
+}
+