2004-05-11 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / reflection.c
index e02ea46253f278ff8167bf82f6fde417fd23bbe9..d7c958f1bd2442d782558548316f59bfe94b7882 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * reflection.c: Routines for creating an image at runtime.
  * 
@@ -50,7 +49,14 @@ typedef struct {
        MonoObject *type;
        MonoString *name;
        MonoBoolean init_locals;
+       MonoArray *return_modreq;
+       MonoArray *return_modopt;
+       MonoArray *param_modreq;
+       MonoArray *param_modopt;
+       MonoArray *permissions;
        MonoMethod *mhandle;
+       guint32 nrefs;
+       gpointer *refs;
 } ReflectionMethodBuilder;
 
 const unsigned char table_sizes [64] = {
@@ -130,6 +136,10 @@ static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gp
 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
 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);
+static void    encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
+static guint32 type_get_signature_size (MonoType *type);
+
 
 static void
 alloc_table (MonoDynamicTable *table, guint nrows)
@@ -300,6 +310,75 @@ add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int
        return idx;
 }
 
+/*
+ * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
+ * dest may be misaligned.
+ */
+static void
+swap_with_size (char *dest, const char* val, int len, int nelem) {
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+       int elem;
+
+       for (elem = 0; elem < nelem; ++elem) {
+               switch (len) {
+               case 1:
+                       *dest = *val;
+                       break;
+               case 2:
+                       dest [0] = val [1];
+                       dest [1] = val [0];
+                       break;
+               case 4:
+                       dest [0] = val [3];
+                       dest [1] = val [2];
+                       dest [2] = val [1];
+                       dest [3] = val [0];
+                       break;
+               case 8:
+                       dest [0] = val [7];
+                       dest [1] = val [6];
+                       dest [2] = val [5];
+                       dest [3] = val [4];
+                       dest [4] = val [3];
+                       dest [5] = val [2];
+                       dest [6] = val [1];
+                       dest [7] = val [0];
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+               dest += len;
+               val += len;
+       }
+#else
+       memcpy (dest, val, len * nelem);
+#endif
+}
+
+static guint32
+add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
+{
+       char blob_size [64];
+       char *b = blob_size;
+       guint32 idx = 0, len;
+
+       len = str->length * 2;
+       mono_metadata_encode_value (len, b, &b);
+#if G_BYTE_ORDER != G_LITTLE_ENDIAN
+       {
+               char *swapped = g_malloc (2 * mono_string_length (str));
+               const char *p = (const char*)mono_string_chars (str);
+
+               swap_with_size (swapped, p, 2, mono_string_length (str));
+               idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
+               g_free (swapped);
+       }
+#else
+       idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
+#endif
+       return idx;
+}
+
 /* modified version needed to handle building corlib */
 static MonoClass*
 my_mono_class_from_mono_type (MonoType *type) {
@@ -319,6 +398,25 @@ my_mono_class_from_mono_type (MonoType *type) {
        }
 }
 
+static void
+encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
+{
+       int i;
+
+       if (!ginst) {
+               g_assert_not_reached ();
+               return;
+       }
+
+       mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
+       encode_type (assembly, ginst->generic_type, p, &p);
+       mono_metadata_encode_value (ginst->type_argc, p, &p);
+       for (i = 0; i < ginst->type_argc; ++i)
+               encode_type (assembly, ginst->type_argv [i], p, &p);
+
+       *endbuf = p;
+}
+
 static void
 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
 {
@@ -380,16 +478,9 @@ encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
                mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
                mono_metadata_encode_value (0, p, &p);
                break;
-       case MONO_TYPE_GENERICINST: {
-               int i;
-               mono_metadata_encode_value (type->type, p, &p);
-               encode_type (assembly, type->data.generic_inst->generic_type, p, &p);
-               mono_metadata_encode_value (type->data.generic_inst->type_argc, p, &p);
-               for (i = 0; i < type->data.generic_inst->type_argc; ++i) {
-                       encode_type (assembly, type->data.generic_inst->type_argv [i], p, &p);
-               }
+       case MONO_TYPE_GENERICINST:
+               encode_generic_inst (assembly, type->data.generic_inst, p, &p);
                break;
-       }
        case MONO_TYPE_VAR:
        case MONO_TYPE_MVAR:
                mono_metadata_encode_value (type->type, p, &p);
@@ -418,6 +509,119 @@ encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, ch
 
 }
 
+static void
+encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
+{
+       int i;
+
+       if (modreq) {
+               for (i = 0; i < mono_array_length (modreq); ++i) {
+                       MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
+                       *p = MONO_TYPE_CMOD_REQD;
+                       p++;
+                       mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
+               }
+       }
+       if (modopt) {
+               for (i = 0; i < mono_array_length (modopt); ++i) {
+                       MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
+                       *p = MONO_TYPE_CMOD_OPT;
+                       p++;
+                       mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
+               }
+       }
+       *endbuf = p;
+}
+
+static guint32
+generic_inst_get_signature_size (MonoGenericInst *ginst)
+{
+       guint32 size = 0;
+       int i;
+
+       if (!ginst) {
+               g_assert_not_reached ();
+       }
+
+       size += 1 + type_get_signature_size (ginst->generic_type);
+       size += 4;
+       for (i = 0; i < ginst->type_argc; ++i)
+               size += type_get_signature_size (ginst->type_argv [i]);
+
+       return size;
+}
+
+static guint32
+type_get_signature_size (MonoType *type)
+{
+       guint32 size = 0;
+
+       if (!type) {
+               g_assert_not_reached ();
+       }
+               
+       if (type->byref)
+               size++;
+
+       switch (type->type){
+       case MONO_TYPE_VOID:
+       case MONO_TYPE_BOOLEAN:
+       case MONO_TYPE_CHAR:
+       case MONO_TYPE_I1:
+       case MONO_TYPE_U1:
+       case MONO_TYPE_I2:
+       case MONO_TYPE_U2:
+       case MONO_TYPE_I4:
+       case MONO_TYPE_U4:
+       case MONO_TYPE_I8:
+       case MONO_TYPE_U8:
+       case MONO_TYPE_R4:
+       case MONO_TYPE_R8:
+       case MONO_TYPE_I:
+       case MONO_TYPE_U:
+       case MONO_TYPE_STRING:
+       case MONO_TYPE_OBJECT:
+       case MONO_TYPE_TYPEDBYREF:
+               return size + 1;
+       case MONO_TYPE_PTR:
+               return size + 1 + type_get_signature_size (type->data.type);
+       case MONO_TYPE_SZARRAY:
+               return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
+
+       case MONO_TYPE_VALUETYPE:
+       case MONO_TYPE_CLASS:
+               return size + 5;
+
+       case MONO_TYPE_ARRAY:
+               return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
+       case MONO_TYPE_GENERICINST:
+               return size + generic_inst_get_signature_size (type->data.generic_inst);
+       case MONO_TYPE_VAR:
+       case MONO_TYPE_MVAR:
+               return size + 5;
+
+       default:
+               g_error ("need to encode type %x", type->type);
+               return size;
+       }
+}
+
+static guint32
+method_get_signature_size (MonoMethodSignature *sig)
+{
+       guint32 size;
+       int i;
+
+       size = type_get_signature_size (sig->ret);
+       for (i = 0; i < sig->param_count; i++)
+               size += type_get_signature_size (sig->params [i]);
+
+       if (sig->generic_param_count)
+               size += 4;
+
+       return size;    
+}
+
 static guint32
 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
 {
@@ -425,7 +629,7 @@ method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
        char *p;
        int i;
        guint32 nparams =  sig->param_count;
-       guint32 size = 10 + nparams * 10;
+       guint32 size = 11 + method_get_signature_size (sig);
        guint32 idx;
        char blob_size [6];
        char *b = blob_size;
@@ -468,7 +672,7 @@ method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBui
        int i;
        guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
        guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
-       guint32 size = 11 + nparams * 10;
+       guint32 size = 21 + nparams * 20;
        guint32 idx;
        char blob_size [6];
        char *b = blob_size;
@@ -486,9 +690,19 @@ method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBui
        if (ngparams)
                mono_metadata_encode_value (ngparams, p, &p);
        mono_metadata_encode_value (nparams, p, &p);
+       encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
        encode_reflection_type (assembly, mb->rtype, p, &p);
        for (i = 0; i < nparams; ++i) {
-               MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
+               MonoArray *modreq = NULL;
+               MonoArray *modopt = NULL;
+               MonoReflectionType *pt;
+
+               if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
+                       modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
+               if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
+                       modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
+               encode_custom_modifiers (assembly, modreq, modopt, p, &p);
+               pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
                encode_reflection_type (assembly, pt, p, &p);
        }
        /* store length */
@@ -524,6 +738,10 @@ encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
        mono_metadata_encode_value (nl, p, &p);
        for (i = 0; i < nl; ++i) {
                MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
+               
+               if (lb->is_pinned)
+                       mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
+               
                encode_reflection_type (assembly, lb->type, p, &p);
        }
        g_assert (p - buf < size);
@@ -636,8 +854,14 @@ method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
                        num_exception = method_count_clauses (mb->ilgen);
        } else {
                code = mb->code;
-               if (code == NULL)
-                       mono_raise_exception (mono_get_exception_argument (NULL, "a method does not have any IL associated"));
+               if (code == NULL){
+                       char *name = mono_string_to_utf8 (mb->name);
+                       char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
+                       MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
+                       g_free (str);
+                       g_free (name);
+                       mono_raise_exception (exception);
+               }
 
                code_size = mono_array_length (code);
                max_stack = 8; /* we probably need to run a verifier on the code... */
@@ -859,6 +1083,52 @@ mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, Mo
        }
 }
 
+static void
+mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
+                                                         MonoArray *permissions)
+{
+       MonoDynamicTable *table;
+       guint32 *values;
+       guint32 count, i, idx;
+       MonoReflectionPermissionSet *perm;
+
+       if (!permissions)
+               return;
+
+       count = mono_array_length (permissions);
+       table = &assembly->tables [MONO_TABLE_DECLSECURITY];
+       table->rows += count;
+       alloc_table (table, table->rows);
+
+       for (i = 0; i < mono_array_length (permissions); ++i) {
+               perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
+
+               values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
+
+               idx = mono_metadata_token_index (parent_token);
+               idx <<= HAS_DECL_SECURITY_BITS;
+               switch (mono_metadata_token_table (parent_token)) {
+               case MONO_TABLE_TYPEDEF:
+                       idx |= HAS_DECL_SECURITY_TYPEDEF;
+                       break;
+               case MONO_TABLE_METHOD:
+                       idx |= HAS_DECL_SECURITY_METHODDEF;
+                       break;
+               case MONO_TABLE_ASSEMBLY:
+                       idx |= HAS_DECL_SECURITY_ASSEMBLY;
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+
+               values [MONO_DECL_SECURITY_ACTION] = perm->action;
+               values [MONO_DECL_SECURITY_PARENT] = idx;
+               values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
+
+               ++table->next_idx;
+       }
+}
+
 /*
  * Fill in the MethodDef and ParamDef tables for a method.
  * This is used for both normal methods and constructors.
@@ -887,6 +1157,10 @@ mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly
        table = &assembly->tables [MONO_TABLE_PARAM];
        values [MONO_METHOD_PARAMLIST] = table->next_idx;
 
+       mono_image_add_decl_security (assembly, 
+                                                                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
+                                                                 mb->permissions);
+
        if (mb->pinfo) {
                MonoDynamicTable *mtable;
                guint32 *mvalues;
@@ -945,7 +1219,14 @@ reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
        rmb->name = mb->name;
        rmb->table_idx = &mb->table_idx;
        rmb->init_locals = mb->init_locals;
+       rmb->return_modreq = mb->return_modreq;
+       rmb->return_modopt = mb->return_modopt;
+       rmb->param_modreq = mb->param_modreq;
+       rmb->param_modopt = mb->param_modopt;
+       rmb->permissions = mb->permissions;
        rmb->mhandle = mb->mhandle;
+       rmb->nrefs = 0;
+       rmb->refs = NULL;
 }
 
 static void
@@ -967,9 +1248,43 @@ reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
        rmb->name = mono_string_new (mono_domain_get (), name);
        rmb->table_idx = &mb->table_idx;
        rmb->init_locals = mb->init_locals;
+       rmb->return_modreq = NULL;
+       rmb->return_modopt = NULL;
+       rmb->param_modreq = mb->param_modreq;
+       rmb->param_modopt = mb->param_modopt;
+       rmb->permissions = mb->permissions;
        rmb->mhandle = mb->mhandle;
+       rmb->nrefs = 0;
+       rmb->refs = NULL;
 }
 
+static void
+reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
+                                                                                         MonoReflectionDynamicMethod *mb)
+{
+       rmb->ilgen = mb->ilgen;
+       rmb->rtype = mb->rtype;
+       rmb->parameters = mb->parameters;
+       rmb->generic_params = NULL;
+       rmb->pinfo = NULL;
+       rmb->attrs = mb->attrs;
+       rmb->iattrs = 0;
+       rmb->call_conv = mb->call_conv;
+       rmb->code = NULL;
+       rmb->type = NULL;
+       rmb->name = mb->name;
+       rmb->table_idx = NULL;
+       rmb->init_locals = mb->init_locals;
+       rmb->return_modreq = NULL;
+       rmb->return_modopt = NULL;
+       rmb->param_modreq = NULL;
+       rmb->param_modopt = NULL;
+       rmb->permissions = NULL;
+       rmb->mhandle = mb->mhandle;
+       rmb->nrefs = 0;
+       rmb->refs = NULL;
+}      
+
 static void
 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
 {
@@ -1057,6 +1372,38 @@ mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, Mon
        mono_image_basic_method (&rmb, assembly);
 }
 
+static char*
+type_get_fully_qualified_name (MonoType *type) {
+       char *name, *result;
+       MonoClass *klass;
+       MonoAssembly *ta;
+
+       name = mono_type_get_name (type);
+       klass = my_mono_class_from_mono_type (type);
+       ta = klass->image->assembly;
+
+       result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
+               name, ta->aname.name,
+               ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
+               ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
+               ta->aname.public_tok_value ? ta->aname.public_tok_value : "null");
+       g_free (name);
+       return result;
+}
+
+static char*
+type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
+       MonoClass *klass;
+       MonoAssembly *ta;
+
+       klass = my_mono_class_from_mono_type (type);
+       ta = klass->image->assembly;
+       if (ta == ass || klass->image == mono_defaults.corlib)
+               return mono_type_get_name (type);
+
+       return type_get_fully_qualified_name (type);
+}
+
 static guint32
 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
 {
@@ -1093,6 +1440,7 @@ field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *
        p = buf = g_malloc (64);
        
        mono_metadata_encode_value (0x06, p, &p);
+       encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
        /* encode custom attributes before the type */
        encode_reflection_type (assembly, fb->type, p, &p);
        g_assert (p-buf < 64);
@@ -1102,58 +1450,13 @@ field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *
        return idx;
 }
 
