2004-07-12 Martin Baulig <martin@ximian.com>
[mono.git] / mono / metadata / reflection.c
index 9d66ba0e33830c80ba1e648ca657f99abf3c07e1..3238759cad6d046d8527745af7f117bfb758bc27 100644 (file)
@@ -138,6 +138,7 @@ static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, Mon
 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
+static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
 static void    ensure_runtime_vtable (MonoClass *klass);
 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
@@ -1205,9 +1206,9 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly
                                        name = mono_string_to_utf8 (pb->name);
                                        values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
                                        g_free (name);
-                               }
-                               else
+                               } else {
                                        values [MONO_PARAM_NAME] = 0;
+                               }
                                values += MONO_PARAM_SIZE;
                                if (pb->marshal_info) {
                                        mtable->rows++;
@@ -1217,6 +1218,17 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly
                                        mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
                                }
                                pb->table_idx = table->next_idx++;
+                               if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
+                                       guint32 field_type = 0;
+                                       mtable = &assembly->tables [MONO_TABLE_CONSTANT];
+                                       mtable->rows ++;
+                                       alloc_table (mtable, mtable->rows);
+                                       mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
+                                       mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
+                                       mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
+                                       mvalues [MONO_CONSTANT_TYPE] = field_type;
+                                       mvalues [MONO_CONSTANT_PADDING] = 0;
+                               }
                        }
                }
        }
@@ -2343,7 +2355,7 @@ encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmetho
        /*
         * FIXME: vararg, explicit_this, differenc call_conv values...
         */
-       mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
+       mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
        mono_metadata_encode_value (nparams, p, &p);
 
        for (i = 0; i < nparams; i++)
@@ -3123,6 +3135,16 @@ compare_nested (const void *a, const void *b)
        return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
 }
 
+static void
+pad_heap (MonoDynamicStream *sh)
+{
+       if (sh->index & 3) {
+               int sz = 4 - (sh->index & 3);
+               memset (sh->data + sh->index, 0, sz);
+               sh->index += sz;
+       }
+}
+
 /*
  * build_compressed_metadata() fills in the blob of data that represents the 
  * raw metadata as it will be saved in the PE file. The five streams are output 
@@ -3168,7 +3190,13 @@ build_compressed_metadata (MonoDynamicImage *assembly)
        /* Compute table sizes */
        /* the MonoImage has already been created in mono_image_basic_init() */
        meta = &assembly->image;
-       
+
+       /* sizes should be multiple of 4 */
+       pad_heap (&assembly->blob);
+       pad_heap (&assembly->guid);
+       pad_heap (&assembly->sheap);
+       pad_heap (&assembly->us);
+
        /* Setup the info used by compute_sizes () */
        meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
        meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
@@ -3193,6 +3221,9 @@ build_compressed_metadata (MonoDynamicImage *assembly)
        }
        heapt_size += 24; /* #~ header size */
        heapt_size += ntables * 4;
+       /* make multiple of 4 */
+       heapt_size += 3;
+       heapt_size &= ~3;
        meta_size += heapt_size;
        meta->raw_metadata = g_malloc0 (meta_size);
        p = meta->raw_metadata;
@@ -4558,23 +4589,25 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
        size &= ~(VIRT_ALIGN - 1);
        header->nt.pe_image_size = GUINT32_FROM_LE (size);
 
-       //
+       /*
        // Translate the PEFileKind value to the value expected by the Windows loader
-       //
+       */
        {
-               short kind = assemblyb->pekind;
+               short kind;
 
-               //
+               /*
+               // PEFileKinds.Dll == 1
                // PEFileKinds.ConsoleApplication == 2
                // PEFileKinds.WindowApplication == 3
                //
                // need to get:
                //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
-               if (kind == 2)
-                       kind = 3;
-               else if (kind == 3)
+               */
+               if (assemblyb->pekind == 3)
                        kind = 2;
+               else
+                       kind = 3;
                
                header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
        }    
@@ -4846,7 +4879,7 @@ mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
                 * we don't know which module it belongs to, since that is only 
                 * determined at assembly save time.
                 */
-               //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
+               /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
                image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
 
                moduleb->module.image = &image->image;
@@ -4929,7 +4962,7 @@ mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_ind
        res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
        name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
 
