This commit was manufactured by cvs2svn to create branch 'mono-1-0'.
[mono.git] / mono / metadata / metadata.c
index b7049786083a3a0b33bbc1bdc8072705554ba448..3d44463cde90be1fab9068944735fdeb6b6dd1ab 100644 (file)
@@ -17,6 +17,8 @@
 #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"
 
@@ -1201,6 +1203,10 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
 {
        MonoType *type, *cached;
        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
@@ -1210,70 +1216,70 @@ mono_metadata_parse_type (MonoImage *m, MonoParseTypeMode mode, short opt_attrs,
         * 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;
+               case MONO_TYPE_CMOD_REQD:
+               case MONO_TYPE_CMOD_OPT:
+                       count ++;
+                       mono_metadata_parse_custom_mod (m, NULL, tmp_ptr, &tmp_ptr);
                        break;
-               } /* fall through */
+               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 ();
+
+       /* 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;
-       if (mode == MONO_PARSE_LOCAL) {
-               /*
-                * check for pinned flag
-                */
-               if (*ptr == MONO_TYPE_PINNED) {
-                       type->pinned = 1;
-                       ++ptr;
-               }
-       }
+       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;
 
@@ -1324,10 +1330,20 @@ mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)
        /* 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
@@ -1399,6 +1415,10 @@ mono_metadata_parse_method_signature (MonoImage *m, int def, const char *ptr, co
                        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)
@@ -1566,6 +1586,7 @@ do_mono_metadata_parse_type (MonoType *type, MonoImage *m, const char *ptr, cons
        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:
@@ -2405,7 +2426,7 @@ mono_type_stack_size (MonoType *t, gint *align)
                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);          
@@ -2589,9 +2610,9 @@ mono_metadata_signature_equal (MonoMethodSignature *sig1, MonoMethodSignature *s
                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;
        }
@@ -2627,9 +2648,9 @@ mono_metadata_encode_value (guint32 value, char *buf, char **endbuf)
 {
        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;
@@ -2723,16 +2744,16 @@ mono_metadata_get_constant_index (MonoImage *meta, guint32 token, guint32 hint)
        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);
@@ -2813,7 +2834,7 @@ mono_metadata_methods_from_event   (MonoImage *meta, guint32 index, guint *end_i
 
        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;
@@ -2901,7 +2922,7 @@ mono_metadata_methods_from_property   (MonoImage *meta, guint32 index, guint *en
 
        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;
@@ -2938,7 +2959,7 @@ mono_metadata_implmap_from_method (MonoImage *meta, guint32 method_idx)
 
        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;
@@ -3168,6 +3189,16 @@ handle_enum:
                        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);
                        }
@@ -3200,7 +3231,7 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
 
        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;
@@ -3211,11 +3242,11 @@ mono_metadata_get_marshal_info (MonoImage *meta, guint32 idx, gboolean is_field)
 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 ();
@@ -3375,3 +3406,104 @@ mono_metadata_load_generic_params (MonoImage *image, guint32 token, guint32 *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;
+}
+