-/*
- * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
- * dest may be misaligned.
- */
-static void
-swap_with_size (char *dest, const char* val, int len, int nelem) {
-#if G_BYTE_ORDER != G_LITTLE_ENDIAN
-       int elem;
-
-       for (elem = 0; elem < nelem; ++elem) {
-               switch (len) {
-               case 1:
-                       *dest = *val;
-                       break;
-               case 2:
-                       dest [0] = val [1];
-                       dest [1] = val [0];
-                       break;
-               case 4:
-                       dest [0] = val [3];
-                       dest [1] = val [2];
-                       dest [2] = val [1];
-                       dest [3] = val [0];
-                       break;
-               case 8:
-                       dest [0] = val [7];
-                       dest [1] = val [6];
-                       dest [2] = val [5];
-                       dest [3] = val [4];
-                       dest [4] = val [3];
-                       dest [5] = val [2];
-                       dest [6] = val [1];
-                       dest [7] = val [0];
-                       break;
-               default:
-                       g_assert_not_reached ();
-               }
-               dest += len;
-               val += len;
-       }
-#else
-       memcpy (dest, val, len * nelem);
-#endif
-}
-
 static guint32
 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
        char blob_size [64];
        char *b = blob_size;
        char *p, *box_val;
        char* buf;
-       guint32 idx, len, dummy = 0;
+       guint32 idx = 0, len = 0, dummy = 0;
        
        p = buf = g_malloc (64);
        if (!val) {
@@ -1248,7 +1551,16 @@ encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
                mono_metadata_encode_value (minfo->type, p, &p);
                mono_metadata_encode_value (minfo->count, p, &p);
                break;
-               /* FIXME: handle ARRAY and other unmanaged types that need extra info */
+       case MONO_NATIVE_LPARRAY:
+               mono_metadata_encode_value (minfo->type, p, &p);
+               if (minfo->eltype || (minfo->count > 0)) {
+                       mono_metadata_encode_value (minfo->eltype, p, &p);
+                       if (minfo->count > 0) {
+                               mono_metadata_encode_value (0, p, &p);
+                               mono_metadata_encode_value (minfo->count, p, &p);
+                       }
+               }
+               break;
        case MONO_NATIVE_CUSTOM:
                mono_metadata_encode_value (minfo->type, p, &p);
                if (minfo->guid) {
@@ -1278,7 +1590,7 @@ encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
                        mono_metadata_encode_value (0, p, &p);
                }
                if (minfo->marshaltyperef) {
-                       str = type_get_qualified_name (minfo->marshaltyperef->type, assembly->image.assembly);
+                       str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
                        len = strlen (str);
                        mono_metadata_encode_value (len, p, &p);
                        if (p + len >= buf + bufsize) {
@@ -1360,7 +1672,7 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *ass
                values [MONO_CONSTANT_TYPE] = field_type;
                values [MONO_CONSTANT_PADDING] = 0;
        }
-       if (fb->rva_data) {
+       if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
                guint32 rva_idx;
                table = &assembly->tables [MONO_TABLE_FIELDRVA];
                table->rows ++;
@@ -1370,7 +1682,10 @@ mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *ass
                /*
                 * We store it in the code section because it's simpler for now.
                 */
-               rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
+               if (fb->rva_data)
+                       rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
+               else
+                       rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
                values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
        }
        if (fb->marshal_info) {
@@ -1533,6 +1848,75 @@ mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *ass
        }
 }
 
+static void
+encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
+{
+       static MonoClass *NewConstraintAttr;
+       static MonoMethod *NewConstraintAttr_ctor;
+       MonoDynamicTable *table;
+       guint32 *values;
+       guint32 token, type;
+       char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
+       char *buf, *p;
+
+       if (!NewConstraintAttr)
+               NewConstraintAttr = mono_class_from_name (
+                       mono_defaults.corlib, "System.Runtime.CompilerServices",
+                       "NewConstraintAttribute");
+       g_assert (NewConstraintAttr);
+
+       if (!NewConstraintAttr_ctor) {
+               int i;
+
+               for (i = 0; i < NewConstraintAttr->method.count; i++) {
+                       MonoMethod *m = NewConstraintAttr->methods [i];
+
+                       if (strcmp (m->name, ".ctor"))
+                               continue;
+
+                       NewConstraintAttr_ctor = m;
+                       break;
+               }
+
+               g_assert (NewConstraintAttr_ctor);
+       }
+
+       table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+       table->rows += 1;
+       alloc_table (table, table->rows);
+
+       values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
+       owner <<= CUSTOM_ATTR_BITS;
+       owner |= CUSTOM_ATTR_GENERICPAR;
+       values [MONO_CUSTOM_ATTR_PARENT] = owner;
+
+       token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
+
+       type = mono_metadata_token_index (token);
+       type <<= CUSTOM_ATTR_TYPE_BITS;
+       switch (mono_metadata_token_table (token)) {
+       case MONO_TABLE_METHOD:
+               type |= CUSTOM_ATTR_TYPE_METHODDEF;
+               break;
+       case MONO_TABLE_MEMBERREF:
+               type |= CUSTOM_ATTR_TYPE_MEMBERREF;
+               break;
+       default:
+               g_warning ("got wrong token in custom attr");
+               return;
+       }
+       values [MONO_CUSTOM_ATTR_TYPE] = type;
+
+       buf = p = g_malloc (1);
+       mono_metadata_encode_value (4, p, &p);
+       g_assert (p-buf == 1);
+
+       values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
+
+       values += MONO_CUSTOM_ATTR_SIZE;
+       ++table->next_idx;
+}
+
 static void
 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
 {
@@ -1542,25 +1926,43 @@ encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynam
        guint32 table_idx;
 
        table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
-       num_constraints = gparam ? mono_array_length (gparam->constraints) : 0;
+       num_constraints = gparam->iface_constraints ?
+               mono_array_length (gparam->iface_constraints) : 0;
        table->rows += num_constraints;
+       if (gparam->base_type)
+               table->rows++;
        alloc_table (table, table->rows);
 
+       if (gparam->base_type) {
+               table_idx = table->next_idx ++;
+               values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
+
+               values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
+               values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
+                       assembly, gparam->base_type->type);
+       }
+
        for (i = 0; i < num_constraints; i++) {
-               MonoReflectionType *constraint = mono_array_get (gparam->constraints, gpointer, i);
+               MonoReflectionType *constraint = mono_array_get (
+                       gparam->iface_constraints, gpointer, i);
 
                table_idx = table->next_idx ++;
                values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
 
                values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
-               values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (assembly, constraint->type);
+               values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
+                       assembly, constraint->type);
        }
+
+       if (gparam->has_ctor_constraint)
+               encode_new_constraint (assembly, owner);
 }
 
 static void
 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
 {
        MonoDynamicTable *table;
+       MonoGenericParam *param;
        guint32 *values;
        guint32 table_idx;
 
@@ -1568,15 +1970,20 @@ mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 o
        table_idx = table->next_idx ++;
        values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
 
+       param = gparam->type.type->data.generic_param;
+
        values [MONO_GENERICPARAM_OWNER] = owner;
-       values [MONO_GENERICPARAM_FLAGS] = gparam->param->flags;
-       values [MONO_GENERICPARAM_NUMBER] = gparam->param->num;
-       values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, gparam->param->name);
+       if (gparam->has_value_type)
+               values [MONO_GENERICPARAM_FLAGS] = 0x18;
+       else if (gparam->has_reference_type)
+               values [MONO_GENERICPARAM_FLAGS] = 0x04;
+       else
+               values [MONO_GENERICPARAM_FLAGS] = 0x00;
+       values [MONO_GENERICPARAM_NUMBER] = param->num;
+       values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
        values [MONO_GENERICPARAM_KIND] = 0;
-       values [MONO_GENERICPARAM_DEPRECATED_CONSTRAINT] = 0;
 
-       if (gparam->constraints)
-               encode_constraints (gparam, table_idx, assembly);
+       encode_constraints (gparam, table_idx, assembly);
 }
 
 static guint32
@@ -1621,10 +2028,7 @@ resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
        table->rows ++;
        alloc_table (table, table->rows);
        values = table->values + token * MONO_ASSEMBLYREF_SIZE;
-       if (strcmp ("corlib", image->assembly_name) == 0)
-               values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
-       else
-               values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
+       values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
        values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
        values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
        values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
@@ -1633,6 +2037,11 @@ resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
        values [MONO_ASSEMBLYREF_CULTURE] = 0;
        values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
 
+       if (strcmp ("", image->assembly->aname.culture)) {
+               values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
+                               image->assembly->aname.culture);
+       }
+
        if ((pubkey = mono_image_get_public_key (image, &publen))) {
                guchar pubtoken [9];
                pubtoken [0] = 8;
@@ -1647,8 +2056,7 @@ resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
                 * recognized by ms, yuck!
                 * FIXME: need to add more assembly names, as needed.
                 */
-               if (strcmp (image->assembly_name, "corlib") == 0 ||
-                               strcmp (image->assembly_name, "mscorlib") == 0 ||
+               if (strcmp (image->assembly_name, "mscorlib") == 0 ||
                                strcmp (image->assembly_name, "System") == 0 ||
                                strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
                                strcmp (image->assembly_name, "System.Xml") == 0 ||
@@ -1720,7 +2128,7 @@ create_typespec (MonoDynamicImage *assembly, MonoType *type)
                MonoClass *k = mono_class_from_mono_type (type);
                if (!k || !k->generic_inst)
                        return 0;
-               encode_type (assembly, k->generic_inst, p, &p);
+               encode_generic_inst (assembly, k->generic_inst, p, &p);
                break;
        }
        default:
@@ -1871,7 +2279,6 @@ mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMe
                return token;
 
        reflection_methodbuilder_from_method_builder (&rmb, mb);
-
        
        token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
                                                                                        mono_string_to_utf8 (rmb.name),
@@ -1900,55 +2307,29 @@ mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtor
 }
 
 static guint32
-mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoClassField *field, MonoClass *klass)
+mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
 {
+       MonoType *type;
        guint32 token;
-       
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
-       if (token)
-               return token;
-       field->parent = klass;
-       token = mono_image_get_memberref_token (assembly, &klass->byval_arg, 
-               field->name,  fieldref_encode_signature (assembly, field->type));
-       g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
-       return token;
-}
-
-static guint32
-field_encode_inflated_field (MonoDynamicImage *assembly, MonoReflectionInflatedField *field)
-{
-       guint32 sig, token;
-       MonoClass *klass;
-       const gchar *name;
-
-       klass = field->rfield.klass;
-       name = field->rfield.field->name;
-       sig = fieldref_encode_signature (assembly, field->declaring->type);
-       token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
 
-       return token;
-}
-
-static guint32
-mono_image_get_inflated_field_token (MonoDynamicImage *assembly, MonoReflectionInflatedField *field)
-{
-       guint32 token;
-       
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field->rfield.field));
+       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
        if (token)
                return token;