-       // Check whenever the row has a corresponding row in the moduleref table
+       /* Check whenever the row has a corresponding row in the moduleref table */
        table = &image->tables [MONO_TABLE_MODULEREF];
        for (i = 0; i < table->rows; ++i) {
                name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
@@ -5084,7 +5117,7 @@ mono_type_get_object (MonoDomain *domain, MonoType *type)
                return res;
        }
        if (klass->reflection_info && !klass->wastypebuilder) {
-               //g_assert_not_reached ();
+               /* g_assert_not_reached (); */
                /* should this be considered an error condition? */
                if (!type->byref) {
                        mono_domain_unlock (domain);
@@ -5157,7 +5190,10 @@ mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *fie
        res->klass = klass;
        res->field = field;
        res->name = mono_string_new (domain, field->name);
-       res->attrs = field->type->attrs;
+       if (field->generic_info)
+               res->attrs = field->generic_info->generic_type->attrs;
+       else
+               res->attrs = field->type->attrs;
        res->type = mono_type_get_object (domain, field->type);
        CACHE_OBJECT (field, res, klass);
        return res;
@@ -5326,7 +5362,7 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
                                len = (p - start + 1);
                                if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
                                        len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
-                               g_strlcpy (assembly->public_key_token, p, len);
+                               g_strlcpy (assembly->public_key_token, start, len);
                        }
                } else {
                        while (*p && *p != ',')
@@ -5558,7 +5594,7 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
        if (!mono_domain_has_type_resolve (mono_domain_get ()))
                return NULL;
        
-       // Reconstruct the type name
+       /* Reconstruct the type name */
        fullName = g_string_new ("");
        if (info->name_space && (info->name_space [0] != '\0'))
                g_string_printf (fullName, "%s.%s", info->name_space, info->name);
@@ -5997,11 +6033,11 @@ create_custom_attr (MonoImage *image, MonoMethod *method,
                        type_name [type_len] = 0;
                        named += type_len;
                        /* FIXME: lookup the type and check type consistency */
+               } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
+                       /* this seems to be the type of the element of the array */
+                       /* g_print ("skipping 0x%02x after prop\n", *named); */
+                       named++;
                }
-               else
-                       if (data_type == MONO_TYPE_SZARRAY)
-                               /* The spec does not mention this */
-                               named ++;
                name_len = mono_metadata_decode_blob_size (named, &named);
                name = g_malloc (name_len + 1);
                memcpy (name, named, name_len);
@@ -6010,9 +6046,9 @@ create_custom_attr (MonoImage *image, MonoMethod *method,
                if (named_type == 0x53) {
                        MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
                        void *val = load_cattr_value (image, field->type, named, &named);
-                               mono_field_set_value (attr, field, val);
-                               if (!type_is_reference (field->type))
-                                       g_free (val);
+                       mono_field_set_value (attr, field, val);
+                       if (!type_is_reference (field->type))
+                               g_free (val);
                } else if (named_type == 0x54) {
                        MonoProperty *prop;
                        void *pparams [1];
@@ -6223,7 +6259,7 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
 
        if (method->klass->generic_inst || method->klass->gen_params ||
            method->signature->generic_param_count) {
-               // FIXME FIXME FIXME
+               /* FIXME FIXME FIXME */
                return NULL;
        }
 
@@ -6399,10 +6435,21 @@ get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
        }
 }
 
+/*
+ * Encode a value in a custom attribute stream of bytes.
+ * The value to encode is either supplied as an object in argument val
+ * (valuetypes are boxed), or as a pointer to the data in the
+ * argument argval.
+ * @type represents the type of the value
+ * @buffer is the start of the buffer
+ * @p the current position in the buffer
+ * @buflen contains the size of the buffer and is used to return the new buffer size
+ * if this needs to be realloced.
+ * @retbuffer and @retp return the start and the position of the buffer
+ */
 static void
-encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
+encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
 {
-       char *argval;
        MonoTypeEnum simple_type;
        
        if ((p-buffer) + 10 >= *buflen) {
@@ -6412,7 +6459,8 @@ encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuf
                p = newbuf + (p-buffer);
                buffer = newbuf;
        }
-       argval = ((char*)arg + sizeof (MonoObject));
+       if (!argval)
+               argval = ((char*)arg + sizeof (MonoObject));
        simple_type = type->type;
 handle_enum:
        switch (simple_type) {
@@ -6501,7 +6549,7 @@ handle_type:
        }
        case MONO_TYPE_SZARRAY: {
                int len, i;
-               MonoClass *eclass;
+               MonoClass *eclass, *arg_eclass;
 
                if (!arg) {
                        *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
@@ -6515,8 +6563,18 @@ handle_type:
                *retp = p;
                *retbuffer = buffer;
                eclass = type->data.klass;
-               for (i = 0; i < len; ++i) {
-                       encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
+               arg_eclass = mono_object_class (arg)->element_class;
+               if (eclass->valuetype && arg_eclass->valuetype) {
+                       char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
+                       int elsize = mono_class_array_element_size (eclass);
+                       for (i = 0; i < len; ++i) {
+                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
+                               elptr += elsize;
+                       }
+               } else {
+                       for (i = 0; i < len; ++i) {
+                               encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
+                       }
                }
                break;
        }
@@ -6602,7 +6660,7 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
        *p++ = 0;
        for (i = 0; i < sig->param_count; ++i) {
                arg = mono_array_get (ctorArgs, MonoObject*, i);
-               encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
+               encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
        }
        i = 0;
        if (properties)
@@ -6663,7 +6721,7 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
                        mono_metadata_encode_value (len, p, &p);
                        memcpy (p, pname, len);
                        p += len;
-                       encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
+                       encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
                        g_free (pname);
                }
        }
@@ -6700,12 +6758,14 @@ mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObj
                                g_free (str);
                        } else {
                                mono_metadata_encode_value (ftype->type, p, &p);
+                               if (ftype->type == MONO_TYPE_SZARRAY)
+                                       mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
                        }
                        len = strlen (fname);
                        mono_metadata_encode_value (len, p, &p);
                        memcpy (p, fname, len);
                        p += len;
-                       encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
+                       encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
                        g_free (fname);
                }
        }
@@ -6736,10 +6796,6 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
 
        MONO_ARCH_SAVE_REGS;
 
-       klass = g_new0 (MonoClass, 1);
-
-       klass->image = &tb->module->dynamic_image->image;
-
        if (tb->parent) {
                /* check so we can compile corlib correctly */
                if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
@@ -6750,6 +6806,21 @@ mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
        } else
                parent = NULL;
        
+       /* the type has already being created: it means we just have to change the parent */
+       if (tb->type.type) {
+               klass = mono_class_from_mono_type (tb->type.type);
+               klass->parent = NULL;
+               /* fool mono_class_setup_parent */
+               g_free (klass->supertypes);
+               klass->supertypes = NULL;
+               mono_class_setup_parent (klass, parent);
+               return;
+       }
+       
+       klass = g_new0 (MonoClass, 1);
+
+       klass->image = &tb->module->dynamic_image->image;
+
        klass->inited = 1; /* we lie to the runtime */
        klass->name = mono_string_to_utf8 (tb->name);
        klass->name_space = mono_string_to_utf8 (tb->nspace);
@@ -7138,14 +7209,13 @@ fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder*
        if (fb->def_value) {
                MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
                field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
-               field->def_value = g_new0 (MonoConstant, 1);
-               idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
+               idx = encode_constant (assembly, fb->def_value, &field->def_type);
                /* Copy the data from the blob since it might get realloc-ed */
                p = assembly->blob.data + idx;
                len = mono_metadata_decode_blob_size (p, &p2);
                len += p2 - p;
-               field->def_value->value = g_malloc (len);
-               memcpy (field->def_value->value, p, len);
+               field->data = g_malloc (len);
+               memcpy (field->data, p, len);
        }
 
        return field;
@@ -7640,14 +7710,13 @@ typebuilder_setup_fields (MonoClass *klass)
                if (fb->def_value) {
                        MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
                        field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
-                       field->def_value = g_new0 (MonoConstant, 1);
-                       idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
+                       idx = encode_constant (assembly, fb->def_value, &field->def_type);
                        /* Copy the data from the blob since it might get realloc-ed */
                        p = assembly->blob.data + idx;
                        len = mono_metadata_decode_blob_size (p, &p2);
                        len += p2 - p;
-                       field->def_value->value = g_malloc (len);
-                       memcpy (field->def_value->value, p, len);
+                       field->data = g_malloc (len);
+                       memcpy (field->data, p, len);
                }
        }
        mono_class_layout_fields (klass);