-       token = field_encode_inflated_field (assembly, field);
-       g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
+       g_assert (f->field->parent);
+       type = f->field->generic_type ? f->field->generic_type : f->field->type;
+       token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg, 
+               f->field->name,  fieldref_encode_signature (assembly, type));
+       g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
        return token;
 }
 
 static guint32
-encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericInst *ginst)
+encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
 {
        char *buf;
        char *p;
        int i;
-       guint32 nparams =  ginst->type_argc;
+       guint32 nparams =  gmethod->mtype_argc;
        guint32 size = 10 + nparams * 10;
        guint32 idx;
        char blob_size [6];
@@ -1965,7 +2346,7 @@ encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericInst *ginst)
        mono_metadata_encode_value (nparams, p, &p);
 
        for (i = 0; i < nparams; i++)
-               encode_type (assembly, ginst->type_argv [i], p, &p);
+               encode_type (assembly, gmethod->mtype_argv [i], p, &p);
 
        /* store length */
        g_assert (p - buf < size);
@@ -1976,27 +2357,26 @@ encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericInst *ginst)
 }
 
 static guint32
-method_encode_methodspec (MonoDynamicImage *assembly, MonoGenericInst *ginst)
+method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
 {
        MonoDynamicTable *table;
        guint32 *values;
-       guint32 token, mtoken, sig;
+       guint32 token, mtoken = 0, sig;
+       MonoMethodInflated *imethod;
+       MonoMethod *declaring;
 
        table = &assembly->tables [MONO_TABLE_METHODSPEC];
 
-       g_assert (ginst);
-       if (ginst->generic_method) {
-               MonoMethod *gm = ginst->generic_method;
-               MonoClass *k = ginst->klass ? ginst->klass : gm->klass;
+       g_assert (method->signature->is_inflated);
+       imethod = (MonoMethodInflated *) method;
+       declaring = imethod->declaring;
 
-               sig = method_encode_signature (assembly, gm->signature);
-               mtoken = mono_image_get_memberref_token (assembly, &k->byval_arg, gm->name, sig);
+       sig = method_encode_signature (assembly, declaring->signature);
+       mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
+                                                declaring->name, sig);
 
-               if (!ginst->generic_method->signature->generic_param_count)
-                       return mtoken;
-       }
-       else
-               g_assert_not_reached ();
+       if (!declaring->signature->generic_param_count)
+               return mtoken;
 
        switch (mono_metadata_token_table (mtoken)) {
        case MONO_TABLE_MEMBERREF:
@@ -2009,7 +2389,7 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoGenericInst *ginst)
                g_assert_not_reached ();
        }
 
-       sig = encode_generic_method_sig (assembly, ginst);
+       sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
 
        if (assembly->save) {
                alloc_table (table, table->rows + 1);
@@ -2025,15 +2405,28 @@ method_encode_methodspec (MonoDynamicImage *assembly, MonoGenericInst *ginst)
 }
 
 static guint32
-mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method, MonoGenericInst *ginst)
+mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
 {
+       MonoMethodInflated *imethod;
        guint32 token;
        
-       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
+       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
        if (token)
                return token;
-       token = method_encode_methodspec (assembly, ginst);
-       g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
+
+       g_assert (m->signature->is_inflated);
+       imethod = (MonoMethodInflated *) m;
+
+       if (imethod->declaring->signature->generic_param_count)
+               token = method_encode_methodspec (assembly, m);
+       else {
+               guint32 sig = method_encode_signature (
+                       assembly, imethod->declaring->signature);
+               token = mono_image_get_memberref_token (
+                       assembly, &m->klass->byval_arg, m->name, sig);
+       }
+
+       g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
        return token;
 }
 
@@ -2050,6 +2443,16 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *
        char *b = blob_size;
        int count, i;
 
+       /*
+        * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
+        * ie. what we'd normally use as the generic type in a TypeSpec signature.
+        * Because of this, we must not insert it into the `typeref' hash table.
+        */
+
+       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
+       if (token)
+               return token;
+
        g_assert (tb->generic_params);
        klass = mono_class_from_mono_type (tb->type.type);
 
@@ -2060,14 +2463,10 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *
        mono_metadata_encode_value (count, p, &p);
        for (i = 0; i < count; i++) {
                MonoReflectionGenericParam *gparam;
-               MonoType t;
 
                gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
 
-               t.type = MONO_TYPE_VAR;
-               t.data.generic_param = gparam->param;
-
-               encode_type (assembly, &t, p, &p);
+               encode_type (assembly, gparam->type.type, p, &p);
        }
 
        table = &assembly->tables [MONO_TABLE_TYPESPEC];
@@ -2081,7 +2480,7 @@ create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *
        }
 
        token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
-       g_hash_table_insert (assembly->typeref, tb->type.type, GUINT_TO_POINTER(token));
+       g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
        table->next_idx ++;
        return token;
 }
@@ -2095,6 +2494,10 @@ mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFi
        guint32 token, pclass, parent, sig;
        gchar *name;
 
+       token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
+       if (token)
+               return token;
+
        klass = mono_class_from_mono_type (fb->typeb->type);
        name = mono_string_to_utf8 (fb->name);
 
@@ -2118,7 +2521,7 @@ mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFi
 
        token = MONO_TOKEN_MEMBER_REF | table->next_idx;
        table->next_idx ++;
-
+       g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
        return token;
 }
 
@@ -2340,9 +2743,9 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
        /* handle fields */
        if (tb->fields) {
                table = &assembly->tables [MONO_TABLE_FIELD];
-               table->rows += mono_array_length (tb->fields);
+               table->rows += tb->num_fields;
                alloc_table (table, table->rows);
-               for (i = 0; i < mono_array_length (tb->fields); ++i)
+               for (i = 0; i < tb->num_fields; ++i)
                        mono_image_get_field_info (
                                mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
        }
@@ -2360,9 +2763,9 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
        /* handle methods */
        if (tb->methods) {
                table = &assembly->tables [MONO_TABLE_METHOD];
-               table->rows += mono_array_length (tb->methods);
+               table->rows += tb->num_methods;
                alloc_table (table, table->rows);
-               for (i = 0; i < mono_array_length (tb->methods); ++i)
+               for (i = 0; i < tb->num_methods; ++i)
                        mono_image_get_method_info (
                                mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
        }
@@ -2396,6 +2799,11 @@ mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, Mon
                        mono_image_get_property_info (
                                mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
        }
+
+       mono_image_add_decl_security (assembly, 
+                                                                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
+                                                                 tb->permissions);
+
        if (tb->subtypes) {
                MonoDynamicTable *ntable;
                
@@ -2469,7 +2877,7 @@ type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
        
        mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
        if (tb->fields) {
-               for (i = 0; i < mono_array_length (tb->fields); ++i) {
+               for (i = 0; i < tb->num_fields; ++i) {
                        MonoReflectionFieldBuilder* fb;
                        fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
                        mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
@@ -2499,7 +2907,7 @@ type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
        }
 
        if (tb->methods) {
-               for (i = 0; i < mono_array_length (tb->methods); ++i) {
+               for (i = 0; i < tb->num_methods; ++i) {
                        MonoReflectionMethodBuilder* mb;
                        mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
                        mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
@@ -2523,12 +2931,12 @@ module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb)
        if (!mb->types)
                return;
        
-       for (i = 0; i < mono_array_length (mb->types); ++i)
+       for (i = 0; i < mb->num_types; ++i)
                type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
 }
 
 static void
-mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb,
+mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
                                                        MonoDynamicImage *assembly)
 {
        MonoDynamicTable *table;
@@ -2543,10 +2951,16 @@ mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb,
        alloc_table (table, table->rows);
        values = table->values + table->next_idx * MONO_FILE_SIZE;
        values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
-       values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, mb->dynamic_image->image.module_name);
-       /* This depends on the fact that the main module is emitted last */
-       dir = mono_string_to_utf8 (mb->assemblyb->dir);
-       path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, mb->dynamic_image->image.module_name);
+       values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
+       if (module->image->dynamic) {
+               /* This depends on the fact that the main module is emitted last */
+               dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
+               path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
+       }
+       else {
+               dir = NULL;
+               path = g_strdup (module->image->name);
+       }
        mono_sha1_get_digest_from_file (path, hash);
        g_free (dir);
        g_free (path);
@@ -2576,51 +2990,89 @@ mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *m
        table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
 }
 
-static void
-mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
-                                                         guint32 module_index, guint32 parent_index, 
-                                                         MonoDynamicImage *assembly)
+static guint32
+mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
+                                                                                guint32 module_index, guint32 parent_index, 
+                                                                                MonoDynamicImage *assembly)
 {
        MonoDynamicTable *table;
        guint32 *values;
-       guint32 visib;
-       char *name;
-       char *name_space;
-       int i;
+       guint32 visib, res;
 
-       visib = tb->attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
+       visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
        if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
-               return;
-
-       name = mono_string_to_utf8 (tb->name);
-       name_space = mono_string_to_utf8 (tb->nspace);
+               return 0;
 
        table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
        table->rows++;
        alloc_table (table, table->rows);
        values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
 
-       values [MONO_EXP_TYPE_FLAGS] = tb->attrs;
-       values [MONO_EXP_TYPE_TYPEDEF] = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
-       if (tb->nesting_type) {
+       values [MONO_EXP_TYPE_FLAGS] = klass->flags;
+       values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
+       if (klass->nested_in)
                values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
-       }
-       else {
-               values [MONO_EXP_TYPE_TYPEDEF] = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
+       else
                values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
-       }
-       values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, name);
-       values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, name_space);
+       values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
+       values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
 
-       g_free (name);
-       g_free (name_space);
+       res = table->next_idx;
 
        table->next_idx ++;
 
        /* Emit nested types */
+       if (klass->nested_classes) {
+               GList *tmp;
+
+               for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
+                       mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
+       }
+
+       return res;
+}
+
+static void
+mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
+                                                         guint32 module_index, guint32 parent_index, 
+                                                         MonoDynamicImage *assembly)
+{
+       MonoClass *klass;
+       guint32 idx, i;
+
+       klass = mono_class_from_mono_type (tb->type.type);
+
+       klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
+
+       idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
+                                                                                                  parent_index, assembly);
+
+       /* 
+        * Emit nested types
+        * We need to do this ourselves since klass->nested_classes is not set up.
+        */
        if (tb->subtypes) {
                for (i = 0; i < mono_array_length (tb->subtypes); ++i)
-                       mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, table->next_idx - 1, assembly);
+                       mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
+       }
+}
+
+static void
+mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
+                                                                                 guint32 module_index,
+                                                                                 MonoDynamicImage *assembly)
+{
+       MonoImage *image = module->image;
+       MonoTableInfo  *t;
+       guint32 i;
+
+       t = &image->tables [MONO_TABLE_TYPEDEF];
+
+       for (i = 0; i < t->rows; ++i) {
+               MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
+
+               if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
+                       mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
        }
 }
 
@@ -2788,8 +3240,17 @@ build_compressed_metadata (MonoDynamicImage *assembly)
        int32val = (guint32*)p;
        *int32val = GUINT32_TO_LE (0); /* reserved */
        p += 4;
-       *p++ = 1; /* version */
-       *p++ = 0;
+
+       if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
+           (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
+           (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
+               *p++ = 1; /* version */
+               *p++ = 1;
+       } else {
+               *p++ = 1; /* version */
+               *p++ = 0;
+       }
+
        if (meta->idx_string_wide)
                *p |= 0x01;
        if (meta->idx_guid_wide)
@@ -2886,7 +3347,7 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
        MonoReflectionMethodBuilder *method;
        MonoReflectionTypeBuilder *tb;
        MonoReflectionArrayMethod *am;
-       guint32 i, idx;
+       guint32 i, idx = 0;
        unsigned char *target;
 
        for (i = 0; i < ilgen->num_token_fixups; ++i) {
@@ -2911,7 +3372,8 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
                        } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
                                ctor = (MonoReflectionCtorBuilder *)iltoken->member;
                                idx = ctor->table_idx;
-                       } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
+                       } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
+                                          !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
                                MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
                                idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
                        } else {
@@ -2933,12 +3395,12 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
                                MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
                                g_assert (m->klass->generic_inst);
                                continue;
-                       } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoInflatedMethod") ||
-                                  !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedCtor") ||
-                                  !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedField")) {
-                               continue;
                        } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
                                continue;
+                       } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
+                               MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
+                               g_assert (f->generic_type);
+                               continue;
                        } else {
                                g_assert_not_reached ();
                        }
@@ -2948,9 +3410,6 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
                                MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
                                g_assert (m->signature->generic_param_count);
                                continue;
-                       } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoInflatedMethod") ||
-                                  !strcmp (iltoken->member->vtable->klass->name, "MonoInflatedCtor")) {
-                               continue;
                        } else {
                                g_assert_not_reached ();
                        }
@@ -2964,8 +3423,63 @@ fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *asse
        }
 }
 
+/*
+ * fixup_cattrs:
+ *
+ *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
+ * value is not known when the table is emitted.
+ */
+static void
+fixup_cattrs (MonoDynamicImage *assembly)
+{
+       MonoDynamicTable *table;
+       guint32 *values;
+       guint32 type, i, idx, token;
+       MonoObject *ctor;
+
+       table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
+
+       for (i = 0; i < table->rows; ++i) {
+               values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
+
+               type = values [MONO_CUSTOM_ATTR_TYPE];
+               if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
+                       idx = type >> CUSTOM_ATTR_TYPE_BITS;
+                       token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
+                       ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
+                       g_assert (ctor);
+
+                       if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
+                               MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
+                               idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
+                               values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
+                       }
+               }
+       }
+}
+
+static void
+assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
+{
+       MonoDynamicTable *table;
+       guint32 *values;
+       char *name;
+
+       table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
+       table->rows++;
+       alloc_table (table, table->rows);
+       values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
+       values [MONO_MANIFEST_OFFSET] = rsrc->offset;
+       values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
+       name = mono_string_to_utf8 (rsrc->name);
+       values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
+       g_free (name);
+       values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
+       table->next_idx++;
+}
+
 static void
-assembly_add_resource (MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
+assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
 {
        MonoDynamicTable *table;
        guint32 *values;
@@ -2993,29 +3507,28 @@ assembly_add_resource (MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
                mono_image_add_stream_data (&assembly->blob, hash, 20);
                g_free (name);
                idx = table->next_idx++;
+               rsrc->offset = 0;
                idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
-               offset = 0;
        } else {
                char sizebuf [4];
                offset = mono_array_length (rsrc->data);
                sizebuf [0] = offset; sizebuf [1] = offset >> 8;
                sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
-               offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
+               rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
                mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
-               idx = 0;
+
+               if (!mb->is_main)
+                       /* 
+                        * The entry should be emitted into the MANIFESTRESOURCE table of 
+                        * the main module, but that needs to reference the FILE table
+                        * which isn't emitted yet.
+                        */
+                       return;
+               else
+                       idx = 0;
        }
 
-       table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
-       table->rows++;
-       alloc_table (table, table->rows);
-       values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
-       values [MONO_MANIFEST_OFFSET] = offset;
-       values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
-       name = mono_string_to_utf8 (rsrc->name);
-       values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
-       g_free (name);
-       values [MONO_MANIFEST_IMPLEMENTATION] = idx;
-       table->next_idx++;
+       assembly_add_resource_manifest (mb, assembly, rsrc, idx);
 }
 
 static void
@@ -3069,6 +3582,89 @@ load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
        return token;
 }
 
+static void
+mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
+{
+       MonoDynamicTable *table;
+       MonoDynamicImage *assembly;
+       MonoReflectionAssemblyBuilder *assemblyb;
+       MonoDomain *domain;
+       guint32 *values;
+       char *name;
+       int i;
+       guint32 module_index;
+
+       assemblyb = moduleb->assemblyb;
+       assembly = moduleb->dynamic_image;
+       domain = mono_object_domain (assemblyb);
+
+       /* Emit ASSEMBLY table */
+       table = &assembly->tables [MONO_TABLE_ASSEMBLY];
+       alloc_table (table, 1);
+       values = table->values + MONO_ASSEMBLY_SIZE;
+       values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
+       name = mono_string_to_utf8 (assemblyb->name);
+       values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
+       g_free (name);
+       if (assemblyb->culture) {
+               name = mono_string_to_utf8 (assemblyb->culture);
+               values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
+               g_free (name);
+       } else {
+               values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
+       }
+       values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
+       values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
+       set_version_from_string (assemblyb->version, values);
+
+       /* Emit FILE + EXPORTED_TYPE table */
+       module_index = 0;
+       for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
+               int j;
+               MonoReflectionModuleBuilder *file_module = 
+                       mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
+               if (file_module != moduleb) {
+                       mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
+                       module_index ++;
+                       if (file_module->types) {
+                               for (j = 0; j < file_module->num_types; ++j) {
+                                       MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
+                                       mono_image_fill_export_table (domain, tb, module_index, 0,
+                                                                                                 assembly);
+                               }
+                       }
+               }
+       }
+       if (assemblyb->loaded_modules) {
+               for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
+                       MonoReflectionModule *file_module = 
+                               mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
+                       mono_image_fill_file_table (domain, file_module, assembly);
+                       module_index ++;
+                       mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
+               }
+       }
+
+       /* Emit MANIFESTRESOURCE table */
+       module_index = 0;
+       for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
+               int j;
+               MonoReflectionModuleBuilder *file_module = 
+                       mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
+               /* The table for the main module is emitted later */
+               if (file_module != moduleb) {
+                       module_index ++;
+                       if (file_module->resources) {
+                               int len = mono_array_length (file_module->resources);
+                               for (j = 0; j < len; ++j) {
+                                       MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
+                                       assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
+                               }
+                       }
+               }
+       }               
+}
+
 /*
  * mono_image_build_metadata() will fill the info in all the needed metadata tables
  * for the modulebuilder @moduleb.
@@ -3083,9 +3679,7 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
        MonoReflectionAssemblyBuilder *assemblyb;
        MonoDomain *domain;
        guint32 *values;
-       char *name;
        int i;
-       guint32 module_index;
 
        assemblyb = moduleb->assemblyb;
        assembly = moduleb->dynamic_image;
@@ -3097,41 +3691,7 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
        assembly->text_rva = START_TEXT_RVA;
 
        if (moduleb->is_main) {
-               /* Emit the manifest */
-               table = &assembly->tables [MONO_TABLE_ASSEMBLY];
-               alloc_table (table, 1);
-               values = table->values + MONO_ASSEMBLY_SIZE;
-               values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
-               name = mono_string_to_utf8 (assemblyb->name);
-               values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
-               g_free (name);
-               if (assemblyb->culture) {
-                       name = mono_string_to_utf8 (assemblyb->culture);
-                       values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
-                       g_free (name);
-               } else {
-                       values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
-               }
-               values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
-               values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
-               set_version_from_string (assemblyb->version, values);
-
-               /* Emit FILE + EXPORTED_TYPE table */
-               module_index = 0;
-               for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
-                       int j;
-                       MonoReflectionModuleBuilder *file_module = 
-                               mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
-                       if (file_module != moduleb) {
-                               mono_image_fill_file_table (domain, file_module, assembly);
-                               module_index ++;
-                               for (j = 0; j < mono_array_length (file_module->types); ++j) {
-                                       MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
-                                       mono_image_fill_export_table (domain, tb, module_index, 0,
-                                                                                                 assembly);
-                               }
-                       }
-               }
+               mono_image_emit_manifest (moduleb);
        }
 
        table = &assembly->tables [MONO_TABLE_TYPEDEF];
@@ -3180,7 +3740,7 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
                GPtrArray *types = g_ptr_array_new ();
 
                if (moduleb->types)
-                       for (i = 0; i < mono_array_length (moduleb->types); ++i) {
+                       for (i = 0; i < moduleb->num_types; ++i) {
                                MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
                                collect_types (types, type);
                        }
@@ -3207,6 +3767,7 @@ mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
 
        /* fixup tokens */
        mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
+       fixup_cattrs (assembly);
 }
 
 /*
@@ -3277,7 +3838,7 @@ guint32
 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
 {
        MonoClass *klass;
-       guint32 token;
+       guint32 token = 0;
 
        klass = obj->vtable->klass;
        if (strcmp (klass->name, "MethodBuilder") == 0) {
@@ -3311,7 +3872,13 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
                MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
                token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
        }
-       else if (strcmp (klass->name, "MonoType") == 0) {
+       else if (strcmp (klass->name, "MonoType") == 0 ||
+                strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
+               MonoReflectionType *tb = (MonoReflectionType *)obj;
+               token = mono_metadata_token_from_dor (
+                       mono_image_typedef_or_ref (assembly, tb->type));
+       }
+       else if (strcmp (klass->name, "MonoGenericInst") == 0) {
                MonoReflectionType *tb = (MonoReflectionType *)obj;
                token = mono_metadata_token_from_dor (
                        mono_image_typedef_or_ref (assembly, tb->type));
@@ -3319,9 +3886,10 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
        else if (strcmp (klass->name, "MonoCMethod") == 0 ||
                        strcmp (klass->name, "MonoMethod") == 0) {
                MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
-               if (m->method->signature->generic_param_count) {
+               if (m->method->signature->is_inflated) {
+                       token = mono_image_get_methodspec_token (assembly, m->method);
+               } else if (m->method->signature->generic_param_count) {
                        g_assert_not_reached ();
-                       token = mono_image_get_methodspec_token (assembly, m->method, NULL);
                } else if ((m->method->klass->image == &assembly->image) &&
                         !m->method->klass->generic_inst) {
                        static guint32 method_table_idx = 0xffffff;
@@ -3336,23 +3904,14 @@ mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
                        token = mono_image_get_methodref_token (assembly, m->method);
                /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
        }
-       else if (strcmp (klass->name, "MonoInflatedMethod") == 0 ||
-                strcmp (klass->name, "MonoInflatedCtor") == 0) {
-               MonoReflectionInflatedMethod *m = (MonoReflectionInflatedMethod *)obj;
-               token = mono_image_get_methodspec_token (assembly, m->rmethod.method, m->ginst);
-       }
-       else if (strcmp (klass->name, "MonoInflatedField") == 0) {
-               MonoReflectionInflatedField *f = (MonoReflectionInflatedField *)obj;
-               token = mono_image_get_inflated_field_token (assembly, f);
-       }
        else if (strcmp (klass->name, "MonoField") == 0) {
                MonoReflectionField *f = (MonoReflectionField *)obj;
-               if (f->klass->image == &assembly->image) {
+               if ((f->klass->image == &assembly->image) && !f->field->generic_type) {
                        static guint32 field_table_idx = 0xffffff;
                        field_table_idx --;
                        token = MONO_TOKEN_FIELD_DEF | field_table_idx;
                } else
-                       token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
+                       token = mono_image_get_fieldref_token (assembly, f);
                /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
        }
        else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
@@ -3413,6 +3972,7 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly,
        image->image.assembly_name = image->image.name; /* they may be different */
        image->image.module_name = module_name;
        image->image.version = g_strdup (version);
+       image->image.dynamic = TRUE;
 
        image->image.references = g_new0 (MonoAssembly*, 1);
        image->image.references [0] = NULL;
@@ -3425,6 +3985,7 @@ create_dynamic_mono_image (MonoDynamicAssembly *assembly,
        image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
        image->handleref = g_hash_table_new (NULL, NULL);
        image->tokens = mono_g_hash_table_new (NULL, NULL);
+       image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
        image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
        image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
 
@@ -3474,7 +4035,7 @@ mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
                return;
 
 #if HAVE_BOEHM_GC
-       assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicImage));
+       assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
 #else
        assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
 #endif
@@ -3515,6 +4076,14 @@ calc_section_size (MonoDynamicImage *assembly)
        assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
        nsections++;
 
+       if (assembly->win32_res) {
+               guint32 res_size = (assembly->win32_res_size + 3) & ~3;
+
+               assembly->sections [MONO_SECTION_RSRC].size = res_size;
+               assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
+               nsections++;
+       }
+
        assembly->sections [MONO_SECTION_RELOC].size = 12;
        assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
        nsections++;
@@ -3522,6 +4091,227 @@ calc_section_size (MonoDynamicImage *assembly)
        return nsections;
 }
 
+typedef struct {
+       guint32 id;
+       guint32 offset;
+       GSList *children;
+       MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
+} ResTreeNode;
+
+static int
+resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
+{
+       ResTreeNode *t1 = (ResTreeNode*)a;
+       ResTreeNode *t2 = (ResTreeNode*)b;
+
+       return t1->id - t2->id;
+}
+
+/*
+ * resource_tree_create:
+ *
+ *  Organize the resources into a resource tree.
+ */
+static ResTreeNode *
+resource_tree_create (MonoArray *win32_resources)
+{
+       ResTreeNode *tree, *res_node, *type_node, *lang_node;
+       GSList *l;
+       int i;
+
+       tree = g_new0 (ResTreeNode, 1);
+       
+       for (i = 0; i < mono_array_length (win32_resources); ++i) {
+               MonoReflectionWin32Resource *win32_res =
+                       (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
+
+               /* Create node */
+
+               lang_node = g_new0 (ResTreeNode, 1);
+               lang_node->id = win32_res->lang_id;
+               lang_node->win32_res = win32_res;
+
+               /* Create type node if neccesary */
+               type_node = NULL;
+               for (l = tree->children; l; l = l->next)
+                       if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
+                               type_node = (ResTreeNode*)l->data;
+                               break;
+                       }
+
+               if (!type_node) {
+                       type_node = g_new0 (ResTreeNode, 1);
+                       type_node->id = win32_res->res_type;
+
+                       /* 
+                        * The resource types have to be sorted otherwise
+                        * Windows Explorer can't display the version information.
+                        */
+                       tree->children = g_slist_insert_sorted (tree->children, type_node, 
+                                                                                                       resource_tree_compare_by_id);
+               }
+
+               /* Create res node if neccesary */
+               res_node = NULL;
+               for (l = type_node->children; l; l = l->next)
+                       if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
+                               res_node = (ResTreeNode*)l->data;
+                               break;
+                       }
+
+               if (!res_node) {
+                       res_node = g_new0 (ResTreeNode, 1);
+                       res_node->id = win32_res->res_id;
+                       type_node->children = g_slist_append (type_node->children, res_node);
+               }
+
+               res_node->children = g_slist_append (res_node->children, lang_node);
+       }
+
+       return tree;
+}
+
+/*
+ * resource_tree_encode:
+ * 
+ *   Encode the resource tree into the format used in the PE file.
+ */
+static void
+resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
+{
+       char *entries;
+       MonoPEResourceDir dir;
+       MonoPEResourceDirEntry dir_entry;
+       MonoPEResourceDataEntry data_entry;
+       GSList *l;
+
+       /*
+        * For the format of the resource directory, see the article
+        * "An In-Depth Look into the Win32 Portable Executable File Format" by
+        * Matt Pietrek
+        */
+
+       memset (&dir, 0, sizeof (dir));
+       memset (&dir_entry, 0, sizeof (dir_entry));
+       memset (&data_entry, 0, sizeof (data_entry));
+
+       g_assert (sizeof (dir) == 16);
+       g_assert (sizeof (dir_entry) == 8);
+       g_assert (sizeof (data_entry) == 16);
+
+       node->offset = p - begin;
+
+       /* IMAGE_RESOURCE_DIRECTORY */
+       dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
+
+       memcpy (p, &dir, sizeof (dir));
+       p += sizeof (dir);
+
+       /* Reserve space for entries */
+       entries = p;
+       p += sizeof (dir_entry) * dir.res_id_entries;
+
+       /* Write children */
+       for (l = node->children; l; l = l->next) {
+               ResTreeNode *child = (ResTreeNode*)l->data;
+
+               if (child->win32_res) {
+
+                       child->offset = p - begin;
+
+                       /* IMAGE_RESOURCE_DATA_ENTRY */
+                       data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
+                       data_entry.rde_size = mono_array_length (child->win32_res->res_data);
+
+                       memcpy (p, &data_entry, sizeof (data_entry));
+                       p += sizeof (data_entry);
+
+                       memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
+                       p += data_entry.rde_size;
+               }
+               else
+                       resource_tree_encode (child, begin, p, &p);
+       }
+
+       /* IMAGE_RESOURCE_ENTRY */
+       for (l = node->children; l; l = l->next) {
+               ResTreeNode *child = (ResTreeNode*)l->data;
+               dir_entry.name_offset = GUINT32_TO_LE (child->id);
+
+               dir_entry.is_dir = child->win32_res ? 0 : 1;
+               dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
+
+               memcpy (entries, &dir_entry, sizeof (dir_entry));
+               entries += sizeof (dir_entry);
+       }
+
+       *endbuf = p;
+}
+
+static void
+assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
+{
+       char *buf;
+       char *p;
+       guint32 size, i;
+       MonoReflectionWin32Resource *win32_res;
+       ResTreeNode *tree;
+
+       if (!assemblyb->win32_resources)
+               return;
+
+       /*
+        * Resources are stored in a three level tree inside the PE file.
+        * - level one contains a node for each type of resource
+        * - level two contains a node for each resource
+        * - level three contains a node for each instance of a resource for a
+        *   specific language.
+        */
+
+       tree = resource_tree_create (assemblyb->win32_resources);
+
+       /* Estimate the size of the encoded tree */
+       size = 0;
+       for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
+               win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
+               size += mono_array_length (win32_res->res_data);
+       }
+       /* Directory structure */
+       size += mono_array_length (assemblyb->win32_resources) * 256;
+       p = buf = g_malloc (size);
+
+       resource_tree_encode (tree, p, p, &p);
+
+       g_assert (p - buf < size);
+
+       assembly->win32_res = g_malloc (p - buf);
+       assembly->win32_res_size = p - buf;
+       memcpy (assembly->win32_res, buf, p - buf);
+
+       g_free (buf);
+}
+
+static void
+fixup_resource_directory (char *res_section, char *p, guint32 rva)
+{
+       MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
+       int i;
+
+       p += sizeof (MonoPEResourceDir);
+       for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
+               MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
+               char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
+               if (dir_entry->is_dir)
+                       fixup_resource_directory (res_section, child, rva);
+               else {
+                       MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
+                       data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
+               }
+
+               p += sizeof (MonoPEResourceDirEntry);
+       }
+}
+
 /*
  * mono_image_create_pefile:
  * @mb: a module builder object
@@ -3566,15 +4356,23 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
        
        mono_image_build_metadata (mb);
 
-       if (assemblyb->resources) {
+       if (mb->is_main && assemblyb->resources) {
                int len = mono_array_length (assemblyb->resources);
                for (i = 0; i < len; ++i)
-                       assembly_add_resource (assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
+                       assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
+       }
+
+       if (mb->resources) {
+               int len = mono_array_length (mb->resources);
+               for (i = 0; i < len; ++i)
+                       assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
        }
 
-       
        build_compressed_metadata (assembly);
 
+       if (mb->is_main)
+               assembly_add_win32_resources (assembly, assemblyb);
+
        nsections = calc_section_size (assembly);
 
        pefile = &assembly->pefile;
@@ -3738,8 +4536,16 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
        cli_header->ch_size = GUINT32_FROM_LE (72);
        cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
        cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
-       if (assemblyb->entry_point) 
-               cli_header->ch_entry_point = GUINT32_FROM_LE (assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF);
+       if (assemblyb->entry_point) {
+               guint32 table_idx = 0;
+               if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
+                       MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
+                       table_idx = methodb->table_idx;
+               }
+               else
+                       table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
+               cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
+       }                       
        else
                cli_header->ch_entry_point = GUINT32_FROM_LE (0);
        /* The embedded managed resources */
@@ -3810,6 +4616,15 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
                        *data16 = 0; /* terminate */
                        break;
                case MONO_SECTION_RSRC:
+                       if (assembly->win32_res) {
+                               text_offset = assembly->sections [i].offset;
+
+                               /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
+                               fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
+
+                               memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
+                       }
+                       break;
                default:
                        g_assert_not_reached ();
                }
@@ -3826,6 +4641,41 @@ mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
 #endif
 }
 
+MonoReflectionModule *
+mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
+{
+       char *name;
+       MonoImage *image;
+       MonoImageOpenStatus status;
+       MonoDynamicAssembly *assembly;
+       
+       name = mono_string_to_utf8 (fileName);
+
+       image = mono_image_open (name, &status);
+       if (status) {
+               MonoException *exc;
+               if (status == MONO_IMAGE_ERROR_ERRNO)
+                       exc = mono_get_exception_file_not_found (fileName);
+               else
+                       exc = mono_get_exception_bad_image_format (name);
+               g_free (name);
+               mono_raise_exception (exc);
+       }
+
+       g_free (name);
+
+       assembly = ab->dynamic_assembly;
+       image->assembly = (MonoAssembly*)assembly;
+
+       mono_assembly_load_references (image, &status);
+       if (status) {
+               mono_image_close (image);
+               mono_raise_exception (mono_get_exception_file_not_found (fileName));
+       }
+
+       return mono_module_get_object (mono_domain_get (), image);
+}
+
 /*
  * We need to return always the same object for MethodInfo, FieldInfo etc..
  * but we need to consider the reflected type.
@@ -3958,9 +4808,11 @@ mono_module_get_object   (MonoDomain *domain, MonoImage *image)
        res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
 
        res->fqname    = mono_string_new (domain, image->name);
-       res->name      = mono_string_new (domain, image->name);
+       res->name      = mono_string_new (domain, g_path_get_basename (image->name));
        res->scopename = mono_string_new (domain, image->module_name);
 
+       mono_image_addref (image);
+
        CACHE_OBJECT (image, res, NULL);
        return res;
 }
@@ -4086,6 +4938,36 @@ mymono_metadata_type_hash (MonoType *t1)
        return hash;
 }
 
+static MonoReflectionGenericInst*
+mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
+{
+       static MonoClass *System_Reflection_MonoGenericInst;
+       MonoReflectionGenericInst *res;
+       MonoGenericInst *ginst;
+       MonoClass *gklass;
+
+       if (!System_Reflection_MonoGenericInst) {
+               System_Reflection_MonoGenericInst = mono_class_from_name (
+                       mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
+               g_assert (System_Reflection_MonoGenericInst);
+       }
+
+       ginst = geninst->data.generic_inst;
+       gklass = mono_class_from_mono_type (ginst->generic_type);
+
+       mono_class_init (ginst->klass);
+
+       res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
+
+       res->type.type = geninst;
+       if (gklass->wastypebuilder && gklass->reflection_info)
+               res->generic_type = gklass->reflection_info;
+       else
+               res->generic_type = mono_type_get_object (domain, ginst->generic_type);
+
+       return res;
+}
+
 /*
  * mono_type_get_object:
  * @domain: an app domain
@@ -4107,6 +4989,12 @@ mono_type_get_object (MonoDomain *domain, MonoType *type)
                mono_domain_unlock (domain);
                return res;
        }
+       if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
+               res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
+               mono_g_hash_table_insert (domain->type_hash, type, res);
+               mono_domain_unlock (domain);
+               return res;
+       }
        if (klass->reflection_info && !klass->wastypebuilder) {
                //g_assert_not_reached ();
                /* should this be considered an error condition? */
@@ -4294,8 +5182,9 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
        memset (assembly, 0, sizeof (MonoAssemblyName));
        assembly->name = p;
        assembly->culture = "";
-       
-       while (*p && (isalnum (*p) || *p == '.' || *p == '-'))
+       assembly->public_tok_value = NULL;
+
+       while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
                p++;
        found_sep = 0;
        while (*p == ' ' || *p == ',') {
@@ -4307,7 +5196,7 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
        if (!found_sep)
                return 1;
        while (*p) {
-               if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
+               if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
                        p += 8;
                        assembly->major = strtoul (p, &s, 10);
                        if (s == p || *s != '.')
@@ -4324,10 +5213,11 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
                        assembly->revision = strtoul (p, &s, 10);
                        if (s == p)
                                return 1;
-               } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
+                       p = s;
+               } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
                        p += 8;
-                       if (strncmp (p, "neutral", 7) == 0) {
-                               assembly->culture = "";
+                       if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
+                               assembly->culture = g_strdup ("");
                                p += 7;
                        } else {
                                assembly->culture = p;
@@ -4335,26 +5225,16 @@ assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
                                        p++;
                                }
                        }
-               } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
+               } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
                        p += 15;
-                       s = p;
-                       while (*s && isxdigit (*s)) {
-                               *s = tolower (*s);
-                               s++;
-                       }
-                       assembly->hash_len = s - p;
-                       if (!(s-p) || ((s-p) & 1))
-                               return 1;
-                       assembly->hash_value = s = p;
-                       while (*s && isxdigit (*s)) {
-                               int val;
-                               val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
-                               s++;
-                               *p = val << 4;
-                               *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
-                               p++;
+                       if (strncmp (p, "null", 4) == 0) {
+                               p += 4;
+                       } else {
+                               assembly->public_tok_value = p;
+                               while (*p && *p != ',') {
+                                       p++;
+                               }
                        }
-                       p = s;
                } else {
                        while (*p && *p != ',')
                                p++;
@@ -4597,9 +5477,36 @@ mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ig
        assembly = 
                mono_domain_try_type_resolve (
                        mono_domain_get (), fullName->str, NULL);
-       if (assembly && (!image || (assembly->assembly->image == image)))
-               type = mono_reflection_get_type_internal (assembly->assembly->image, 
-                                                                                info, ignorecase);
+       if (assembly && (!image || (assembly->assembly->image == image))) {
+
+               if (assembly->assembly->dynamic) {
+                       /* Enumerate all modules */
+                       MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
+                       int i;
+
+                       type = NULL;
+                       if (abuilder->modules) {
+                               for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
+                                       MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
+                                       type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
+                                       if (type)
+                                               break;
+                               }
+                       }
+
+                       if (!type && abuilder->loaded_modules) {
+                               for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
+                                       MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
+                                       type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
+                                       if (type)
+                                               break;
+                               }
+                       }
+               }
+               else
+                       type = mono_reflection_get_type_internal (assembly->assembly->image, 
+                                                                                                         info, ignorecase);
+       }
        g_string_free (fullName, TRUE);
        return type;
 }
@@ -4619,6 +5526,7 @@ mono_reflection_type_from_name (char *name, MonoImage *image)
 {
        MonoType *type;
        MonoTypeNameParse info;
+       MonoAssembly *assembly;
        
        /*g_print ("requested type %s\n", str);*/
        if (!mono_reflection_parse_type (name, &info)) {
@@ -4628,13 +5536,15 @@ mono_reflection_type_from_name (char *name, MonoImage *image)
        }
 
        if (info.assembly.name) {
-               image = mono_image_loaded (info.assembly.name);
+               assembly = mono_assembly_loaded (&info.assembly);
                /* do we need to load if it's not already loaded? */
-               if (!image) {
+               if (!assembly) {
                        g_list_free (info.modifiers);
                        g_list_free (info.nested);
                        return NULL;
                }
+               else
+                       image = assembly->image;
        } else if (image == NULL) {
                image = mono_defaults.corlib;
        }
@@ -4728,12 +5638,15 @@ handle_type:
                        g_warning ("Cannot load type '%s'", n);
                g_free (n);
                *end = p + slen;
-               return mono_type_get_object (mono_domain_get (), t);
+               if (t)
+                       return mono_type_get_object (mono_domain_get (), t);
+               else
+                       return NULL;
        }
        case MONO_TYPE_OBJECT: {
                char subt = *p++;
                MonoObject *obj;
-               MonoClass *subc;
+               MonoClass *subc = NULL;
                void *val;
 
                if (subt == 0x50) {
@@ -4940,10 +5853,17 @@ create_custom_attr (MonoImage *image, MonoMethod *method,
        MonoObject *attr;
        void **params;
 
+       mono_class_init (method->klass);
+
+       if (len == 0) {
+               attr = mono_object_new (mono_domain_get (), method->klass);
+               mono_runtime_invoke (method, attr, NULL, NULL);
+               return attr;
+       }
+
        if (len < 2 || read16 (p) != 0x0001) /* Prolog */
                return NULL;
 
-       mono_class_init (method->klass);
        /*g_print ("got attr %s\n", method->klass->name);*/
        
        params = g_new (void*, method->signature->param_count);
@@ -4976,6 +5896,10 @@ create_custom_attr (MonoImage *image, MonoMethod *method,
                        named += type_len;
                        /* FIXME: lookup the type and check type consistency */
                }
+               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);
@@ -5119,6 +6043,20 @@ mono_custom_attrs_from_assembly (MonoAssembly *assembly)
        return mono_custom_attrs_from_index (assembly->image, idx);
 }
 
+static MonoCustomAttrInfo*
+mono_custom_attrs_from_module (MonoImage *image)
+{
+       MonoCustomAttrInfo *cinfo;
+       guint32 idx;
+       
+       if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
+               return cinfo;
+       idx = 1; /* there is only one module */
+       idx <<= CUSTOM_ATTR_BITS;
+       idx |= CUSTOM_ATTR_MODULE;
+       return mono_custom_attrs_from_index (image, idx);
+}
+
 MonoCustomAttrInfo*
 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
 {
@@ -5168,10 +6106,15 @@ mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
        guint32 i, idx, method_index;
        guint32 param_list, param_last, param_pos, found;
        MonoImage *image;
-       
-       /* FIXME: handle dynamic custom attrs for parameters */
-       /*if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
-               return cinfo;*/
+       MonoReflectionMethodAux *aux;
+
+       if (method->klass->image->dynamic) {
+               aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
+               if (!aux || !aux->param_cattr)
+                       return NULL;
+               return aux->param_cattr [param];
+       }
+
        image = method->klass->image;
        method_index = find_method_index (method);
        ca = &image->tables [MONO_TABLE_METHOD];
@@ -5218,7 +6161,7 @@ mono_reflection_get_custom_attrs (MonoObject *obj)
 {
        MonoClass *klass;
        MonoArray *result;
-       MonoCustomAttrInfo *cinfo;
+       MonoCustomAttrInfo *cinfo = NULL;
        
        MONO_ARCH_SAVE_REGS;
 
@@ -5231,15 +6174,18 @@ mono_reflection_get_custom_attrs (MonoObject *obj)
        } else if (strcmp ("Assembly", klass->name) == 0) {
                MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
                cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
+       } else if (strcmp ("Module", klass->name) == 0) {
+               MonoReflectionModule *module = (MonoReflectionModule*)obj;
+               cinfo = mono_custom_attrs_from_module (module->image);
        } else if (strcmp ("MonoProperty", klass->name) == 0) {
                MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
-               cinfo = mono_custom_attrs_from_property (rprop->klass, rprop->property);
+               cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
        } else if (strcmp ("MonoEvent", klass->name) == 0) {
                MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
-               cinfo = mono_custom_attrs_from_event (revent->klass, revent->event);
+               cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
        } else if (strcmp ("MonoField", klass->name) == 0) {
                MonoReflectionField *rfield = (MonoReflectionField*)obj;
-               cinfo = mono_custom_attrs_from_field (rfield->klass, rfield->field);
+               cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
        } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
                MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
                cinfo = mono_custom_attrs_from_method (rmethod->method);
@@ -5250,6 +6196,9 @@ mono_reflection_get_custom_attrs (MonoObject *obj)
        } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
                MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
                cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
+       } else if (strcmp ("TypeBuilder", klass->name) == 0) {
+               MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
+               cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
        } else { /* handle other types here... */
                g_error ("get custom attrs not yet supported for %s", klass->name);
        }
@@ -5302,6 +6251,17 @@ method_builder_to_signature (MonoReflectionMethodBuilder *method) {
        return sig;
 }
 
+static MonoMethodSignature*
+dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
+       MonoMethodSignature *sig;
+
+       sig = parameters_to_signature (method->parameters);
+       sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
+       sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
+       sig->generic_param_count = 0;
+       return sig;
+}
+
 static void
 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
 {
@@ -5335,27 +6295,6 @@ get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
        }
 }
 
-static char*
-type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
-       char *name, *result;
-       MonoClass *klass;
-       MonoAssembly *ta;
-
-       name = mono_type_get_name (type);
-       klass = my_mono_class_from_mono_type (type);
-       ta = klass->image->assembly;
-       if (ta == ass || klass->image == mono_defaults.corlib)
-               return name;
-
-       /* missing public key */
-       result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
-               name, ta->aname.name,
-               ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
-               ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
-       g_free (name);
-       return result;
-}
-
 static void
 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
 {
@@ -5613,6 +6552,8 @@ mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, Mo
                                g_free (str);
                        } else {
                                mono_metadata_encode_value (ptype->type, p, &p);
+                               if (ptype->type == MONO_TYPE_SZARRAY)
+                                       mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
                        }
                        len = strlen (pname);
                        mono_metadata_encode_value (len, p, &p);
@@ -5775,10 +6716,8 @@ mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
 
        for (i = 0; i < count; i++) {
                MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
-               klass->gen_params [i] = *gparam->param;
+               klass->gen_params [i] = *gparam->type.type->data.generic_param;
        }
-
-       ensure_runtime_vtable (klass);
 }
 
 /*
@@ -5843,8 +6782,7 @@ mono_marshal_spec_from_builder (MonoAssembly *assembly,
        case MONO_NATIVE_CUSTOM:
                if (minfo->marshaltyperef)
                        res->data.custom_data.custom_name =
-                               type_get_qualified_name (minfo->marshaltyperef->type, 
-                                                                                assembly);
+                               type_get_fully_qualified_name (minfo->marshaltyperef->type);
                if (minfo->mcookie)
                        res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
                break;
@@ -5858,8 +6796,8 @@ mono_marshal_spec_from_builder (MonoAssembly *assembly,
 
 static MonoMethod*
 reflection_methodbuilder_to_mono_method (MonoClass *klass,
-                                                                                ReflectionMethodBuilder *rmb,
-                                                                                MonoMethodSignature *sig)
+                                        ReflectionMethodBuilder *rmb,
+                                        MonoMethodSignature *sig)
 {
        MonoMethod *m;
        MonoMethodNormal *pm;
@@ -5871,6 +6809,9 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
            (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
                m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
        else 
+               if (rmb->refs)
+                       m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
+       else
                m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
 
        pm = (MonoMethodNormal*)m;
@@ -5881,7 +6822,8 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
        m->name = mono_string_to_utf8 (rmb->name);
        m->klass = klass;
        m->signature = sig;
-       m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
+       if (rmb->table_idx)
+               m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
 
        if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
                if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
@@ -5944,23 +6886,52 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                header->num_clauses = num_clauses;
                if (num_clauses) {
                        header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
-                                                                                                        rmb->ilgen,
-                                                                                                        num_clauses);
+                                                                rmb->ilgen,
+                                                                num_clauses);
+               }
+
+               if (rmb->generic_params) {
+                       int count = mono_array_length (rmb->generic_params);
+                       header->gen_params = g_new0 (MonoGenericParam, count);
+                       for (i = 0; i < count; i++) {
+                               MonoReflectionGenericParam *gp =
+                                       mono_array_get (rmb->generic_params,
+                                                       MonoReflectionGenericParam*, i);
+
+                               header->gen_params [i] = *gp->type.type->data.generic_param;
+                       }
                }
 
                pm->header = header;
        }
 
-       method_aux = g_new0 (MonoReflectionMethodAux, 1);
+       if (rmb->refs) {
+               MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
+               int i;
+
+               m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
+
+               for (i = 0; i < rmb->nrefs; ++i)
+                       mw->data = g_list_append (mw->data, rmb->refs [i]);
+       }
+
+       method_aux = NULL;
 
        /* Parameter names */
-       if (rmb->parameters) {
-               method_aux->param_names = g_new0 (char *, m->signature->param_count);
-               for (i = 0; i < m->signature->param_count; ++i) {
+       if (rmb->pinfo) {
+               if (!method_aux)
+                       method_aux = g_new0 (MonoReflectionMethodAux, 1);
+               method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
+               for (i = 0; i <= m->signature->param_count; ++i) {
                        MonoReflectionParamBuilder *pb;
-                       if ((pb = mono_array_get (rmb->parameters, MonoReflectionParamBuilder*, i))) {
+                       if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
                                if (pb->name)
                                        method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
+                               if (pb->cattrs) {
+                                       if (!method_aux->param_cattr)
+                                               method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
+                                       method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
+                               }
                        }
                }
        }
@@ -5979,10 +6950,14 @@ reflection_methodbuilder_to_mono_method (MonoClass *klass,
                                }
                        }
                }
-       if (specs != NULL)
+       if (specs != NULL) {
+               if (!method_aux)
+                       method_aux = g_new0 (MonoReflectionMethodAux, 1);
                method_aux->param_marshall = specs;
+       }
 
-       mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
+       if (klass->image->dynamic && method_aux)
+               mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
 
        return m;
 }      
@@ -6072,106 +7047,159 @@ fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder*
        return field;
 }
 
-static MonoReflectionInflatedMethod*
-inflated_method_get_object (MonoDomain *domain, MonoMethod *method, MonoReflectionMethod *declaring,
-                           MonoGenericInst *ginst)
-{
-       const char *cname;
-       MonoClass *klass, *refclass;
-       MonoReflectionInflatedMethod *ret;
-
-       refclass = method->klass;
-
-       CHECK_OBJECT (MonoReflectionInflatedMethod *, method, refclass);
-       if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
-               cname = "MonoInflatedCtor";
-       else
-               cname = "MonoInflatedMethod";
-       klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
-       g_assert (klass);
-
-       ret = (MonoReflectionInflatedMethod*)mono_object_new (domain, klass);
-       ret->rmethod.method = method;
-       ret->rmethod.name = mono_string_new (domain, method->name);
-       ret->rmethod.reftype = mono_type_get_object (domain, &refclass->byval_arg);
-       ret->declaring = declaring;
-       ret->ginst = ginst;
-       CACHE_OBJECT (method, ret, refclass);
-       return ret;
-}
-
-MonoReflectionGenericInst*
-mono_reflection_bind_generic_parameters (MonoReflectionType *type, MonoArray *types)
+static MonoType*
+do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
+                                           MonoType **types)
 {
-       static MonoClass *System_Reflection_MonoGenericInst;
+       MonoClass *klass;
+       MonoReflectionTypeBuilder *tb = NULL;
+       MonoGenericInst *ginst;
        MonoDomain *domain;
        MonoType *geninst;
-       MonoGenericInst *ginst;
-       MonoReflectionType *ptype;
-       MonoClass *klass, *iklass, *pklass;
-       MonoReflectionGenericInst *res, *parent = NULL;
-       int i;
-
-       domain = mono_object_domain (type);
+       int icount, i;
 
        klass = mono_class_from_mono_type (type->type);
-       if (!klass->gen_params && !klass->generic_inst)
+       if (!klass->gen_params && !klass->generic_inst &&
+           !(klass->nested_in && klass->nested_in->gen_params))
                return NULL;
 
-       if (!System_Reflection_MonoGenericInst) {
-               System_Reflection_MonoGenericInst = mono_class_from_name (
-                       mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
-               g_assert (System_Reflection_MonoGenericInst);
-       }
+       mono_loader_lock ();
 
-       if (klass->wastypebuilder && klass->reflection_info) {
-               MonoReflectionTypeBuilder *tb = klass->reflection_info;
+       domain = mono_object_domain (type);
+
+       ginst = g_new0 (MonoGenericInst, 1);
+
+       if (!klass->generic_inst) {
+               ginst->type_argc = type_argc;
+               ginst->type_argv = types;
 
-               ptype = tb->parent;
-               pklass = mono_class_from_mono_type (ptype->type);
+               for (i = 0; i < ginst->type_argc; ++i) {
+                       if (!ginst->is_open)
+                               ginst->is_open = mono_class_is_open_constructed_type (types [i]);
+               }
+
+               ginst->generic_type = &klass->byval_arg;
        } else {
-               pklass = klass->parent;
-               ptype = mono_type_get_object (domain, &pklass->byval_arg);
+               MonoGenericInst *kginst = klass->generic_inst;
+
+               ginst->type_argc = kginst->type_argc;
+               ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
+
+               for (i = 0; i < ginst->type_argc; i++) {
+                       MonoType *t = kginst->type_argv [i];
+
+                       if (t->type == MONO_TYPE_VAR)
+                               t = types [t->data.generic_param->num];
+
+                       if (!ginst->is_open)
+                               ginst->is_open = mono_class_is_open_constructed_type (t);
+
+                       ginst->type_argv [i] = t;
+               }
+
+               ginst->generic_type = kginst->generic_type;
        }
 
-       if (pklass && pklass->generic_inst)
-               parent = mono_reflection_bind_generic_parameters (ptype, types);
-       else if (!pklass)
-               pklass = mono_defaults.object_class;
+       geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
+       if (geninst) {
+               g_free (ginst);
+               mono_loader_unlock ();
+               return geninst;
+       }
+
+       ginst->context = g_new0 (MonoGenericContext, 1);
+       ginst->context->ginst = ginst;
 
        geninst = g_new0 (MonoType, 1);
        geninst->type = MONO_TYPE_GENERICINST;
-       geninst->data.generic_inst = ginst = g_new0 (MonoGenericInst, 1);
-       ginst->generic_type = &klass->byval_arg;
+       geninst->data.generic_inst = ginst;
 
-       ginst->type_argc = mono_array_length (types);
-       ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
-       for (i = 0; i < ginst->type_argc; ++i) {
-               MonoReflectionType *garg = mono_array_get (types, gpointer, i);
-               ginst->type_argv [i] = garg->type;
+       if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
+               tb = (MonoReflectionTypeBuilder *) type;
+
+               icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
+               ginst->is_dynamic = TRUE;
+       } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
+               MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
+               MonoReflectionType *rgt = rgi->generic_type;
+
+               g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
+               tb = (MonoReflectionTypeBuilder *) rgt;
+
+               icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
+               ginst->is_dynamic = TRUE;
+       } else
+               icount = klass->interface_count;
+
+       ginst->ifaces = g_new0 (MonoType *, icount);
+       ginst->count_ifaces = icount;
+
+       for (i = 0; i < icount; i++) {
+               MonoReflectionType *itype;
+
+               if (tb)
+                       itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
+               else
+                       itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
+               ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
+               if (!ginst->ifaces [i])
+                       ginst->ifaces [i] = itype->type;
        }
 
-       iklass = mono_class_from_generic (geninst, FALSE);
+       mono_class_create_generic (ginst);
 
-       mono_class_setup_parent (iklass, parent ? parent->klass : pklass);
-       mono_class_setup_mono_type (iklass);
+       g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
 
-       res = (MonoReflectionGenericInst *)mono_object_new (domain, System_Reflection_MonoGenericInst);
+       mono_loader_unlock ();
 
-       res->type.type = iklass->generic_inst;
-       res->klass = iklass;
-       res->parent = parent;
-       res->generic_type = type;
+       return geninst;
+}
 
-       return res;
+MonoType*
+mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
+{
+       MonoClass *klass, *pklass = NULL;
+       MonoReflectionType *parent = NULL;
+       MonoType *geninst;
+       MonoReflectionTypeBuilder *tb = NULL;
+       MonoGenericInst *ginst;
+       MonoDomain *domain;
+
+       domain = mono_object_domain (type);
+       klass = mono_class_from_mono_type (type->type);
+
+       if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
+               tb = (MonoReflectionTypeBuilder *) type;
+
+               if (tb->parent) {
+                       parent = tb->parent;
+                       pklass = mono_class_from_mono_type (parent->type);
+               }
+       } else {
+               pklass = klass->parent;
+               if (pklass)
+                       parent = mono_type_get_object (domain, &pklass->byval_arg);
+       }
+
+       geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
+       if (!geninst)
+               return NULL;
+
+       ginst = geninst->data.generic_inst;
+
+       if (pklass && pklass->generic_inst)
+               ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
+
+       return geninst;
 }
 
-MonoReflectionInflatedMethod*
+MonoReflectionMethod*
 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
 {
        MonoMethod *method, *inflated;
        MonoReflectionMethodBuilder *mb = NULL;
-       MonoGenericInst *ginst;
+       MonoGenericMethod *gmethod;
+       MonoGenericContext *context;
        int count, i;
 
        MONO_ARCH_SAVE_REGS;
@@ -6191,34 +7219,62 @@ mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, M
        if (count != mono_array_length (types))
                return NULL;
 
-       ginst = g_new0 (MonoGenericInst, 1);
-       ginst->generic_method = method;
-       ginst->type_argc = count;
-       ginst->type_argv = g_new0 (MonoType *, count);
+       gmethod = g_new0 (MonoGenericMethod, 1);
+       gmethod->mtype_argc = count;
+       gmethod->mtype_argv = g_new0 (MonoType *, count);
        for (i = 0; i < count; i++) {
                MonoReflectionType *garg = mono_array_get (types, gpointer, i);
-               ginst->type_argv [i] = garg->type;
+               gmethod->mtype_argv [i] = garg->type;
+       }
+
+       context = g_new0 (MonoGenericContext, 1);
+       context->ginst = method->klass->generic_inst;
+       context->gmethod = gmethod;
+
+       inflated = mono_class_inflate_generic_method (method, context, NULL);
+
+       return mono_method_get_object (
+               mono_object_domain (rmethod), inflated, NULL);
+}
+
+static MonoMethod *
+inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
+{
+       MonoGenericMethod *gmethod;
+       MonoGenericInst *ginst;
+       MonoGenericContext *context;
+       int i;
+
+       ginst = type->type.type->data.generic_inst;
+
+       gmethod = g_new0 (MonoGenericMethod, 1);
+       gmethod->reflection_info = obj;
+
+       gmethod->mtype_argc = method->signature->generic_param_count;
+       gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
+
+       for (i = 0; i < gmethod->mtype_argc; i++) {
+               MonoMethodNormal *mn = (MonoMethodNormal *) method;
+               MonoGenericParam *gparam = &mn->header->gen_params [i];
+
+               g_assert (gparam->pklass);
+               gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
        }
 
-       inflated = mono_class_inflate_generic_method (method, ginst);
+       context = g_new0 (MonoGenericContext, 1);
+       context->ginst = ginst;
+       context->gmethod = gmethod;
 
-       return inflated_method_get_object (mono_object_domain (rmethod), inflated, rmethod, ginst);
+       return mono_class_inflate_generic_method (method, context, ginst->klass);
 }
 
-MonoReflectionInflatedMethod*
-mono_reflection_inflate_method_or_ctor (MonoReflectionGenericInst *declaring_type,
-                                       MonoReflectionGenericInst *reflected_type,
-                                       MonoObject *obj)
+static MonoMethod *
+inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
 {
-       MonoGenericInst *ginst, *type_ginst;
-       MonoMethod *method, *inflated;
-       MonoReflectionInflatedMethod *res;
+       MonoMethod *method;
        MonoClass *klass;
 
-       MONO_ARCH_SAVE_REGS;
-
-       klass = mono_class_from_mono_type (reflected_type->type.type);
-       type_ginst = reflected_type->type.type->data.generic_inst;
+       klass = mono_class_from_mono_type (type->type.type);
 
        if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
                method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
@@ -6227,83 +7283,138 @@ mono_reflection_inflate_method_or_ctor (MonoReflectionGenericInst *declaring_typ
        else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
                 !strcmp (obj->vtable->klass->name, "MonoCMethod"))
                method = ((MonoReflectionMethod *) obj)->method;
-       else if (!strcmp (obj->vtable->klass->name, "MonoInflatedMethod") ||
-                !strcmp (obj->vtable->klass->name, "MonoInflatedCtor"))
-               method = ((MonoReflectionInflatedMethod *) obj)->rmethod.method;
-       else
+       else {
+               method = NULL; /* prevent compiler warning */
                g_assert_not_reached ();
+       }
 
-       ginst = g_new0 (MonoGenericInst, 1);
-       ginst->generic_method = method;
-       ginst->generic_type = reflected_type->type.type;
-       ginst->type_argc = type_ginst->type_argc;
-       ginst->type_argv = type_ginst->type_argv;
+       return inflate_mono_method (type, method, obj);
+}
 
-       ginst->klass = mono_class_from_generic (ginst->generic_type, FALSE);
+void
+mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
+                                        MonoArray *methods, MonoArray *ctors,
+                                        MonoArray *fields, MonoArray *properties,
+                                        MonoArray *events)
+{
+       MonoGenericInst *ginst;
+       MonoDynamicGenericInst *dginst;
+       MonoClass *klass, *gklass, *pklass;
+       int i;
 
-       inflated = mono_class_inflate_generic_method (method, ginst);
+       MONO_ARCH_SAVE_REGS;
 
-       res = inflated_method_get_object (
-               mono_object_domain (reflected_type), inflated, (MonoReflectionMethod *) obj, ginst);
+       klass = mono_class_from_mono_type (type->type.type);
+       ginst = type->type.type->data.generic_inst;
 
-       res->declaring_type = declaring_type;
-       res->reflected_type = reflected_type;
+       if (ginst->initialized)
+               return;
 
-       return res;
-}
+       dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
 
-MonoReflectionInflatedField*
-mono_reflection_inflate_field (MonoReflectionGenericInst *declaring_type,
-                              MonoReflectionGenericInst *reflected_type,
-                              MonoObject *obj)
-{
-       static MonoClass *System_Reflection_MonoInflatedField;
-       MonoGenericInst *ginst, *type_ginst;
-       MonoClassField *field, *inflated;
-       MonoReflectionInflatedField *res;
-       MonoDomain *domain;
-       MonoClass *klass;
+       gklass = mono_class_from_mono_type (ginst->generic_type);
+       mono_class_init (gklass);
 
-       MONO_ARCH_SAVE_REGS;
+       if (ginst->parent)
+               pklass = mono_class_from_mono_type (ginst->parent);
+       else
+               pklass = gklass->parent;
+
+       mono_class_setup_parent (klass, pklass);
+
+       dginst->count_methods = methods ? mono_array_length (methods) : 0;
+       dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
+       dginst->count_fields = fields ? mono_array_length (fields) : 0;
+       dginst->count_properties = properties ? mono_array_length (properties) : 0;
+       dginst->count_events = events ? mono_array_length (events) : 0;
 
-       if (!System_Reflection_MonoInflatedField) {
-               System_Reflection_MonoInflatedField = mono_class_from_name (
-                       mono_defaults.corlib, "System.Reflection", "MonoInflatedField");
-               g_assert (System_Reflection_MonoInflatedField);
+       dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
+       dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
+       dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
+       dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
+       dginst->events = g_new0 (MonoEvent, dginst->count_events);
+
+       for (i = 0; i < dginst->count_methods; i++) {
+               MonoObject *obj = mono_array_get (methods, gpointer, i);
+
+               dginst->methods [i] = inflate_method (type, obj);
        }
 
-       klass = mono_class_from_mono_type (reflected_type->type.type);
-       type_ginst = reflected_type->type.type->data.generic_inst;
+       for (i = 0; i < dginst->count_ctors; i++) {
+               MonoObject *obj = mono_array_get (ctors, gpointer, i);
 
-       if (!strcmp (obj->vtable->klass->name, "FieldBuilder")) {
-               field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
-       } else if (!strcmp (obj->vtable->klass->name, "MonoField"))
-               field = ((MonoReflectionField *) obj)->field;
-       else
-               g_assert_not_reached ();
+               dginst->ctors [i] = inflate_method (type, obj);
+       }
 
-       ginst = g_new0 (MonoGenericInst, 1);
-       ginst->generic_type = reflected_type->type.type;
-       ginst->type_argc = type_ginst->type_argc;
-       ginst->type_argv = type_ginst->type_argv;
-
-       inflated = g_new0 (MonoClassField, 1);
-       *inflated = *field;
-       inflated->type = mono_class_inflate_generic_type (field->type, ginst);
-
-       domain = mono_object_domain (obj);
-
-       res = (MonoReflectionInflatedField *)mono_object_new (domain, System_Reflection_MonoInflatedField);
-       res->declaring = field;
-       res->declaring_type = declaring_type;
-       res->reflected_type = reflected_type;
-       res->rfield.klass = klass;
-       res->rfield.field = inflated;
-       res->rfield.name = mono_string_new (domain, inflated->name);
-       res->rfield.attrs = inflated->type->attrs;
-       res->rfield.type = mono_type_get_object (domain, inflated->type);
-       CACHE_OBJECT (inflated, res, field->parent);
-       return res;
+       for (i = 0; i < dginst->count_fields; i++) {
+               MonoObject *obj = mono_array_get (fields, gpointer, i);
+               MonoClassField *field;
+
+               if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
+                       field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
+               else if (!strcmp (obj->vtable->klass->name, "MonoField"))
+                       field = ((MonoReflectionField *) obj)->field;
+               else {
+                       field = NULL; /* prevent compiler warning */
+                       g_assert_not_reached ();
+               }
+
+               dginst->fields [i] = *field;
+               dginst->fields [i].generic_type = field->type;
+               dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
+       }
+
+       for (i = 0; i < dginst->count_properties; i++) {
+               MonoObject *obj = mono_array_get (properties, gpointer, i);
+               MonoProperty *property = &dginst->properties [i];
+
+               if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
+                       MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
+
+                       property->parent = klass;
+                       property->attrs = pb->attrs;
+                       property->name = mono_string_to_utf8 (pb->name);
+                       if (pb->get_method)
+                               property->get = inflate_method (type, (MonoObject *) pb->get_method);
+                       if (pb->set_method)
+                               property->set = inflate_method (type, (MonoObject *) pb->set_method);
+               } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
+                       *property = *((MonoReflectionProperty *) obj)->property;
+
+                       if (property->get)
+                               property->get = inflate_mono_method (type, property->get, NULL);
+                       if (property->set)
+                               property->set = inflate_mono_method (type, property->set, NULL);
+               } else
+                       g_assert_not_reached ();
+       }
+
+       for (i = 0; i < dginst->count_events; i++) {
+               MonoObject *obj = mono_array_get (events, gpointer, i);
+               MonoEvent *event = &dginst->events [i];
+
+               if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
+                       MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
+
+                       event->parent = klass;
+                       event->attrs = eb->attrs;
+                       event->name = mono_string_to_utf8 (eb->name);
+                       if (eb->add_method)
+                               event->add = inflate_method (type, (MonoObject *) eb->add_method);
+                       if (eb->remove_method)
+                               event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
+               } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
+                       *event = *((MonoReflectionEvent *) obj)->event;
+
+                       if (event->add)
+                               event->add = inflate_mono_method (type, event->add, NULL);
+                       if (event->remove)
+                               event->remove = inflate_mono_method (type, event->remove, NULL);
+               } else
+                       g_assert_not_reached ();
+       }
+
+       ginst->initialized = TRUE;
 }
 
 static void
@@ -6319,13 +7430,13 @@ ensure_runtime_vtable (MonoClass *klass)
                ensure_runtime_vtable (klass->parent);
 
        num = tb->ctors? mono_array_length (tb->ctors): 0;
-       num += tb->methods? mono_array_length (tb->methods): 0;
+       num += tb->num_methods;
        klass->method.count = num;
        klass->methods = g_new (MonoMethod*, num);
        num = tb->ctors? mono_array_length (tb->ctors): 0;
        for (i = 0; i < num; ++i)
                klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
-       num = tb->methods? mono_array_length (tb->methods): 0;
+       num = tb->num_methods;
        j = i;
        for (i = 0; i < num; ++i)
                klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
@@ -6347,7 +7458,7 @@ ensure_runtime_vtable (MonoClass *klass)
        /* Overrides */
        onum = 0;
        if (tb->methods) {
-               for (i = 0; i < mono_array_length (tb->methods); ++i) {
+               for (i = 0; i < tb->num_methods; ++i) {
                        MonoReflectionMethodBuilder *mb = 
                                mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
                        if (mb->override_method)
@@ -6359,7 +7470,7 @@ ensure_runtime_vtable (MonoClass *klass)
 
        if (tb->methods) {
                onum = 0;
-               for (i = 0; i < mono_array_length (tb->methods); ++i) {
+               for (i = 0; i < tb->num_methods; ++i) {
                        MonoReflectionMethodBuilder *mb = 
                                mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
                        if (mb->override_method) {
@@ -6389,7 +7500,7 @@ typebuilder_setup_fields (MonoClass *klass)
        int i;
        guint32 len, idx;
 
-       klass->field.count = tb->fields? mono_array_length (tb->fields): 0;
+       klass->field.count = tb->num_fields;
        klass->field.first = 0;
        klass->field.last = klass->field.count;
 
@@ -6447,6 +7558,7 @@ typebuilder_setup_properties (MonoClass *klass)
        klass->properties = g_new0 (MonoProperty, klass->property.count);
        for (i = 0; i < klass->property.count; ++i) {
                pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
+               klass->properties [i].parent = klass;
                klass->properties [i].attrs = pb->attrs;
                klass->properties [i].name = mono_string_to_utf8 (pb->name);
                if (pb->get_method)
@@ -6456,6 +7568,38 @@ typebuilder_setup_properties (MonoClass *klass)
        }
 }
 
+MonoReflectionEvent *
+mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
+{
+       MonoEvent *event = g_new0 (MonoEvent, 1);
+       MonoClass *klass;
+       int j;
+
+       klass = my_mono_class_from_mono_type (tb->type.type);
+
+       event->parent = klass;
+       event->attrs = eb->attrs;
+       event->name = mono_string_to_utf8 (eb->name);
+       if (eb->add_method)
+               event->add = eb->add_method->mhandle;
+       if (eb->remove_method)
+               event->remove = eb->remove_method->mhandle;
+       if (eb->raise_method)
+               event->raise = eb->raise_method->mhandle;
+
+       if (eb->other_methods) {
+               event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
+               for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
+                       MonoReflectionMethodBuilder *mb = 
+                               mono_array_get (eb->other_methods,
+                                               MonoReflectionMethodBuilder*, j);
+                       event->other [j] = mb->mhandle;
+               }
+       }
+
+       return mono_event_get_object (mono_object_domain (tb), klass, event);
+}
+
 static void
 typebuilder_setup_events (MonoClass *klass)
 {
@@ -6470,6 +7614,7 @@ typebuilder_setup_events (MonoClass *klass)
        klass->events = g_new0 (MonoEvent, klass->event.count);
        for (i = 0; i < klass->event.count; ++i) {
                eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
+               klass->events [i].parent = klass;
                klass->events [i].attrs = eb->attrs;
                klass->events [i].name = mono_string_to_utf8 (eb->name);
                if (eb->add_method)
@@ -6509,7 +7654,6 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
         * nested_classes
         */
        klass->flags = tb->attrs;
-       klass->element_class = klass;
 
        if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
                /* No need to fully construct the type */
@@ -6545,38 +7689,29 @@ mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
        return res;
 }
 
-MonoReflectionType *
-mono_reflection_define_generic_parameter (MonoReflectionTypeBuilder *tb, MonoReflectionMethodBuilder *mb, guint32 index, MonoReflectionGenericParam *gparam)
+void
+mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
 {
-       MonoClass *klass;
-       MonoImage *image;
        MonoGenericParam *param;
-       int count, i;
-
-       param = gparam->param = g_new0 (MonoGenericParam, 1);
+       MonoImage *image;
 
-       if (mb)
-               tb = (MonoReflectionTypeBuilder *) mb->type;
+       MONO_ARCH_SAVE_REGS;
 
-       image = (MonoImage*)tb->module->dynamic_image;
+       param = g_new0 (MonoGenericParam, 1);
 
        param->method = NULL;
        param->name = mono_string_to_utf8 (gparam->name);
-       param->num = index;
-
-       count = gparam->constraints ? mono_array_length (gparam->constraints) : 0;
-       param->constraints = g_new0 (MonoClass *, count + 1);
-       for (i = 0; i < count; i++) {
-               MonoReflectionType *constraint = mono_array_get (gparam->constraints, MonoReflectionType *, i);
-
-               param->constraints [i] = mono_class_from_mono_type (constraint->type);
-       }
+       param->num = gparam->index;
 
-       klass = mono_class_from_generic_parameter (param, image, mb != NULL);
+       image = &gparam->tbuilder->module->dynamic_image->image;
+       mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
 
-       gparam->type = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
+       param->pklass->reflection_info = gparam;
 
-       return gparam->type;
+       gparam->type.type = g_new0 (MonoType, 1);
+       gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
+       gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
+       gparam->type.type->data.generic_param = param;
 }
 
 MonoArray *
@@ -6636,6 +7771,42 @@ mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
        return result;
 }
 
+void 
+mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
+{
+       ReflectionMethodBuilder rmb;
+       MonoMethodSignature *sig;
+       int i;
+
+       sig = dynamic_method_to_signature (mb);
+
+       reflection_methodbuilder_from_dynamic_method (&rmb, mb);
+
+       /*
+        * Resolve references.
+        */
+       rmb.nrefs = mb->nrefs;
+       rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
+       for (i = 0; i < mb->nrefs; ++i) {
+               gpointer ref = resolve_object (mb->module->image, 
+                                              mono_array_get (mb->refs, MonoObject*, i));
+               if (!ref) {
+                       g_free (rmb.refs);
+                       mono_raise_exception (mono_get_exception_type_load (NULL));
+                       return;
+               }
+               rmb.refs [i] = ref;
+       }               
+
+       /* FIXME: class */
+       mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
+
+       g_free (rmb.refs);
+
+       /* ilgen is no longer needed */
+       mb->ilgen = NULL;
+}
+
 /**
  * mono_reflection_lookup_dynamic_token:
  *
@@ -6647,11 +7818,18 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
 {
        MonoDynamicImage *assembly = (MonoDynamicImage*)image;
        MonoObject *obj;
-       gpointer result;
 
        obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
        g_assert (obj);
 
+       return resolve_object (image, obj);
+}
+
+static gpointer
+resolve_object (MonoImage *image, MonoObject *obj)
+{
+       gpointer result = NULL;
+
        if (strcmp (obj->vtable->klass->name, "String") == 0) {
                result = mono_string_intern ((MonoString*)obj);
                g_assert (result);
@@ -6768,8 +7946,3 @@ mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
        }
        return result;
 }
-
-
-
-
-