2004-09-23 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
8  *
9  */
10 #include <config.h>
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
22 #include <stdio.h>
23 #include <glib.h>
24 #include <errno.h>
25 #include <time.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include "image.h"
29 #include "cil-coff.h"
30 #include "rawbuffer.h"
31 #include "mono-endian.h"
32 #include "private.h"
33 #include <mono/os/gc_wrapper.h>
34
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA  0x00002000
40
41 typedef struct {
42         MonoReflectionILGen *ilgen;
43         MonoReflectionType *rtype;
44         MonoArray *parameters;
45         MonoArray *generic_params;
46         MonoArray *pinfo;
47         MonoArray *opt_types;
48         guint32 attrs;
49         guint32 iattrs;
50         guint32 call_conv;
51         guint32 *table_idx; /* note: it's a pointer */
52         MonoArray *code;
53         MonoObject *type;
54         MonoString *name;
55         MonoBoolean init_locals;
56         MonoArray *return_modreq;
57         MonoArray *return_modopt;
58         MonoArray *param_modreq;
59         MonoArray *param_modopt;
60         MonoArray *permissions;
61         MonoMethod *mhandle;
62         guint32 nrefs;
63         gpointer *refs;
64         /* for PInvoke */
65         int charset, lasterr, native_cc;
66         MonoString *dll, *dllentry;
67 } ReflectionMethodBuilder;
68
69 typedef struct {
70         guint32 owner;
71         MonoReflectionGenericParam *gparam;
72 } GenericParamTableEntry;
73
74 const unsigned char table_sizes [64] = {
75         MONO_MODULE_SIZE,
76         MONO_TYPEREF_SIZE,
77         MONO_TYPEDEF_SIZE,
78         0,
79         MONO_FIELD_SIZE,
80         0,
81         MONO_METHOD_SIZE,
82         0,
83         MONO_PARAM_SIZE,
84         MONO_INTERFACEIMPL_SIZE,
85         MONO_MEMBERREF_SIZE,    /* 0x0A */
86         MONO_CONSTANT_SIZE,
87         MONO_CUSTOM_ATTR_SIZE,
88         MONO_FIELD_MARSHAL_SIZE,
89         MONO_DECL_SECURITY_SIZE,
90         MONO_CLASS_LAYOUT_SIZE,
91         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
92         MONO_STAND_ALONE_SIGNATURE_SIZE,
93         MONO_EVENT_MAP_SIZE,
94         0,
95         MONO_EVENT_SIZE,
96         MONO_PROPERTY_MAP_SIZE,
97         0,
98         MONO_PROPERTY_SIZE,
99         MONO_METHOD_SEMA_SIZE,
100         MONO_METHODIMPL_SIZE,
101         MONO_MODULEREF_SIZE,    /* 0x1A */
102         MONO_TYPESPEC_SIZE,
103         MONO_IMPLMAP_SIZE,      
104         MONO_FIELD_RVA_SIZE,
105         0,
106         0,
107         MONO_ASSEMBLY_SIZE,     /* 0x20 */
108         MONO_ASSEMBLY_PROCESSOR_SIZE,
109         MONO_ASSEMBLYOS_SIZE,
110         MONO_ASSEMBLYREF_SIZE,
111         MONO_ASSEMBLYREFPROC_SIZE,
112         MONO_ASSEMBLYREFOS_SIZE,
113         MONO_FILE_SIZE,
114         MONO_EXP_TYPE_SIZE,
115         MONO_MANIFEST_SIZE,
116         MONO_NESTED_CLASS_SIZE,
117
118         MONO_GENERICPARAM_SIZE, /* 0x2A */
119         MONO_METHODSPEC_SIZE,
120         MONO_GENPARCONSTRAINT_SIZE,
121
122         0       /* 0x2D */
123 };
124
125 /**
126  * These macros can be used to allocate long living atomic data so it won't be
127  * tracked by the garbage collector. We use libgc because it's apparently faster
128  * than g_malloc.
129  */
130 #ifdef HAVE_BOEHM_GC
131 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
132 #define FREE_ATOMIC(ptr)
133 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
134 #else
135 #define ALLOC_ATOMIC(size) g_malloc (size)
136 #define FREE_ATOMIC(ptr) g_free (ptr)
137 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
138 #endif
139
140 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
141 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
142 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
143 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
144 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
145 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
146 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
147 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
148 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
149 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
150 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
151 static void    ensure_runtime_vtable (MonoClass *klass);
152 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
153 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
154 static guint32 type_get_signature_size (MonoType *type);
155 static void get_default_param_value_blobs (MonoMethod *method, char **blobs);
156 static MonoObject *mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob);
157
158
159 static void
160 alloc_table (MonoDynamicTable *table, guint nrows)
161 {
162         table->rows = nrows;
163         g_assert (table->columns);
164         if (nrows + 1 >= table->alloc_rows) {
165                 while (nrows + 1 >= table->alloc_rows) {
166                         if (table->alloc_rows == 0)
167                                 table->alloc_rows = 16;
168                         else
169                                 table->alloc_rows *= 2;
170                 }
171
172                 if (table->values)
173                         table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
174                 else
175                         table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
176         }
177 }
178
179 static void
180 make_room_in_stream (MonoDynamicStream *stream, int size)
181 {
182         while (stream->alloc_size <= size) {
183                 if (stream->alloc_size < 4096)
184                         stream->alloc_size = 4096;
185                 else
186                         stream->alloc_size *= 2;
187         }
188         if (stream->data)
189                 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
190         else
191                 stream->data = ALLOC_ATOMIC (stream->alloc_size);
192 }       
193
194 static guint32
195 string_heap_insert (MonoDynamicStream *sh, const char *str)
196 {
197         guint32 idx;
198         guint32 len;
199         gpointer oldkey, oldval;
200
201         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
202                 return GPOINTER_TO_UINT (oldval);
203
204         len = strlen (str) + 1;
205         idx = sh->index;
206         if (idx + len > sh->alloc_size)
207                 make_room_in_stream (sh, idx + len);
208
209         /*
210          * We strdup the string even if we already copy them in sh->data
211          * so that the string pointers in the hash remain valid even if
212          * we need to realloc sh->data. We may want to avoid that later.
213          */
214         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
215         memcpy (sh->data + idx, str, len);
216         sh->index += len;
217         return idx;
218 }
219
220 static void
221 string_heap_init (MonoDynamicStream *sh)
222 {
223         sh->index = 0;
224         sh->alloc_size = 4096;
225         sh->data = ALLOC_ATOMIC (4096);
226         sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
227         string_heap_insert (sh, "");
228 }
229
230 #if 0 /* never used */
231 static void
232 string_heap_free (MonoDynamicStream *sh)
233 {
234         FREE_ATOMIC (sh->data);
235         g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
236         g_hash_table_destroy (sh->hash);
237 }
238 #endif
239
240 static guint32
241 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
242 {
243         guint32 idx;
244         if (stream->alloc_size < stream->index + len)
245                 make_room_in_stream (stream, stream->index + len);
246         memcpy (stream->data + stream->index, data, len);
247         idx = stream->index;
248         stream->index += len;
249         /* 
250          * align index? Not without adding an additional param that controls it since
251          * we may store a blob value in pieces.
252          */
253         return idx;
254 }
255
256 static guint32
257 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
258 {
259         guint32 idx;
260         if (stream->alloc_size < stream->index + len)
261                 make_room_in_stream (stream, stream->index + len);
262         memset (stream->data + stream->index, 0, len);
263         idx = stream->index;
264         stream->index += len;
265         return idx;
266 }
267
268 static void
269 stream_data_align (MonoDynamicStream *stream)
270 {
271         char buf [4] = {0};
272         guint32 count = stream->index % 4;
273
274         /* we assume the stream data will be aligned */
275         if (count)
276                 mono_image_add_stream_data (stream, buf, 4 - count);
277 }
278
279 static int
280 mono_blob_entry_hash (const char* str)
281 {
282         guint len, h;
283         const char *end;
284         len = mono_metadata_decode_blob_size (str, &str);
285         if (len > 0) {
286                 end = str + len;
287                 h = *str;
288                 for (str += 1; str < end; str++)
289                         h = (h << 5) - h + *str;
290                 return h;
291         } else {
292                 return 0;
293         }
294 }
295
296 static gboolean
297 mono_blob_entry_equal (const char *str1, const char *str2) {
298         int len, len2;
299         const char *end1;
300         const char *end2;
301         len = mono_metadata_decode_blob_size (str1, &end1);
302         len2 = mono_metadata_decode_blob_size (str2, &end2);
303         if (len != len2)
304                 return 0;
305         return memcmp (end1, end2, len) == 0;
306 }
307
308 static guint32
309 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
310 {
311         guint32 idx;
312         char *copy;
313         gpointer oldkey, oldval;
314         
315         copy = ALLOC_ATOMIC (s1+s2);
316         memcpy (copy, b1, s1);
317         memcpy (copy + s1, b2, s2);
318         if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
319                 FREE_ATOMIC (copy);
320                 idx = GPOINTER_TO_UINT (oldval);
321         } else {
322                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
323                 mono_image_add_stream_data (&assembly->blob, b2, s2);
324                 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
325         }
326         return idx;
327 }
328
329 /*
330  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
331  * dest may be misaligned.
332  */
333 static void
334 swap_with_size (char *dest, const char* val, int len, int nelem) {
335 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
336         int elem;
337
338         for (elem = 0; elem < nelem; ++elem) {
339                 switch (len) {
340                 case 1:
341                         *dest = *val;
342                         break;
343                 case 2:
344                         dest [0] = val [1];
345                         dest [1] = val [0];
346                         break;
347                 case 4:
348                         dest [0] = val [3];
349                         dest [1] = val [2];
350                         dest [2] = val [1];
351                         dest [3] = val [0];
352                         break;
353                 case 8:
354                         dest [0] = val [7];
355                         dest [1] = val [6];
356                         dest [2] = val [5];
357                         dest [3] = val [4];
358                         dest [4] = val [3];
359                         dest [5] = val [2];
360                         dest [6] = val [1];
361                         dest [7] = val [0];
362                         break;
363                 default:
364                         g_assert_not_reached ();
365                 }
366                 dest += len;
367                 val += len;
368         }
369 #else
370         memcpy (dest, val, len * nelem);
371 #endif
372 }
373
374 static guint32
375 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
376 {
377         char blob_size [64];
378         char *b = blob_size;
379         guint32 idx = 0, len;
380
381         len = str->length * 2;
382         mono_metadata_encode_value (len, b, &b);
383 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
384         {
385                 char *swapped = g_malloc (2 * mono_string_length (str));
386                 const char *p = (const char*)mono_string_chars (str);
387
388                 swap_with_size (swapped, p, 2, mono_string_length (str));
389                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
390                 g_free (swapped);
391         }
392 #else
393         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
394 #endif
395         return idx;
396 }
397
398 /* modified version needed to handle building corlib */
399 static MonoClass*
400 my_mono_class_from_mono_type (MonoType *type) {
401         switch (type->type) {
402         case MONO_TYPE_ARRAY:
403         case MONO_TYPE_PTR:
404         case MONO_TYPE_SZARRAY:
405         case MONO_TYPE_GENERICINST:
406                 return mono_class_from_mono_type (type);
407         case MONO_TYPE_VAR:
408         case MONO_TYPE_MVAR:
409                 g_assert (type->data.generic_param->pklass);
410                 return type->data.generic_param->pklass;
411         default:
412                 /* should be always valid when we reach this case... */
413                 return type->data.klass;
414         }
415 }
416
417 static MonoClass *
418 default_class_from_mono_type (MonoType *type)
419 {
420         switch (type->type) {
421         case MONO_TYPE_OBJECT:
422                 return mono_defaults.object_class;
423         case MONO_TYPE_VOID:
424                 return mono_defaults.void_class;
425         case MONO_TYPE_BOOLEAN:
426                 return mono_defaults.boolean_class;
427         case MONO_TYPE_CHAR:
428                 return mono_defaults.char_class;
429         case MONO_TYPE_I1:
430                 return mono_defaults.sbyte_class;
431         case MONO_TYPE_U1:
432                 return mono_defaults.byte_class;
433         case MONO_TYPE_I2:
434                 return mono_defaults.int16_class;
435         case MONO_TYPE_U2:
436                 return mono_defaults.uint16_class;
437         case MONO_TYPE_I4:
438                 return mono_defaults.int32_class;
439         case MONO_TYPE_U4:
440                 return mono_defaults.uint32_class;
441         case MONO_TYPE_I:
442                 return mono_defaults.int_class;
443         case MONO_TYPE_U:
444                 return mono_defaults.uint_class;
445         case MONO_TYPE_I8:
446                 return mono_defaults.int64_class;
447         case MONO_TYPE_U8:
448                 return mono_defaults.uint64_class;
449         case MONO_TYPE_R4:
450                 return mono_defaults.single_class;
451         case MONO_TYPE_R8:
452                 return mono_defaults.double_class;
453         case MONO_TYPE_STRING:
454                 return mono_defaults.string_class;
455         default:
456                 g_warning ("implement me 0x%02x\n", type->type);
457                 g_assert_not_reached ();
458         }
459         
460         return NULL;
461 }
462
463 static void
464 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
465 {
466         int i;
467
468         if (!ginst) {
469                 g_assert_not_reached ();
470                 return;
471         }
472
473         mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
474         encode_type (assembly, ginst->generic_type, p, &p);
475         mono_metadata_encode_value (ginst->type_argc, p, &p);
476         for (i = 0; i < ginst->type_argc; ++i)
477                 encode_type (assembly, ginst->type_argv [i], p, &p);
478
479         *endbuf = p;
480 }
481
482 static void
483 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
484 {
485         if (!type) {
486                 g_assert_not_reached ();
487                 return;
488         }
489                 
490         if (type->byref)
491                 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
492
493         switch (type->type){
494         case MONO_TYPE_VOID:
495         case MONO_TYPE_BOOLEAN:
496         case MONO_TYPE_CHAR:
497         case MONO_TYPE_I1:
498         case MONO_TYPE_U1:
499         case MONO_TYPE_I2:
500         case MONO_TYPE_U2:
501         case MONO_TYPE_I4:
502         case MONO_TYPE_U4:
503         case MONO_TYPE_I8:
504         case MONO_TYPE_U8:
505         case MONO_TYPE_R4:
506         case MONO_TYPE_R8:
507         case MONO_TYPE_I:
508         case MONO_TYPE_U:
509         case MONO_TYPE_STRING:
510         case MONO_TYPE_OBJECT:
511         case MONO_TYPE_TYPEDBYREF:
512                 mono_metadata_encode_value (type->type, p, &p);
513                 break;
514         case MONO_TYPE_PTR:
515                 mono_metadata_encode_value (type->type, p, &p);
516                 encode_type (assembly, type->data.type, p, &p);
517                 break;
518         case MONO_TYPE_SZARRAY:
519                 mono_metadata_encode_value (type->type, p, &p);
520                 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
521                 break;
522         case MONO_TYPE_VALUETYPE:
523         case MONO_TYPE_CLASS: {
524                 MonoClass *k = mono_class_from_mono_type (type);
525                 mono_metadata_encode_value (type->type, p, &p);
526                 /*
527                  * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
528                  * otherwise two typerefs could point to the same type, leading to
529                  * verification errors.
530                  */
531                 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
532                 break;
533         }
534         case MONO_TYPE_ARRAY:
535                 mono_metadata_encode_value (type->type, p, &p);
536                 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
537                 mono_metadata_encode_value (type->data.array->rank, p, &p);
538                 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
539                 mono_metadata_encode_value (0, p, &p);
540                 break;
541         case MONO_TYPE_GENERICINST:
542                 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
543                 break;
544         case MONO_TYPE_VAR:
545         case MONO_TYPE_MVAR:
546                 mono_metadata_encode_value (type->type, p, &p);
547                 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
548                 break;
549         default:
550                 g_error ("need to encode type %x", type->type);
551         }
552         *endbuf = p;
553 }
554
555 static void
556 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
557 {
558         if (!type) {
559                 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
560                 return;
561         }
562         if (type->type) {
563                 encode_type (assembly, type->type, p, endbuf);
564                 return;
565         }
566
567         g_assert_not_reached ();
568
569 }
570
571 static void
572 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
573 {
574         int i;
575
576         if (modreq) {
577                 for (i = 0; i < mono_array_length (modreq); ++i) {
578                         MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
579                         *p = MONO_TYPE_CMOD_REQD;
580                         p++;
581                         mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
582                 }
583         }
584         if (modopt) {
585                 for (i = 0; i < mono_array_length (modopt); ++i) {
586                         MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
587                         *p = MONO_TYPE_CMOD_OPT;
588                         p++;
589                         mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
590                 }
591         }
592         *endbuf = p;
593 }
594
595 static guint32
596 generic_inst_get_signature_size (MonoGenericInst *ginst)
597 {
598         guint32 size = 0;
599         int i;
600
601         if (!ginst) {
602                 g_assert_not_reached ();
603         }
604
605         size += 1 + type_get_signature_size (ginst->generic_type);
606         size += 4;
607         for (i = 0; i < ginst->type_argc; ++i)
608                 size += type_get_signature_size (ginst->type_argv [i]);
609
610         return size;
611 }
612
613 static guint32
614 type_get_signature_size (MonoType *type)
615 {
616         guint32 size = 0;
617
618         if (!type) {
619                 g_assert_not_reached ();
620         }
621                 
622         if (type->byref)
623                 size++;
624
625         switch (type->type){
626         case MONO_TYPE_VOID:
627         case MONO_TYPE_BOOLEAN:
628         case MONO_TYPE_CHAR:
629         case MONO_TYPE_I1:
630         case MONO_TYPE_U1:
631         case MONO_TYPE_I2:
632         case MONO_TYPE_U2:
633         case MONO_TYPE_I4:
634         case MONO_TYPE_U4:
635         case MONO_TYPE_I8:
636         case MONO_TYPE_U8:
637         case MONO_TYPE_R4:
638         case MONO_TYPE_R8:
639         case MONO_TYPE_I:
640         case MONO_TYPE_U:
641         case MONO_TYPE_STRING:
642         case MONO_TYPE_OBJECT:
643         case MONO_TYPE_TYPEDBYREF:
644                 return size + 1;
645         case MONO_TYPE_PTR:
646                 return size + 1 + type_get_signature_size (type->data.type);
647         case MONO_TYPE_SZARRAY:
648                 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
649         case MONO_TYPE_VALUETYPE:
650         case MONO_TYPE_CLASS:
651                 return size + 5;
652         case MONO_TYPE_ARRAY:
653                 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
654         case MONO_TYPE_GENERICINST:
655                 return size + generic_inst_get_signature_size (type->data.generic_inst);
656         case MONO_TYPE_VAR:
657         case MONO_TYPE_MVAR:
658                 return size + 5;
659         default:
660                 g_error ("need to encode type %x", type->type);
661                 return size;
662         }
663 }
664
665 static guint32
666 method_get_signature_size (MonoMethodSignature *sig)
667 {
668         guint32 size;
669         int i;
670
671         size = type_get_signature_size (sig->ret);
672         for (i = 0; i < sig->param_count; i++)
673                 size += type_get_signature_size (sig->params [i]);
674
675         if (sig->generic_param_count)
676                 size += 4;
677         if (sig->sentinelpos >= 0)
678                 size++;
679
680         return size;    
681 }
682
683 static guint32
684 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
685 {
686         char *buf;
687         char *p;
688         int i;
689         guint32 nparams =  sig->param_count;
690         guint32 size = 11 + method_get_signature_size (sig);
691         guint32 idx;
692         char blob_size [6];
693         char *b = blob_size;
694
695         if (!assembly->save)
696                 return 0;
697
698         p = buf = g_malloc (size);
699         /*
700          * FIXME: vararg, explicit_this, differenc call_conv values...
701          */
702         *p = sig->call_convention;
703         if (sig->hasthis)
704                 *p |= 0x20; /* hasthis */
705         if (sig->generic_param_count)
706                 *p |= 0x10; /* generic */
707         p++;
708         if (sig->generic_param_count)
709                 mono_metadata_encode_value (sig->generic_param_count, p, &p);
710         mono_metadata_encode_value (nparams, p, &p);
711         encode_type (assembly, sig->ret, p, &p);
712         for (i = 0; i < nparams; ++i) {
713                 if (i == sig->sentinelpos)
714                         *p++ = MONO_TYPE_SENTINEL;
715                 encode_type (assembly, sig->params [i], p, &p);
716         }
717         /* store length */
718         g_assert (p - buf < size);
719         mono_metadata_encode_value (p-buf, b, &b);
720         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
721         g_free (buf);
722         return idx;
723 }
724
725 static guint32
726 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
727 {
728         /*
729          * FIXME: reuse code from method_encode_signature().
730          */
731         char *buf;
732         char *p;
733         int i;
734         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
735         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
736         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
737         guint32 size = 21 + nparams * 20 + notypes * 20;
738         guint32 idx;
739         char blob_size [6];
740         char *b = blob_size;
741
742         p = buf = g_malloc (size);
743         /* LAMESPEC: all the call conv spec is foobared */
744         *p = mb->call_conv & 0x60; /* has-this, explicit-this */
745         if (mb->call_conv & 2)
746                 *p |= 0x5; /* vararg */
747         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
748                 *p |= 0x20; /* hasthis */
749         if (ngparams)
750                 *p |= 0x10; /* generic */
751         p++;
752         if (ngparams)
753                 mono_metadata_encode_value (ngparams, p, &p);
754         mono_metadata_encode_value (nparams + notypes, p, &p);
755         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
756         encode_reflection_type (assembly, mb->rtype, p, &p);
757         for (i = 0; i < nparams; ++i) {
758                 MonoArray *modreq = NULL;
759                 MonoArray *modopt = NULL;
760                 MonoReflectionType *pt;
761
762                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
763                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
764                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
765                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
766                 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
767                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
768                 encode_reflection_type (assembly, pt, p, &p);
769         }
770         if (notypes)
771                 *p++ = MONO_TYPE_SENTINEL;
772         for (i = 0; i < notypes; ++i) {
773                 MonoReflectionType *pt;
774
775                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
776                 encode_reflection_type (assembly, pt, p, &p);
777         }
778
779         /* store length */
780         g_assert (p - buf < size);
781         mono_metadata_encode_value (p-buf, b, &b);
782         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
783         g_free (buf);
784         return idx;
785 }
786
787 static guint32
788 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
789 {
790         MonoDynamicTable *table;
791         guint32 *values;
792         char *p;
793         guint32 idx, sig_idx, size;
794         guint nl = mono_array_length (ilgen->locals);
795         char *buf;
796         char blob_size [6];
797         char *b = blob_size;
798         int i;
799
800         size = 10 + nl * 10;
801         p = buf = g_malloc (size);
802         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
803         idx = table->next_idx ++;
804         table->rows ++;
805         alloc_table (table, table->rows);
806         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
807
808         mono_metadata_encode_value (0x07, p, &p);
809         mono_metadata_encode_value (nl, p, &p);
810         for (i = 0; i < nl; ++i) {
811                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
812                 
813                 if (lb->is_pinned)
814                         mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
815                 
816                 encode_reflection_type (assembly, lb->type, p, &p);
817         }
818         g_assert (p - buf < size);
819         mono_metadata_encode_value (p-buf, b, &b);
820         sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
821         g_free (buf);
822
823         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
824
825         return idx;
826 }
827
828 static guint32
829 method_count_clauses (MonoReflectionILGen *ilgen)
830 {
831         guint32 num_clauses = 0;
832         int i;
833
834         MonoILExceptionInfo *ex_info;
835         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
836                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
837                 if (ex_info->handlers)
838                         num_clauses += mono_array_length (ex_info->handlers);
839                 else
840                         num_clauses++;
841         }
842
843         return num_clauses;
844 }
845
846 static MonoExceptionClause*
847 method_encode_clauses (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
848 {
849         MonoExceptionClause *clauses;
850         MonoExceptionClause *clause;
851         MonoILExceptionInfo *ex_info;
852         MonoILExceptionBlock *ex_block;
853         guint32 finally_start;
854         int i, j, clause_index;;
855
856         clauses = g_new0 (MonoExceptionClause, num_clauses);
857
858         clause_index = 0;
859         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
860                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
861                 finally_start = ex_info->start + ex_info->len;
862                 g_assert (ex_info->handlers);
863                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
864                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
865                         clause = &(clauses [clause_index]);
866
867                         clause->flags = ex_block->type;
868                         clause->try_offset = ex_info->start;
869
870                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
871                                 clause->try_len = finally_start - ex_info->start;
872                         else
873                                 clause->try_len = ex_info->len;
874                         clause->handler_offset = ex_block->start;
875                         clause->handler_len = ex_block->len;
876                         clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
877                                 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
878                         if (ex_block->extype) {
879                                 mono_g_hash_table_insert (assembly->tokens,
880                                           GUINT_TO_POINTER (clause->token_or_filter), ex_block->extype);
881                         }
882                         finally_start = ex_block->start + ex_block->len;
883
884                         clause_index ++;
885                 }
886         }
887
888         return clauses;
889 }
890
891 static guint32
892 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
893 {
894         char flags = 0;
895         guint32 idx;
896         guint32 code_size;
897         gint32 max_stack, i;
898         gint32 num_locals = 0;
899         gint32 num_exception = 0;
900         gint maybe_small;
901         guint32 fat_flags;
902         char fat_header [12];
903         guint32 *intp;
904         guint16 *shortp;
905         guint32 local_sig = 0;
906         guint32 header_size = 12;
907         MonoArray *code;
908
909         if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
910                         (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
911                 return 0;
912
913         /*if (mb->name)
914                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
915         if (mb->ilgen) {
916                 code = mb->ilgen->code;
917                 code_size = mb->ilgen->code_len;
918                 max_stack = mb->ilgen->max_stack;
919                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
920                 if (mb->ilgen->ex_handlers)
921                         num_exception = method_count_clauses (mb->ilgen);
922         } else {
923                 code = mb->code;
924                 if (code == NULL){
925                         char *name = mono_string_to_utf8 (mb->name);
926                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
927                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
928                         g_free (str);
929                         g_free (name);
930                         mono_raise_exception (exception);
931                 }
932
933                 code_size = mono_array_length (code);
934                 max_stack = 8; /* we probably need to run a verifier on the code... */
935         }
936
937         /* check for exceptions, maxstack, locals */
938         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
939         if (maybe_small) {
940                 if (code_size < 64 && !(code_size & 1)) {
941                         flags = (code_size << 2) | 0x2;
942                 } else if (code_size < 32 && (code_size & 1)) {
943                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
944                 } else {
945                         goto fat_header;
946                 }
947                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
948                 /* add to the fixup todo list */
949                 if (mb->ilgen && mb->ilgen->num_token_fixups)
950                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
951                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
952                 return assembly->text_rva + idx;
953         } 
954 fat_header:
955         if (num_locals)
956                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
957         /* 
958          * FIXME: need to set also the header size in fat_flags.
959          * (and more sects and init locals flags)
960          */
961         fat_flags =  0x03;
962         if (num_exception)
963                 fat_flags |= METHOD_HEADER_MORE_SECTS;
964         if (mb->init_locals)
965                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
966         fat_header [0] = fat_flags;
967         fat_header [1] = (header_size / 4 ) << 4;
968         shortp = (guint16*)(fat_header + 2);
969         *shortp = GUINT16_TO_LE (max_stack);
970         intp = (guint32*)(fat_header + 4);
971         *intp = GUINT32_TO_LE (code_size);
972         intp = (guint32*)(fat_header + 8);
973         *intp = GUINT32_TO_LE (local_sig);
974         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
975         /* add to the fixup todo list */
976         if (mb->ilgen && mb->ilgen->num_token_fixups)
977                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
978         
979         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
980         if (num_exception) {
981                 unsigned char sheader [4];
982                 MonoExceptionClause clause;
983                 MonoILExceptionInfo * ex_info;
984                 MonoILExceptionBlock * ex_block;
985                 int j;
986
987                 stream_data_align (&assembly->code);
988                 /* always use fat format for now */
989                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
990                 num_exception *= sizeof (MonoExceptionClause);
991                 num_exception += 4; /* include the size of the header */
992                 sheader [1] = num_exception & 0xff;
993                 sheader [2] = (num_exception >> 8) & 0xff;
994                 sheader [3] = (num_exception >> 16) & 0xff;
995                 mono_image_add_stream_data (&assembly->code, sheader, 4);
996                 /* fat header, so we are already aligned */
997                 /* reverse order */
998                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
999                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1000                         if (ex_info->handlers) {
1001                                 int finally_start = ex_info->start + ex_info->len;
1002                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1003                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1004                                         clause.flags = GUINT32_TO_LE (ex_block->type);
1005                                         clause.try_offset = GUINT32_TO_LE (ex_info->start);
1006                                         /* need fault, too, probably */
1007                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1008                                                 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
1009                                         else
1010                                                 clause.try_len = GUINT32_TO_LE (ex_info->len);
1011                                         clause.handler_offset = GUINT32_TO_LE (ex_block->start);
1012                                         clause.handler_len = GUINT32_TO_LE (ex_block->len);
1013                                         finally_start = ex_block->start + ex_block->len;
1014                                         clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
1015                                                         mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
1016                                         clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
1017                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
1018                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1019                                         mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
1020                                 }
1021                         } else {
1022                                 g_error ("No clauses for ex info block %d", i);
1023                         }
1024                 }
1025         }
1026         return assembly->text_rva + idx;
1027 }
1028
1029 static guint32
1030 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1031 {
1032         int i;
1033         MonoDynamicTable *table;
1034         guint32 *values;
1035         
1036         table = &assembly->tables [table_idx];
1037
1038         g_assert (col < table->columns);
1039
1040         values = table->values + table->columns;
1041         for (i = 1; i <= table->rows; ++i) {
1042                 if (values [col] == token)
1043                         return i;
1044                 values += table->columns;
1045         }
1046         return 0;
1047 }
1048
1049 static GHashTable *dynamic_custom_attrs = NULL;
1050
1051 static MonoCustomAttrInfo*
1052 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
1053 {
1054         int i, count;
1055         MonoCustomAttrInfo *ainfo;
1056         MonoReflectionCustomAttr *cattr;
1057
1058         if (!cattrs)
1059                 return NULL;
1060         /* FIXME: check in assembly the Run flag is set */
1061
1062         count = mono_array_length (cattrs);
1063
1064         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
1065
1066         ainfo->image = image;
1067         ainfo->num_attrs = count;
1068         for (i = 0; i < count; ++i) {
1069                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1070                 ainfo->attrs [i].ctor = cattr->ctor->method;
1071                 /* FIXME: might want to memdup the data here */
1072                 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1073                 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1074         }
1075
1076         return ainfo;
1077 }
1078
1079 static void
1080 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1081 {
1082         MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1083
1084         if (!ainfo)
1085                 return;
1086
1087         if (!dynamic_custom_attrs)
1088                 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1089
1090         g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1091         ainfo->cached = TRUE;
1092 }
1093
1094 void
1095 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1096 {
1097         /* they are cached, so we don't free them */
1098         if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1099                 return;
1100         g_free (ainfo);
1101 }
1102
1103 /*
1104  * idx is the table index of the object
1105  * type is one of MONO_CUSTOM_ATTR_*
1106  */
1107 static void
1108 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1109 {
1110         MonoDynamicTable *table;
1111         MonoReflectionCustomAttr *cattr;
1112         guint32 *values;
1113         guint32 count, i, token;
1114         char blob_size [6];
1115         char *p = blob_size;
1116         
1117         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1118         if (!cattrs)
1119                 return;
1120         count = mono_array_length (cattrs);
1121         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1122         table->rows += count;
1123         alloc_table (table, table->rows);
1124         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1125         idx <<= MONO_CUSTOM_ATTR_BITS;
1126         idx |= type;
1127         for (i = 0; i < count; ++i) {
1128                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1129                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1130                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE);
1131                 type = mono_metadata_token_index (token);
1132                 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1133                 switch (mono_metadata_token_table (token)) {
1134                 case MONO_TABLE_METHOD:
1135                         type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1136                         break;
1137                 case MONO_TABLE_MEMBERREF:
1138                         type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1139                         break;
1140                 default:
1141                         g_warning ("got wrong token in custom attr");
1142                         continue;
1143                 }
1144                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1145                 p = blob_size;
1146                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1147                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1148                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1149                 values += MONO_CUSTOM_ATTR_SIZE;
1150                 ++table->next_idx;
1151         }
1152 }
1153
1154 static void
1155 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1156 {
1157         MonoDynamicTable *table;
1158         guint32 *values;
1159         guint32 count, i, idx;
1160         MonoReflectionPermissionSet *perm;
1161
1162         if (!permissions)
1163                 return;
1164
1165         count = mono_array_length (permissions);
1166         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1167         table->rows += count;
1168         alloc_table (table, table->rows);
1169
1170         for (i = 0; i < mono_array_length (permissions); ++i) {
1171                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1172
1173                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1174
1175                 idx = mono_metadata_token_index (parent_token);
1176                 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1177                 switch (mono_metadata_token_table (parent_token)) {
1178                 case MONO_TABLE_TYPEDEF:
1179                         idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1180                         break;
1181                 case MONO_TABLE_METHOD:
1182                         idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1183                         break;
1184                 case MONO_TABLE_ASSEMBLY:
1185                         idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1186                         break;
1187                 default:
1188                         g_assert_not_reached ();
1189                 }
1190
1191                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1192                 values [MONO_DECL_SECURITY_PARENT] = idx;
1193                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1194
1195                 ++table->next_idx;
1196         }
1197 }
1198
1199 /*
1200  * Fill in the MethodDef and ParamDef tables for a method.
1201  * This is used for both normal methods and constructors.
1202  */
1203 static void
1204 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1205 {
1206         MonoDynamicTable *table;
1207         guint32 *values;
1208         char *name;
1209         guint i, count;
1210
1211         /* room in this table is already allocated */
1212         table = &assembly->tables [MONO_TABLE_METHOD];
1213         *mb->table_idx = table->next_idx ++;
1214         mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1215         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1216         name = mono_string_to_utf8 (mb->name);
1217         values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1218         g_free (name);
1219         values [MONO_METHOD_FLAGS] = mb->attrs;
1220         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1221         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1222         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1223         
1224         table = &assembly->tables [MONO_TABLE_PARAM];
1225         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1226
1227         mono_image_add_decl_security (assembly, 
1228                 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1229
1230         if (mb->pinfo) {
1231                 MonoDynamicTable *mtable;
1232                 guint32 *mvalues;
1233                 
1234                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1235                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1236                 
1237                 count = 0;
1238                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1239                         if (mono_array_get (mb->pinfo, gpointer, i))
1240                                 count++;
1241                 }
1242                 table->rows += count;
1243                 alloc_table (table, table->rows);
1244                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1245                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1246                         MonoReflectionParamBuilder *pb;
1247                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1248                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1249                                 values [MONO_PARAM_SEQUENCE] = i;
1250                                 if (pb->name != NULL) {
1251                                         name = mono_string_to_utf8 (pb->name);
1252                                         values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1253                                         g_free (name);
1254                                 } else {
1255                                         values [MONO_PARAM_NAME] = 0;
1256                                 }
1257                                 values += MONO_PARAM_SIZE;
1258                                 if (pb->marshal_info) {
1259                                         mtable->rows++;
1260                                         alloc_table (mtable, mtable->rows);
1261                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1262                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1263                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1264                                 }
1265                                 pb->table_idx = table->next_idx++;
1266                                 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1267                                         guint32 field_type = 0;
1268                                         mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1269                                         mtable->rows ++;
1270                                         alloc_table (mtable, mtable->rows);
1271                                         mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1272                                         mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1273                                         mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1274                                         mvalues [MONO_CONSTANT_TYPE] = field_type;
1275                                         mvalues [MONO_CONSTANT_PADDING] = 0;
1276                                 }
1277                         }
1278                 }
1279         }
1280 }
1281
1282 static void
1283 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1284 {
1285         rmb->ilgen = mb->ilgen;
1286         rmb->rtype = mb->rtype;
1287         rmb->parameters = mb->parameters;
1288         rmb->generic_params = mb->generic_params;
1289         rmb->opt_types = NULL;
1290         rmb->pinfo = mb->pinfo;
1291         rmb->attrs = mb->attrs;
1292         rmb->iattrs = mb->iattrs;
1293         rmb->call_conv = mb->call_conv;
1294         rmb->code = mb->code;
1295         rmb->type = mb->type;
1296         rmb->name = mb->name;
1297         rmb->table_idx = &mb->table_idx;
1298         rmb->init_locals = mb->init_locals;
1299         rmb->return_modreq = mb->return_modreq;
1300         rmb->return_modopt = mb->return_modopt;
1301         rmb->param_modreq = mb->param_modreq;
1302         rmb->param_modopt = mb->param_modopt;
1303         rmb->permissions = mb->permissions;
1304         rmb->mhandle = mb->mhandle;
1305         rmb->nrefs = 0;
1306         rmb->refs = NULL;
1307
1308         if (mb->dll) {
1309                 rmb->charset = rmb->charset & 0xf;
1310                 rmb->lasterr = rmb->charset & 0x40;
1311                 rmb->native_cc = rmb->native_cc;
1312                 rmb->dllentry = mb->dllentry;
1313                 rmb->dll = mb->dll;
1314         }
1315 }
1316
1317 static void
1318 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1319 {
1320         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1321
1322         rmb->ilgen = mb->ilgen;
1323         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1324         rmb->parameters = mb->parameters;
1325         rmb->generic_params = NULL;
1326         rmb->opt_types = NULL;
1327         rmb->pinfo = mb->pinfo;
1328         rmb->attrs = mb->attrs;
1329         rmb->iattrs = mb->iattrs;
1330         rmb->call_conv = mb->call_conv;
1331         rmb->code = NULL;
1332         rmb->type = mb->type;
1333         rmb->name = mono_string_new (mono_domain_get (), name);
1334         rmb->table_idx = &mb->table_idx;
1335         rmb->init_locals = mb->init_locals;
1336         rmb->return_modreq = NULL;
1337         rmb->return_modopt = NULL;
1338         rmb->param_modreq = mb->param_modreq;
1339         rmb->param_modopt = mb->param_modopt;
1340         rmb->permissions = mb->permissions;
1341         rmb->mhandle = mb->mhandle;
1342         rmb->nrefs = 0;
1343         rmb->refs = NULL;
1344 }
1345
1346 static void
1347 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1348 {
1349         rmb->ilgen = mb->ilgen;
1350         rmb->rtype = mb->rtype;
1351         rmb->parameters = mb->parameters;
1352         rmb->generic_params = NULL;
1353         rmb->opt_types = NULL;
1354         rmb->pinfo = NULL;
1355         rmb->attrs = mb->attrs;
1356         rmb->iattrs = 0;
1357         rmb->call_conv = mb->call_conv;
1358         rmb->code = NULL;
1359         rmb->type = NULL;
1360         rmb->name = mb->name;
1361         rmb->table_idx = NULL;
1362         rmb->init_locals = mb->init_locals;
1363         rmb->return_modreq = NULL;
1364         rmb->return_modopt = NULL;
1365         rmb->param_modreq = NULL;
1366         rmb->param_modopt = NULL;
1367         rmb->permissions = NULL;
1368         rmb->mhandle = mb->mhandle;
1369         rmb->nrefs = 0;
1370         rmb->refs = NULL;
1371 }       
1372
1373 static void
1374 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1375 {
1376         MonoDynamicTable *table;
1377         guint32 *values;
1378         char *name;
1379         ReflectionMethodBuilder rmb;
1380         int i;
1381
1382         reflection_methodbuilder_from_method_builder (&rmb, mb);
1383
1384         mono_image_basic_method (&rmb, assembly);
1385
1386         if (mb->dll) { /* It's a P/Invoke method */
1387                 guint32 moduleref;
1388                 int charset = mb->charset & 0xf;
1389                 int lasterr = mb->charset & 0x40;
1390                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1391                 table->rows ++;
1392                 alloc_table (table, table->rows);
1393                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1394                 /* map CharSet values to on-disk values */
1395                 
1396                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1397                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1398                 name = mono_string_to_utf8 (mb->dllentry);
1399                 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1400                 g_free (name);
1401                 name = mono_string_to_utf8 (mb->dll);
1402                 moduleref = string_heap_insert (&assembly->sheap, name);
1403                 g_free (name);
1404                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1405                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1406                         table->rows ++;
1407                         alloc_table (table, table->rows);
1408                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1409                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1410                 }
1411         }
1412
1413         if (mb->override_method) {
1414                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1415                 guint32 tok;
1416                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1417                 table->rows ++;
1418                 alloc_table (table, table->rows);
1419                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1420                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1421                 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1422
1423                 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE);
1424                 switch (mono_metadata_token_table (tok)) {
1425                 case MONO_TABLE_MEMBERREF:
1426                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1427                         break;
1428                 case MONO_TABLE_METHOD:
1429                         tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1430                         break;
1431                 default:
1432                         g_assert_not_reached ();
1433                 }
1434                 values [MONO_METHODIMPL_DECLARATION] = tok;
1435         }
1436
1437         if (mb->generic_params) {
1438                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1439                 table->rows += mono_array_length (mb->generic_params);
1440                 alloc_table (table, table->rows);
1441                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1442                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1443
1444                         mono_image_get_generic_param_info (
1445                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1446                 }
1447         }
1448
1449 }
1450
1451 static void
1452 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1453 {
1454         ReflectionMethodBuilder rmb;
1455
1456         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1457
1458         mono_image_basic_method (&rmb, assembly);
1459 }
1460
1461 static char*
1462 type_get_fully_qualified_name (MonoType *type) {
1463         char *name, *result;
1464         MonoClass *klass;
1465         MonoAssembly *ta;
1466
1467         name = mono_type_get_name (type);
1468         klass = my_mono_class_from_mono_type (type);
1469         ta = klass->image->assembly;
1470
1471         result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
1472                 name, ta->aname.name,
1473                 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1474                 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
1475                 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
1476         g_free (name);
1477         return result;
1478 }
1479
1480 static char*
1481 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1482         MonoClass *klass;
1483         MonoAssembly *ta;
1484
1485         klass = my_mono_class_from_mono_type (type);
1486         if (!klass) 
1487                 return mono_type_get_name (type);
1488         ta = klass->image->assembly;
1489         if (ta == ass || klass->image == mono_defaults.corlib)
1490                 return mono_type_get_name (type);
1491
1492         return type_get_fully_qualified_name (type);
1493 }
1494
1495 static guint32
1496 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1497 {
1498         char blob_size [64];
1499         char *b = blob_size;
1500         char *p;
1501         char* buf;
1502         guint32 idx;
1503
1504         if (!assembly->save)
1505                 return 0;
1506
1507         p = buf = g_malloc (64);
1508         
1509         mono_metadata_encode_value (0x06, p, &p);
1510         /* encode custom attributes before the type */
1511         encode_type (assembly, type, p, &p);
1512         g_assert (p-buf < 64);
1513         mono_metadata_encode_value (p-buf, b, &b);
1514         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1515         g_free (buf);
1516         return idx;
1517 }
1518
1519 static guint32
1520 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1521 {
1522         char blob_size [64];
1523         char *b = blob_size;
1524         char *p;
1525         char* buf;
1526         guint32 idx;
1527         
1528         p = buf = g_malloc (64);
1529         
1530         mono_metadata_encode_value (0x06, p, &p);
1531         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1532         /* encode custom attributes before the type */
1533         encode_reflection_type (assembly, fb->type, p, &p);
1534         g_assert (p-buf < 64);
1535         mono_metadata_encode_value (p-buf, b, &b);
1536         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1537         g_free (buf);
1538         return idx;
1539 }
1540
1541 static guint32
1542 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1543         char blob_size [64];
1544         char *b = blob_size;
1545         char *p, *box_val;
1546         char* buf;
1547         guint32 idx = 0, len = 0, dummy = 0;
1548         
1549         p = buf = g_malloc (64);
1550         if (!val) {
1551                 *ret_type = MONO_TYPE_CLASS;
1552                 len = 4;
1553                 box_val = (char*)&dummy;
1554         } else {
1555                 box_val = ((char*)val) + sizeof (MonoObject);
1556                 *ret_type = val->vtable->klass->byval_arg.type;
1557         }
1558 handle_enum:
1559         switch (*ret_type) {
1560         case MONO_TYPE_BOOLEAN:
1561         case MONO_TYPE_U1:
1562         case MONO_TYPE_I1:
1563                 len = 1;
1564                 break;
1565         case MONO_TYPE_CHAR:
1566         case MONO_TYPE_U2:
1567         case MONO_TYPE_I2:
1568                 len = 2;
1569                 break;
1570         case MONO_TYPE_U4:
1571         case MONO_TYPE_I4:
1572         case MONO_TYPE_R4:
1573                 len = 4;
1574                 break;
1575         case MONO_TYPE_U8:
1576         case MONO_TYPE_I8:
1577         case MONO_TYPE_R8:
1578                 len = 8;
1579                 break;
1580         case MONO_TYPE_VALUETYPE:
1581                 if (val->vtable->klass->enumtype) {
1582                         *ret_type = val->vtable->klass->enum_basetype->type;
1583                         goto handle_enum;
1584                 } else
1585                         g_error ("we can't encode valuetypes");
1586         case MONO_TYPE_CLASS:
1587                 break;
1588         case MONO_TYPE_STRING: {
1589                 MonoString *str = (MonoString*)val;
1590                 /* there is no signature */
1591                 len = str->length * 2;
1592                 mono_metadata_encode_value (len, b, &b);
1593 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1594                 {
1595                         char *swapped = g_malloc (2 * mono_string_length (str));
1596                         const char *p = (const char*)mono_string_chars (str);
1597
1598                         swap_with_size (swapped, p, 2, mono_string_length (str));
1599                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1600                         g_free (swapped);
1601                 }
1602 #else
1603                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1604 #endif
1605
1606                 g_free (buf);
1607                 return idx;
1608         }
1609         default:
1610                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1611         }
1612
1613         /* there is no signature */
1614         mono_metadata_encode_value (len, b, &b);
1615 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1616         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1617         swap_with_size (blob_size, box_val, len, 1);
1618         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1619 #else
1620         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1621 #endif
1622
1623         g_free (buf);
1624         return idx;
1625 }
1626
1627 static guint32
1628 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1629         char blob_size [64];
1630         char *b = blob_size;
1631         char *p, *buf, *str;
1632         guint32 idx, len, bufsize = 256;
1633         
1634         p = buf = g_malloc (bufsize);
1635
1636         switch (minfo->type) {
1637         case MONO_NATIVE_BYVALTSTR:
1638         case MONO_NATIVE_BYVALARRAY:
1639                 mono_metadata_encode_value (minfo->type, p, &p);
1640                 mono_metadata_encode_value (minfo->count, p, &p);
1641                 break;
1642         case MONO_NATIVE_LPARRAY:
1643                 mono_metadata_encode_value (minfo->type, p, &p);
1644                 if (minfo->eltype || (minfo->count > 0)) {
1645                         mono_metadata_encode_value (minfo->eltype, p, &p);
1646                         if (minfo->count > 0) {
1647                                 mono_metadata_encode_value (0, p, &p);
1648                                 mono_metadata_encode_value (minfo->count, p, &p);
1649                         }
1650                 }
1651                 break;
1652         case MONO_NATIVE_CUSTOM:
1653                 mono_metadata_encode_value (minfo->type, p, &p);
1654                 if (minfo->guid) {
1655                         str = mono_string_to_utf8 (minfo->guid);
1656                         len = strlen (str);
1657                         mono_metadata_encode_value (len, p, &p);
1658                         memcpy (p, str, len);
1659                         p += len;
1660                         g_free (str);
1661                 } else {
1662                         mono_metadata_encode_value (0, p, &p);
1663                 }
1664                 if (minfo->marshaltype) {
1665                         str = mono_string_to_utf8 (minfo->marshaltype);
1666                         len = strlen (str);
1667                         mono_metadata_encode_value (len, p, &p);
1668                         if (p + len >= buf + bufsize) {
1669                                 idx = p - buf;
1670                                 bufsize *= 2;
1671                                 buf = g_realloc (buf, bufsize);
1672                                 p = buf + idx;
1673                         }
1674                         memcpy (p, str, len);
1675                         p += len;
1676                         g_free (str);
1677                 } else {
1678                         mono_metadata_encode_value (0, p, &p);
1679                 }
1680                 if (minfo->marshaltyperef) {
1681                         str = type_get_fully_qualified_name (minfo->marshaltyperef->type);
1682                         len = strlen (str);
1683                         mono_metadata_encode_value (len, p, &p);
1684                         if (p + len >= buf + bufsize) {
1685                                 idx = p - buf;
1686                                 bufsize *= 2;
1687                                 buf = g_realloc (buf, bufsize);
1688                                 p = buf + idx;
1689                         }
1690                         memcpy (p, str, len);
1691                         p += len;
1692                         g_free (str);
1693                 } else {
1694                         mono_metadata_encode_value (0, p, &p);
1695                 }
1696                 if (minfo->mcookie) {
1697                         str = mono_string_to_utf8 (minfo->mcookie);
1698                         len = strlen (str);
1699                         mono_metadata_encode_value (len, p, &p);
1700                         if (p + len >= buf + bufsize) {
1701                                 idx = p - buf;
1702                                 bufsize *= 2;
1703                                 buf = g_realloc (buf, bufsize);
1704                                 p = buf + idx;
1705                         }
1706                         memcpy (p, str, len);
1707                         p += len;
1708                         g_free (str);
1709                 } else {
1710                         mono_metadata_encode_value (0, p, &p);
1711                 }
1712                 break;
1713         default:
1714                 mono_metadata_encode_value (minfo->type, p, &p);
1715                 break;
1716         }
1717         len = p-buf;
1718         mono_metadata_encode_value (len, b, &b);
1719         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, len);
1720         g_free (buf);
1721         return idx;
1722 }
1723
1724 static void
1725 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1726 {
1727         MonoDynamicTable *table;
1728         guint32 *values;
1729         char *name;
1730
1731         /* maybe this fixup should be done in the C# code */
1732         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1733                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1734         table = &assembly->tables [MONO_TABLE_FIELD];
1735         fb->table_idx = table->next_idx ++;
1736         mono_g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1737         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1738         name = mono_string_to_utf8 (fb->name);
1739         values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
1740         g_free (name);
1741         values [MONO_FIELD_FLAGS] = fb->attrs;
1742         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1743
1744         if (fb->offset != -1) {
1745                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1746                 table->rows ++;
1747                 alloc_table (table, table->rows);
1748                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1749                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1750                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1751         }
1752         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1753                 guint32 field_type = 0;
1754                 table = &assembly->tables [MONO_TABLE_CONSTANT];
1755                 table->rows ++;
1756                 alloc_table (table, table->rows);
1757                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1758                 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1759                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1760                 values [MONO_CONSTANT_TYPE] = field_type;
1761                 values [MONO_CONSTANT_PADDING] = 0;
1762         }
1763         if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1764                 guint32 rva_idx;
1765                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1766                 table->rows ++;
1767                 alloc_table (table, table->rows);
1768                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1769                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1770                 /*
1771                  * We store it in the code section because it's simpler for now.
1772                  */
1773                 if (fb->rva_data)
1774                         rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1775                 else
1776                         rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1777                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1778         }
1779         if (fb->marshal_info) {
1780                 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1781                 table->rows ++;
1782                 alloc_table (table, table->rows);
1783                 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1784                 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1785                 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1786         }
1787 }
1788
1789 static guint32
1790 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1791 {
1792         char *buf, *p;
1793         char blob_size [6];
1794         char *b = blob_size;
1795         guint32 nparams = 0;
1796         MonoReflectionMethodBuilder *mb = fb->get_method;
1797         MonoReflectionMethodBuilder *smb = fb->set_method;
1798         guint32 idx, i, size;
1799
1800         if (mb && mb->parameters)
1801                 nparams = mono_array_length (mb->parameters);
1802         if (!mb && smb && smb->parameters)
1803                 nparams = mono_array_length (smb->parameters) - 1;
1804         size = 24 + nparams * 10;
1805         buf = p = g_malloc (size);
1806         *p = 0x08;
1807         p++;
1808         mono_metadata_encode_value (nparams, p, &p);
1809         if (mb) {
1810                 encode_reflection_type (assembly, mb->rtype, p, &p);
1811                 for (i = 0; i < nparams; ++i) {
1812                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1813                         encode_reflection_type (assembly, pt, p, &p);
1814                 }
1815         } else {
1816                 /* the property type is the last param */
1817                 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), p, &p);
1818                 for (i = 0; i < nparams; ++i) {
1819                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1820                         encode_reflection_type (assembly, pt, p, &p);
1821                 }
1822         }
1823         /* store length */
1824         g_assert (p - buf < size);
1825         mono_metadata_encode_value (p-buf, b, &b);
1826         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1827         g_free (buf);
1828         return idx;
1829 }
1830
1831 static void
1832 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
1833 {
1834         MonoDynamicTable *table;
1835         guint32 *values;
1836         char *name;
1837         guint num_methods = 0;
1838         guint32 semaidx;
1839
1840         /* 
1841          * we need to set things in the following tables:
1842          * PROPERTYMAP (info already filled in _get_type_info ())
1843          * PROPERTY    (rows already preallocated in _get_type_info ())
1844          * METHOD      (method info already done with the generic method code)
1845          * METHODSEMANTICS
1846          */
1847         table = &assembly->tables [MONO_TABLE_PROPERTY];
1848         pb->table_idx = table->next_idx ++;
1849         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
1850         name = mono_string_to_utf8 (pb->name);
1851         values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
1852         g_free (name);
1853         values [MONO_PROPERTY_FLAGS] = pb->attrs;
1854         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
1855
1856         /* FIXME: we still don't handle 'other' methods */
1857         if (pb->get_method) num_methods ++;
1858         if (pb->set_method) num_methods ++;
1859
1860         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1861         table->rows += num_methods;
1862         alloc_table (table, table->rows);
1863
1864         if (pb->get_method) {
1865                 semaidx = table->next_idx ++;
1866                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1867                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
1868                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
1869                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1870         }
1871         if (pb->set_method) {
1872                 semaidx = table->next_idx ++;
1873                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1874                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
1875                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
1876                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
1877         }
1878 }
1879
1880 static void
1881 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
1882 {
1883         MonoDynamicTable *table;
1884         guint32 *values;
1885         char *name;
1886         guint num_methods = 0;
1887         guint32 semaidx;
1888
1889         /* 
1890          * we need to set things in the following tables:
1891          * EVENTMAP (info already filled in _get_type_info ())
1892          * EVENT    (rows already preallocated in _get_type_info ())
1893          * METHOD      (method info already done with the generic method code)
1894          * METHODSEMANTICS
1895          */
1896         table = &assembly->tables [MONO_TABLE_EVENT];
1897         eb->table_idx = table->next_idx ++;
1898         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
1899         name = mono_string_to_utf8 (eb->name);
1900         values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
1901         g_free (name);
1902         values [MONO_EVENT_FLAGS] = eb->attrs;
1903         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
1904
1905         /*
1906          * FIXME: we still don't handle 'other' methods 
1907          */
1908         if (eb->add_method) num_methods ++;
1909         if (eb->remove_method) num_methods ++;
1910         if (eb->raise_method) num_methods ++;
1911
1912         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
1913         table->rows += num_methods;
1914         alloc_table (table, table->rows);
1915
1916         if (eb->add_method) {
1917                 semaidx = table->next_idx ++;
1918                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1919                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1920                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1921                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1922         }
1923         if (eb->remove_method) {
1924                 semaidx = table->next_idx ++;
1925                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1926                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1927                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1928                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1929         }
1930         if (eb->raise_method) {
1931                 semaidx = table->next_idx ++;
1932                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1933                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1934                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1935                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
1936         }
1937 }
1938
1939 static void
1940 encode_new_constraint (MonoDynamicImage *assembly, guint32 owner)
1941 {
1942         static MonoClass *NewConstraintAttr;
1943         static MonoMethod *NewConstraintAttr_ctor;
1944         MonoDynamicTable *table;
1945         guint32 *values;
1946         guint32 token, type;
1947         char blob_size [4] = { 0x01, 0x00, 0x00, 0x00 };
1948         char *buf, *p;
1949
1950         if (!NewConstraintAttr)
1951                 NewConstraintAttr = mono_class_from_name ( mono_defaults.corlib, 
1952                         "System.Runtime.CompilerServices", "NewConstraintAttribute");
1953         g_assert (NewConstraintAttr);
1954
1955         if (!NewConstraintAttr_ctor) {
1956                 int i;
1957
1958                 for (i = 0; i < NewConstraintAttr->method.count; i++) {
1959                         MonoMethod *m = NewConstraintAttr->methods [i];
1960
1961                         if (strcmp (m->name, ".ctor"))
1962                                 continue;
1963
1964                         NewConstraintAttr_ctor = m;
1965                         break;
1966                 }
1967
1968                 g_assert (NewConstraintAttr_ctor);
1969         }
1970
1971         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1972         table->rows += 1;
1973         alloc_table (table, table->rows);
1974
1975         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1976         owner <<= MONO_CUSTOM_ATTR_BITS;
1977         owner |= MONO_CUSTOM_ATTR_GENERICPAR;
1978         values [MONO_CUSTOM_ATTR_PARENT] = owner;
1979
1980         token = mono_image_get_methodref_token (assembly, NewConstraintAttr_ctor);
1981
1982         type = mono_metadata_token_index (token);
1983         type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1984         switch (mono_metadata_token_table (token)) {
1985         case MONO_TABLE_METHOD:
1986                 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1987                 break;
1988         case MONO_TABLE_MEMBERREF:
1989                 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1990                 break;
1991         default:
1992                 g_warning ("got wrong token in custom attr");
1993                 return;
1994         }
1995         values [MONO_CUSTOM_ATTR_TYPE] = type;
1996
1997         buf = p = g_malloc (1);
1998         mono_metadata_encode_value (4, p, &p);
1999         g_assert (p-buf == 1);
2000
2001         values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, buf, 1, blob_size, 4);
2002
2003         values += MONO_CUSTOM_ATTR_SIZE;
2004         ++table->next_idx;
2005 }
2006
2007 static void
2008 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2009 {
2010         MonoDynamicTable *table;
2011         guint32 num_constraints, i;
2012         guint32 *values;
2013         guint32 table_idx;
2014
2015         table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2016         num_constraints = gparam->iface_constraints ?
2017                 mono_array_length (gparam->iface_constraints) : 0;
2018         table->rows += num_constraints;
2019         if (gparam->base_type)
2020                 table->rows++;
2021         alloc_table (table, table->rows);
2022
2023         if (gparam->base_type) {
2024                 table_idx = table->next_idx ++;
2025                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2026
2027                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2028                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2029                         assembly, gparam->base_type->type);
2030         }
2031
2032         for (i = 0; i < num_constraints; i++) {
2033                 MonoReflectionType *constraint = mono_array_get (
2034                         gparam->iface_constraints, gpointer, i);
2035
2036                 table_idx = table->next_idx ++;
2037                 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2038
2039                 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2040                 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2041                         assembly, constraint->type);
2042         }
2043
2044         if (gparam->has_ctor_constraint)
2045                 encode_new_constraint (assembly, owner);
2046 }
2047
2048 static void
2049 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2050 {
2051         GenericParamTableEntry *entry;
2052
2053         /*
2054          * The GenericParam table must be sorted according to the `owner' field.
2055          * We need to do this sorting prior to writing the GenericParamConstraint
2056          * table, since we have to use the final GenericParam table indices there
2057          * and they must also be sorted.
2058          */
2059
2060         entry = g_new0 (GenericParamTableEntry, 1);
2061         entry->owner = owner;
2062         entry->gparam = gparam;
2063
2064         g_ptr_array_add (assembly->gen_params, entry);
2065 }
2066
2067 static void
2068 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2069 {
2070         MonoDynamicTable *table;
2071         MonoGenericParam *param;
2072         guint32 *values;
2073         guint32 table_idx;
2074
2075         table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2076         table_idx = table->next_idx ++;
2077         values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2078
2079         param = entry->gparam->type.type->data.generic_param;
2080
2081         values [MONO_GENERICPARAM_OWNER] = entry->owner;
2082         if (entry->gparam->has_value_type)
2083                 values [MONO_GENERICPARAM_FLAGS] = 0x18;
2084         else if (entry->gparam->has_reference_type)
2085                 values [MONO_GENERICPARAM_FLAGS] = 0x04;
2086         else
2087                 values [MONO_GENERICPARAM_FLAGS] = 0x00;
2088         values [MONO_GENERICPARAM_NUMBER] = param->num;
2089         values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, param->name);
2090         values [MONO_GENERICPARAM_KIND] = 0;
2091
2092         encode_constraints (entry->gparam, table_idx, assembly);
2093 }
2094
2095 static guint32
2096 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2097 {
2098         MonoDynamicTable *table;
2099         guint32 token;
2100         guint32 *values;
2101         guint32 cols [MONO_ASSEMBLY_SIZE];
2102         const char *pubkey;
2103         guint32 publen;
2104
2105         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2106                 return token;
2107
2108         if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2109                 table = &assembly->tables [MONO_TABLE_MODULEREF];
2110                 token = table->next_idx ++;
2111                 table->rows ++;
2112                 alloc_table (table, table->rows);
2113                 values = table->values + token * MONO_MODULEREF_SIZE;
2114                 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2115
2116                 token <<= MONO_RESOLTION_SCOPE_BITS;
2117                 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2118                 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2119
2120                 return token;
2121         }
2122         
2123         if (image->assembly->dynamic)
2124                 /* FIXME: */
2125                 memset (cols, 0, sizeof (cols));
2126         else {
2127                 /* image->assembly->image is the manifest module */
2128                 image = image->assembly->image;
2129                 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2130         }
2131
2132         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2133         token = table->next_idx ++;
2134         table->rows ++;
2135         alloc_table (table, table->rows);
2136         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2137         values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2138         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2139         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2140         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2141         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2142         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2143         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2144         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2145
2146         if (strcmp ("", image->assembly->aname.culture)) {
2147                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2148                                 image->assembly->aname.culture);
2149         }
2150
2151         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2152                 guchar pubtoken [9];
2153                 pubtoken [0] = 8;
2154                 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2155                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2156         } else {
2157                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2158         }
2159         token <<= MONO_RESOLTION_SCOPE_BITS;
2160         token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2161         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2162         return token;
2163 }
2164
2165 static guint32
2166 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2167 {
2168         MonoDynamicTable *table;
2169         guint32 *values;
2170         guint32 token;
2171         char sig [128];
2172         char *p = sig;
2173         char blob_size [6];
2174         char *b = blob_size;
2175
2176         switch (type->type) {
2177         case MONO_TYPE_FNPTR:
2178         case MONO_TYPE_PTR:
2179         case MONO_TYPE_SZARRAY:
2180         case MONO_TYPE_ARRAY:
2181         case MONO_TYPE_VAR:
2182         case MONO_TYPE_MVAR:
2183         case MONO_TYPE_GENERICINST:
2184                 encode_type (assembly, type, p, &p);
2185                 break;
2186         case MONO_TYPE_CLASS:
2187         case MONO_TYPE_VALUETYPE: {
2188                 MonoClass *k = mono_class_from_mono_type (type);
2189                 if (!k || !k->generic_inst)
2190                         return 0;
2191                 encode_generic_inst (assembly, k->generic_inst, p, &p);
2192                 break;
2193         }
2194         default:
2195                 return 0;
2196         }
2197
2198         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2199         if (assembly->save) {
2200                 g_assert (p-sig < 128);
2201                 mono_metadata_encode_value (p-sig, b, &b);
2202                 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2203                 alloc_table (table, table->rows + 1);
2204                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2205                 values [MONO_TYPESPEC_SIGNATURE] = token;
2206         }
2207
2208         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2209         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2210         table->next_idx ++;
2211         return token;
2212 }
2213
2214 /*
2215  * Despite the name, we handle also TypeSpec (with the above helper).
2216  */
2217 static guint32
2218 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2219 {
2220         MonoDynamicTable *table;
2221         guint32 *values;
2222         guint32 token, scope, enclosing;
2223         MonoClass *klass;
2224
2225         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2226         if (token)
2227                 return token;
2228         token = create_typespec (assembly, type);
2229         if (token)
2230                 return token;
2231         klass = my_mono_class_from_mono_type (type);
2232         if (!klass)
2233                 klass = mono_class_from_mono_type (type);
2234
2235         /*
2236          * If it's in the same module and not a generic type parameter:
2237          */
2238         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
2239                         (type->type != MONO_TYPE_MVAR)) {
2240                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2241                 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2242                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2243                 return token;
2244         }
2245
2246         if (klass->nested_in) {
2247                 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2248                 /* get the typeref idx of the enclosing type */
2249                 enclosing >>= MONO_TYPEDEFORREF_BITS;
2250                 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2251         } else {
2252                 scope = resolution_scope_from_image (assembly, klass->image);
2253         }
2254         table = &assembly->tables [MONO_TABLE_TYPEREF];
2255         if (assembly->save) {
2256                 alloc_table (table, table->rows + 1);
2257                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2258                 values [MONO_TYPEREF_SCOPE] = scope;
2259                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2260                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2261         }
2262         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2263         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2264         table->next_idx ++;
2265         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2266         return token;
2267 }
2268
2269 /*
2270  * Insert a memberef row into the metadata: the token that point to the memberref
2271  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2272  * mono_image_get_fieldref_token()).
2273  * The sig param is an index to an already built signature.
2274  */
2275 static guint32
2276 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2277 {
2278         MonoDynamicTable *table;
2279         guint32 *values;
2280         guint32 token, pclass;
2281         guint32 parent;
2282
2283         parent = mono_image_typedef_or_ref (assembly, type);
2284         switch (parent & MONO_TYPEDEFORREF_MASK) {
2285         case MONO_TYPEDEFORREF_TYPEREF:
2286                 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2287                 break;
2288         case MONO_TYPEDEFORREF_TYPESPEC:
2289                 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2290                 break;
2291         case MONO_TYPEDEFORREF_TYPEDEF:
2292                 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2293                 break;
2294         default:
2295                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2296                 return 0;
2297         }
2298         /* extract the index */
2299         parent >>= MONO_TYPEDEFORREF_BITS;
2300
2301         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2302
2303         if (assembly->save) {
2304                 alloc_table (table, table->rows + 1);
2305                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2306                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2307                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2308                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2309         }
2310
2311         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2312         table->next_idx ++;
2313
2314         return token;
2315 }
2316
2317 static guint32
2318 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2319 {
2320         guint32 token;
2321         MonoMethodSignature *sig;
2322         
2323         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2324         if (token)
2325                 return token;
2326
2327         /*
2328          * A methodref signature can't contain an unmanaged calling convention.
2329          */
2330         sig = mono_metadata_signature_dup (method->signature);
2331         if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2332                 sig->call_convention = MONO_CALL_DEFAULT;
2333         token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2334                 method->name,  method_encode_signature (assembly, sig));
2335         g_free (sig);
2336         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2337         return token;
2338 }
2339
2340 static guint32
2341 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2342                                      const gchar *name, guint32 sig)
2343 {
2344         MonoDynamicTable *table;
2345         guint32 token;
2346         guint32 *values;
2347         
2348         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2349
2350         if (assembly->save) {
2351                 alloc_table (table, table->rows + 1);
2352                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2353                 values [MONO_MEMBERREF_CLASS] = original;
2354                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2355                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2356         }
2357
2358         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2359         table->next_idx ++;
2360
2361         return token;
2362 }
2363
2364 static guint32
2365 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2366 {
2367         guint32 token;
2368         ReflectionMethodBuilder rmb;
2369         
2370         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2371         if (token)
2372                 return token;
2373
2374         reflection_methodbuilder_from_method_builder (&rmb, mb);
2375         
2376         token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2377                 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2378         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2379         return token;
2380 }
2381
2382 static guint32
2383 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2384 {
2385         guint32 token;
2386         ReflectionMethodBuilder rmb;
2387         
2388         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2389         if (token)
2390                 return token;
2391
2392         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2393
2394         token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2395                 mono_string_to_utf8 (rmb.name), method_builder_encode_signature (assembly, &rmb));
2396         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2397         return token;
2398 }
2399
2400 static guint32
2401 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2402 {
2403         MonoType *type;
2404         guint32 token;
2405
2406         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2407         if (token)
2408                 return token;
2409         g_assert (f->field->parent);
2410         type = f->field->generic_info ? f->field->generic_info->generic_type : f->field->type;
2411         token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg, 
2412                 f->field->name,  fieldref_encode_signature (assembly, type));
2413         g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2414         return token;
2415 }
2416
2417 static guint32
2418 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2419 {
2420         char *buf;
2421         char *p;
2422         int i;
2423         guint32 nparams =  gmethod->mtype_argc;
2424         guint32 size = 10 + nparams * 10;
2425         guint32 idx;
2426         char blob_size [6];
2427         char *b = blob_size;
2428
2429         if (!assembly->save)
2430                 return 0;
2431
2432         p = buf = g_malloc (size);
2433         /*
2434          * FIXME: vararg, explicit_this, differenc call_conv values...
2435          */
2436         mono_metadata_encode_value (0xa, p, &p); /* FIXME FIXME FIXME */
2437         mono_metadata_encode_value (nparams, p, &p);
2438
2439         for (i = 0; i < nparams; i++)
2440                 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2441
2442         /* store length */
2443         g_assert (p - buf < size);
2444         mono_metadata_encode_value (p-buf, b, &b);
2445         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2446         g_free (buf);
2447         return idx;
2448 }
2449
2450 static guint32
2451 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2452 {
2453         MonoDynamicTable *table;
2454         guint32 *values;
2455         guint32 token, mtoken = 0, sig;
2456         MonoMethodInflated *imethod;
2457         MonoMethod *declaring;
2458
2459         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2460
2461         g_assert (method->signature->is_inflated);
2462         imethod = (MonoMethodInflated *) method;
2463         declaring = imethod->declaring;
2464
2465         sig = method_encode_signature (assembly, declaring->signature);
2466         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2467
2468         if (!declaring->signature->generic_param_count)
2469                 return mtoken;
2470
2471         switch (mono_metadata_token_table (mtoken)) {
2472         case MONO_TABLE_MEMBERREF:
2473                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2474                 break;
2475         case MONO_TABLE_METHOD:
2476                 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2477                 break;
2478         default:
2479                 g_assert_not_reached ();
2480         }
2481
2482         sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2483
2484         if (assembly->save) {
2485                 alloc_table (table, table->rows + 1);
2486                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2487                 values [MONO_METHODSPEC_METHOD] = mtoken;
2488                 values [MONO_METHODSPEC_SIGNATURE] = sig;
2489         }
2490
2491         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2492         table->next_idx ++;
2493
2494         return token;
2495 }
2496
2497 static guint32
2498 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2499 {
2500         MonoMethodInflated *imethod;
2501         guint32 token;
2502         
2503         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2504         if (token)
2505                 return token;
2506
2507         g_assert (m->signature->is_inflated);
2508         imethod = (MonoMethodInflated *) m;
2509
2510         if (imethod->declaring->signature->generic_param_count) {
2511                 token = method_encode_methodspec (assembly, m);
2512         } else {
2513                 guint32 sig = method_encode_signature (
2514                         assembly, imethod->declaring->signature);
2515                 token = mono_image_get_memberref_token (
2516                         assembly, &m->klass->byval_arg, m->name, sig);
2517         }
2518
2519         g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2520         return token;
2521 }
2522
2523 static guint32
2524 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
2525 {
2526         MonoMethodInflated *imethod = (MonoMethodInflated *) m;
2527         guint32 sig, token;
2528
2529         sig = method_encode_signature (assembly, imethod->declaring->signature);
2530         token = mono_image_get_memberref_token (
2531                 assembly, &m->klass->byval_arg, m->name, sig);
2532
2533         return token;
2534 }
2535
2536 static guint32
2537 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2538 {
2539         MonoDynamicTable *table;
2540         MonoClass *klass;
2541         guint32 *values;
2542         guint32 token;
2543         char sig [128];
2544         char *p = sig;
2545         char blob_size [6];
2546         char *b = blob_size;
2547         int count, i;
2548
2549         /*
2550          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2551          * ie. what we'd normally use as the generic type in a TypeSpec signature.
2552          * Because of this, we must not insert it into the `typeref' hash table.
2553          */
2554
2555         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2556         if (token)
2557                 return token;
2558
2559         g_assert (tb->generic_params);
2560         klass = mono_class_from_mono_type (tb->type.type);
2561
2562         mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2563         encode_type (assembly, &klass->byval_arg, p, &p);
2564
2565         count = mono_array_length (tb->generic_params);
2566         mono_metadata_encode_value (count, p, &p);
2567         for (i = 0; i < count; i++) {
2568                 MonoReflectionGenericParam *gparam;
2569
2570                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2571
2572                 encode_type (assembly, gparam->type.type, p, &p);
2573         }
2574
2575         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2576         if (assembly->save) {
2577                 g_assert (p-sig < 128);
2578                 mono_metadata_encode_value (p-sig, b, &b);
2579                 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2580                 alloc_table (table, table->rows + 1);
2581                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2582                 values [MONO_TYPESPEC_SIGNATURE] = token;
2583         }
2584
2585         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2586         g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2587         table->next_idx ++;
2588         return token;
2589 }
2590
2591 static guint32
2592 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2593 {
2594         MonoDynamicTable *table;
2595         MonoClass *klass;
2596         guint32 *values;
2597         guint32 token, pclass, parent, sig;
2598         gchar *name;
2599
2600         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2601         if (token)
2602                 return token;
2603
2604         klass = mono_class_from_mono_type (fb->typeb->type);
2605         name = mono_string_to_utf8 (fb->name);
2606
2607         sig = fieldref_encode_signature (assembly, fb->type->type);
2608
2609         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2610         g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
2611         
2612         pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2613         parent >>= MONO_TYPEDEFORREF_BITS;
2614
2615         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2616
2617         if (assembly->save) {
2618                 alloc_table (table, table->rows + 1);
2619                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2620                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2621                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2622                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2623         }
2624
2625         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2626         table->next_idx ++;
2627         g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2628         return token;
2629 }
2630
2631 static guint32
2632 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2633 {
2634         char *buf;
2635         char *p;
2636         guint32 nargs;
2637         guint32 size;
2638         guint32 i, idx;
2639         char blob_size [6];
2640         char *b = blob_size;
2641
2642         if (!assembly->save)
2643                 return 0;
2644
2645         /* FIXME: */
2646         g_assert (helper->type == 2);
2647
2648         if (helper->arguments)
2649                 nargs = mono_array_length (helper->arguments);
2650         else
2651                 nargs = 0;
2652
2653         size = 10 + (nargs * 10);
2654         
2655         p = buf = g_malloc (size);
2656
2657         /* Encode calling convention */
2658         /* Change Any to Standard */
2659         if ((helper->call_conv & 0x03) == 0x03)
2660                 helper->call_conv = 0x01;
2661         /* explicit_this implies has_this */
2662         if (helper->call_conv & 0x40)
2663                 helper->call_conv &= 0x20;
2664
2665         if (helper->call_conv == 0) { /* Unmanaged */
2666                 *p = helper->unmanaged_call_conv - 1;
2667         } else {
2668                 /* Managed */
2669                 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2670                 if (helper->call_conv & 0x02) /* varargs */
2671                         *p += 0x05;
2672         }
2673
2674         p++;
2675         mono_metadata_encode_value (nargs, p, &p);
2676         encode_reflection_type (assembly, helper->return_type, p, &p);
2677         for (i = 0; i < nargs; ++i) {
2678                 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2679                 encode_reflection_type (assembly, pt, p, &p);
2680         }
2681         /* store length */
2682         g_assert (p - buf < size);
2683         mono_metadata_encode_value (p-buf, b, &b);
2684         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2685         g_free (buf);
2686
2687         return idx;
2688 }
2689         
2690 static guint32 
2691 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2692 {
2693         guint32 idx;
2694         MonoDynamicTable *table;
2695         guint32 *values;
2696
2697         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2698         idx = table->next_idx ++;
2699         table->rows ++;
2700         alloc_table (table, table->rows);
2701         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2702
2703         values [MONO_STAND_ALONE_SIGNATURE] =
2704                 mono_reflection_encode_sighelper (assembly, helper);
2705
2706         return idx;
2707 }
2708
2709 static int
2710 reflection_cc_to_file (int call_conv) {
2711         switch (call_conv & 0x3) {
2712         case 0:
2713         case 1: return MONO_CALL_DEFAULT;
2714         case 2: return MONO_CALL_VARARG;
2715         default:
2716                 g_assert_not_reached ();
2717         }
2718         return 0;
2719 }
2720
2721 typedef struct {
2722         MonoType *parent;
2723         MonoMethodSignature *sig;
2724         char *name;
2725         guint32 token;
2726 } ArrayMethod;
2727
2728 static guint32
2729 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2730 {
2731         guint32 nparams, i;
2732         GList *tmp;
2733         char *name;
2734         MonoMethodSignature *sig;
2735         ArrayMethod *am;
2736         
2737         name = mono_string_to_utf8 (m->name);
2738         nparams = mono_array_length (m->parameters);
2739         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2740         sig->hasthis = 1;
2741         sig->sentinelpos = -1;
2742         sig->call_convention = reflection_cc_to_file (m->call_conv);
2743         sig->param_count = nparams;
2744         sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2745         for (i = 0; i < nparams; ++i) {
2746                 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2747                 sig->params [i] = t->type;
2748         }
2749
2750         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2751                 am = tmp->data;
2752                 if (strcmp (name, am->name) == 0 && 
2753                                 mono_metadata_type_equal (am->parent, m->parent->type) &&
2754                                 mono_metadata_signature_equal (am->sig, sig)) {
2755                         g_free (name);
2756                         g_free (sig);
2757                         m->table_idx = am->token & 0xffffff;
2758                         return am->token;
2759                 }
2760         }
2761         am = g_new0 (ArrayMethod, 1);
2762         am->name = name;
2763         am->sig = sig;
2764         am->parent = m->parent->type;
2765         am->token = mono_image_get_memberref_token (assembly, am->parent, name,
2766                 method_encode_signature (assembly, sig));
2767         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2768         m->table_idx = am->token & 0xffffff;
2769         return am->token;
2770 }
2771
2772 /*
2773  * Insert into the metadata tables all the info about the TypeBuilder tb.
2774  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2775  */
2776 static void
2777 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2778 {
2779         MonoDynamicTable *table;
2780         guint *values;
2781         int i, is_object = 0, is_system = 0;
2782         char *n;
2783
2784         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2785         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2786         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2787         n = mono_string_to_utf8 (tb->name);
2788         if (strcmp (n, "Object") == 0)
2789                 is_object++;
2790         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2791         g_free (n);
2792         n = mono_string_to_utf8 (tb->nspace);
2793         if (strcmp (n, "System") == 0)
2794                 is_system++;
2795         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2796         g_free (n);
2797         if (tb->parent && !(is_system && is_object) && 
2798                         !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2799                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2800         } else {
2801                 values [MONO_TYPEDEF_EXTENDS] = 0;
2802         }
2803         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2804         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2805
2806         /*
2807          * if we have explicitlayout or sequentiallayouts, output data in the
2808          * ClassLayout table.
2809          */
2810         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
2811                         ((tb->class_size > 0) || (tb->packing_size > 0))) {
2812                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2813                 table->rows++;
2814                 alloc_table (table, table->rows);
2815                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2816                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2817                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2818                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2819         }
2820
2821         /* handle interfaces */
2822         if (tb->interfaces) {
2823                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2824                 i = table->rows;
2825                 table->rows += mono_array_length (tb->interfaces);
2826                 alloc_table (table, table->rows);
2827                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2828                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2829                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2830                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2831                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2832                         values += MONO_INTERFACEIMPL_SIZE;
2833                 }
2834         }
2835
2836         /* handle fields */
2837         if (tb->fields) {
2838                 table = &assembly->tables [MONO_TABLE_FIELD];
2839                 table->rows += tb->num_fields;
2840                 alloc_table (table, table->rows);
2841                 for (i = 0; i < tb->num_fields; ++i)
2842                         mono_image_get_field_info (
2843                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2844         }
2845
2846         /* handle constructors */
2847         if (tb->ctors) {
2848                 table = &assembly->tables [MONO_TABLE_METHOD];
2849                 table->rows += mono_array_length (tb->ctors);
2850                 alloc_table (table, table->rows);
2851                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2852                         mono_image_get_ctor_info (domain,
2853                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2854         }
2855
2856         /* handle methods */
2857         if (tb->methods) {
2858                 table = &assembly->tables [MONO_TABLE_METHOD];
2859                 table->rows += tb->num_methods;
2860                 alloc_table (table, table->rows);
2861                 for (i = 0; i < tb->num_methods; ++i)
2862                         mono_image_get_method_info (
2863                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2864         }
2865
2866         /* Do the same with properties etc.. */
2867         if (tb->events && mono_array_length (tb->events)) {
2868                 table = &assembly->tables [MONO_TABLE_EVENT];
2869                 table->rows += mono_array_length (tb->events);
2870                 alloc_table (table, table->rows);
2871                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2872                 table->rows ++;
2873                 alloc_table (table, table->rows);
2874                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2875                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2876                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2877                 for (i = 0; i < mono_array_length (tb->events); ++i)
2878                         mono_image_get_event_info (
2879                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2880         }
2881         if (tb->properties && mono_array_length (tb->properties)) {
2882                 table = &assembly->tables [MONO_TABLE_PROPERTY];
2883                 table->rows += mono_array_length (tb->properties);
2884                 alloc_table (table, table->rows);
2885                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2886                 table->rows ++;
2887                 alloc_table (table, table->rows);
2888                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2889                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2890                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2891                 for (i = 0; i < mono_array_length (tb->properties); ++i)
2892                         mono_image_get_property_info (
2893                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2894         }
2895
2896         /* handle generic parameters */
2897         if (tb->generic_params) {
2898                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2899                 table->rows += mono_array_length (tb->generic_params);
2900                 alloc_table (table, table->rows);
2901                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2902                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2903
2904                         mono_image_get_generic_param_info (
2905                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2906                 }
2907         }
2908
2909         mono_image_add_decl_security (assembly, 
2910                 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
2911
2912         if (tb->subtypes) {
2913                 MonoDynamicTable *ntable;
2914                 
2915                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2916                 ntable->rows += mono_array_length (tb->subtypes);
2917                 alloc_table (ntable, ntable->rows);
2918                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2919
2920                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2921                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2922
2923                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2924                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2925                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2926                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2927                                 mono_string_to_utf8 (tb->name), tb->table_idx,
2928                                 ntable->next_idx, ntable->rows);*/
2929                         values += MONO_NESTED_CLASS_SIZE;
2930                         ntable->next_idx++;
2931                 }
2932         }
2933 }
2934
2935 static void
2936 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2937 {
2938         int i;
2939
2940         g_ptr_array_add (types, type);
2941
2942         if (!type->subtypes)
2943                 return;
2944
2945         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2946                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2947                 collect_types (types, subtype);
2948         }
2949 }
2950
2951 static gint
2952 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
2953 {
2954         if ((*type1)->table_idx < (*type2)->table_idx)
2955                 return -1;
2956         else
2957                 if ((*type1)->table_idx > (*type2)->table_idx)
2958                         return 1;
2959         else
2960                 return 0;
2961 }
2962
2963 static void
2964 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2965         int i;
2966
2967         if (!pinfo)
2968                 return;
2969         for (i = 0; i < mono_array_length (pinfo); ++i) {
2970                 MonoReflectionParamBuilder *pb;
2971                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2972                 if (!pb)
2973                         continue;
2974                 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2975         }
2976 }
2977
2978 static void
2979 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2980         int i;
2981         
2982         mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2983         if (tb->fields) {
2984                 for (i = 0; i < tb->num_fields; ++i) {
2985                         MonoReflectionFieldBuilder* fb;
2986                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2987                         mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2988                 }
2989         }
2990         if (tb->events) {
2991                 for (i = 0; i < mono_array_length (tb->events); ++i) {
2992                         MonoReflectionEventBuilder* eb;
2993                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2994                         mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
2995                 }
2996         }
2997         if (tb->properties) {
2998                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2999                         MonoReflectionPropertyBuilder* pb;
3000                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3001                         mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3002                 }
3003         }
3004         if (tb->ctors) {
3005                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3006                         MonoReflectionCtorBuilder* cb;
3007                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3008                         mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3009                         params_add_cattrs (assembly, cb->pinfo);
3010                 }
3011         }
3012
3013         if (tb->methods) {
3014                 for (i = 0; i < tb->num_methods; ++i) {
3015                         MonoReflectionMethodBuilder* mb;
3016                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3017                         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3018                         params_add_cattrs (assembly, mb->pinfo);
3019                 }
3020         }
3021
3022         if (tb->subtypes) {
3023                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3024                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3025         }
3026 }
3027
3028 static void
3029 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
3030         int i;
3031         
3032         mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_MODULE, mb->cattrs);
3033         
3034         /* no types in the module */
3035         if (!mb->types)
3036                 return;
3037         
3038         for (i = 0; i < mb->num_types; ++i)
3039                 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
3040 }
3041
3042 static void
3043 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3044 {
3045         MonoDynamicTable *table;
3046         guint32 *values;
3047         char blob_size [6];
3048         guchar hash [20];
3049         char *b = blob_size;
3050         char *dir, *path;
3051
3052         table = &assembly->tables [MONO_TABLE_FILE];
3053         table->rows++;
3054         alloc_table (table, table->rows);
3055         values = table->values + table->next_idx * MONO_FILE_SIZE;
3056         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3057         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3058         if (module->image->dynamic) {
3059                 /* This depends on the fact that the main module is emitted last */
3060                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3061                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3062         } else {
3063                 dir = NULL;
3064                 path = g_strdup (module->image->name);
3065         }
3066         mono_sha1_get_digest_from_file (path, hash);
3067         g_free (dir);
3068         g_free (path);
3069         mono_metadata_encode_value (20, b, &b);
3070         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3071         mono_image_add_stream_data (&assembly->blob, hash, 20);
3072         table->next_idx ++;
3073 }
3074
3075 static void
3076 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3077 {
3078         MonoDynamicTable *table;
3079         int i;
3080         char *name;
3081
3082         table = &assembly->tables [MONO_TABLE_MODULE];
3083         mb->table_idx = table->next_idx ++;
3084         name = mono_string_to_utf8 (mb->module.name);
3085         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
3086         g_free (name);
3087         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3088         i /= 16;
3089         ++i;
3090         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3091         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3092         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3093 }
3094
3095 static guint32
3096 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3097         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3098 {
3099         MonoDynamicTable *table;
3100         guint32 *values;
3101         guint32 visib, res;
3102
3103         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3104         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3105                 return 0;
3106
3107         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3108         table->rows++;
3109         alloc_table (table, table->rows);
3110         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3111
3112         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3113         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3114         if (klass->nested_in)
3115                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3116         else
3117                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3118         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3119         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3120
3121         res = table->next_idx;
3122
3123         table->next_idx ++;
3124
3125         /* Emit nested types */
3126         if (klass->nested_classes) {
3127                 GList *tmp;
3128
3129                 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3130                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3131         }
3132
3133         return res;
3134 }
3135
3136 static void
3137 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3138         guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3139 {
3140         MonoClass *klass;
3141         guint32 idx, i;
3142
3143         klass = mono_class_from_mono_type (tb->type.type);
3144
3145         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3146
3147         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3148                                                                                                    parent_index, assembly);
3149
3150         /* 
3151          * Emit nested types
3152          * We need to do this ourselves since klass->nested_classes is not set up.
3153          */
3154         if (tb->subtypes) {
3155                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3156                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3157         }
3158 }
3159
3160 static void
3161 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3162         guint32 module_index, MonoDynamicImage *assembly)
3163 {
3164         MonoImage *image = module->image;
3165         MonoTableInfo  *t;
3166         guint32 i;
3167
3168         t = &image->tables [MONO_TABLE_TYPEDEF];
3169
3170         for (i = 0; i < t->rows; ++i) {
3171                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3172
3173                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3174                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3175         }
3176 }
3177
3178 #define align_pointer(base,p)\
3179         do {\
3180                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3181                 if (__diff & 3)\
3182                         (p) += 4 - (__diff & 3);\
3183         } while (0)
3184
3185 static int
3186 compare_semantics (const void *a, const void *b)
3187 {
3188         const guint32 *a_values = a;
3189         const guint32 *b_values = b;
3190         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3191         if (assoc)
3192                 return assoc;
3193         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3194 }
3195
3196 static int
3197 compare_custom_attrs (const void *a, const void *b)
3198 {
3199         const guint32 *a_values = a;
3200         const guint32 *b_values = b;
3201
3202         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3203 }
3204
3205 static int
3206 compare_field_marshal (const void *a, const void *b)
3207 {
3208         const guint32 *a_values = a;
3209         const guint32 *b_values = b;
3210
3211         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3212 }
3213
3214 static int
3215 compare_nested (const void *a, const void *b)
3216 {
3217         const guint32 *a_values = a;
3218         const guint32 *b_values = b;
3219
3220         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3221 }
3222
3223 static int
3224 compare_genericparam (const void *a, const void *b)
3225 {
3226         const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3227         const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3228
3229         return (*a_entry)->owner - (*b_entry)->owner;
3230 }
3231
3232 static int
3233 compare_declsecurity_attrs (const void *a, const void *b)
3234 {
3235         const guint32 *a_values = a;
3236         const guint32 *b_values = b;
3237
3238         return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3239 }
3240
3241 static void
3242 pad_heap (MonoDynamicStream *sh)
3243 {
3244         if (sh->index & 3) {
3245                 int sz = 4 - (sh->index & 3);
3246                 memset (sh->data + sh->index, 0, sz);
3247                 sh->index += sz;
3248         }
3249 }
3250
3251 struct StreamDesc {
3252         const char *name;
3253         MonoDynamicStream *stream;
3254 };
3255
3256 /*
3257  * build_compressed_metadata() fills in the blob of data that represents the 
3258  * raw metadata as it will be saved in the PE file. The five streams are output 
3259  * and the metadata tables are comnpressed from the guint32 array representation, 
3260  * to the compressed on-disk format.
3261  */
3262 static void
3263 build_compressed_metadata (MonoDynamicImage *assembly)
3264 {
3265         MonoDynamicTable *table;
3266         int i;
3267         guint64 valid_mask = 0;
3268         guint64 sorted_mask;
3269         guint32 heapt_size = 0;
3270         guint32 meta_size = 256; /* allow for header and other stuff */
3271         guint32 table_offset;
3272         guint32 ntables = 0;
3273         guint64 *int64val;
3274         guint32 *int32val;
3275         guint16 *int16val;
3276         MonoImage *meta;
3277         unsigned char *p;
3278         struct StreamDesc stream_desc [5];
3279
3280         qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3281         for (i = 0; i < assembly->gen_params->len; i++){
3282                 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3283                 write_generic_param_entry (assembly, entry);
3284         }
3285
3286         stream_desc [0].name  = "#~";
3287         stream_desc [0].stream = &assembly->tstream;
3288         stream_desc [1].name  = "#Strings";
3289         stream_desc [1].stream = &assembly->sheap;
3290         stream_desc [2].name  = "#US";
3291         stream_desc [2].stream = &assembly->us;
3292         stream_desc [3].name  = "#Blob";
3293         stream_desc [3].stream = &assembly->blob;
3294         stream_desc [4].name  = "#GUID";
3295         stream_desc [4].stream = &assembly->guid;
3296         
3297         /* tables that are sorted */
3298         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3299                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3300                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3301                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3302                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3303                 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM);
3304         
3305         /* Compute table sizes */
3306         /* the MonoImage has already been created in mono_image_basic_init() */
3307         meta = &assembly->image;
3308
3309         /* sizes should be multiple of 4 */
3310         pad_heap (&assembly->blob);
3311         pad_heap (&assembly->guid);
3312         pad_heap (&assembly->sheap);
3313         pad_heap (&assembly->us);
3314
3315         /* Setup the info used by compute_sizes () */
3316         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3317         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3318         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3319
3320         meta_size += assembly->blob.index;
3321         meta_size += assembly->guid.index;
3322         meta_size += assembly->sheap.index;
3323         meta_size += assembly->us.index;
3324
3325         for (i=0; i < 64; ++i)
3326                 meta->tables [i].rows = assembly->tables [i].rows;
3327         
3328         for (i = 0; i < 64; i++){
3329                 if (meta->tables [i].rows == 0)
3330                         continue;
3331                 valid_mask |= (guint64)1 << i;
3332                 ntables ++;
3333                 meta->tables [i].row_size = mono_metadata_compute_size (
3334                         meta, i, &meta->tables [i].size_bitfield);
3335                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3336         }
3337         heapt_size += 24; /* #~ header size */
3338         heapt_size += ntables * 4;
3339         /* make multiple of 4 */
3340         heapt_size += 3;
3341         heapt_size &= ~3;
3342         meta_size += heapt_size;
3343         meta->raw_metadata = g_malloc0 (meta_size);
3344         p = meta->raw_metadata;
3345         /* the metadata signature */
3346         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3347         /* version numbers and 4 bytes reserved */
3348         int16val = (guint16*)p;
3349         *int16val++ = GUINT16_TO_LE (1);
3350         *int16val = GUINT16_TO_LE (1);
3351         p += 8;
3352         /* version string */
3353         int32val = (guint32*)p;
3354         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3355         p += 4;
3356         memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3357         p += GUINT32_FROM_LE (*int32val);
3358         align_pointer (meta->raw_metadata, p);
3359         int16val = (guint16*)p;
3360         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3361         *int16val = GUINT16_TO_LE (5); /* number of streams */
3362         p += 4;
3363
3364         /*
3365          * write the stream info.
3366          */
3367         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3368         table_offset += 3; table_offset &= ~3;
3369
3370         assembly->tstream.index = heapt_size;
3371         for (i = 0; i < 5; ++i) {
3372                 int32val = (guint32*)p;
3373                 stream_desc [i].stream->offset = table_offset;
3374                 *int32val++ = GUINT32_TO_LE (table_offset);
3375                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3376                 table_offset += GUINT32_FROM_LE (*int32val);
3377                 table_offset += 3; table_offset &= ~3;
3378                 p += 8;
3379                 strcpy (p, stream_desc [i].name);
3380                 p += strlen (stream_desc [i].name) + 1;
3381                 align_pointer (meta->raw_metadata, p);
3382         }
3383         /* 
3384          * now copy the data, the table stream header and contents goes first.
3385          */
3386         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3387         p = meta->raw_metadata + assembly->tstream.offset;
3388         int32val = (guint32*)p;
3389         *int32val = GUINT32_TO_LE (0); /* reserved */
3390         p += 4;
3391
3392         if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3393                         (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3394                         (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3395                 *p++ = 1; /* version */
3396                 *p++ = 1;
3397         } else {
3398                 *p++ = 1; /* version */
3399                 *p++ = 0;
3400         }
3401
3402         if (meta->idx_string_wide)
3403                 *p |= 0x01;
3404         if (meta->idx_guid_wide)
3405                 *p |= 0x02;
3406         if (meta->idx_blob_wide)
3407                 *p |= 0x04;
3408         ++p;
3409         *p++ = 0; /* reserved */
3410         int64val = (guint64*)p;
3411         *int64val++ = GUINT64_TO_LE (valid_mask);
3412         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
3413         p += 16;
3414         int32val = (guint32*)p;
3415         for (i = 0; i < 64; i++){
3416                 if (meta->tables [i].rows == 0)
3417                         continue;
3418                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3419         }
3420         p = (unsigned char*)int32val;
3421
3422         /* sort the tables that still need sorting */
3423         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3424         if (table->rows)
3425                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3426         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3427         if (table->rows)
3428                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3429         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3430         if (table->rows)
3431                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3432         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3433         if (table->rows)
3434                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3435         /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3436         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
3437         if (table->rows)
3438                 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
3439
3440         /* compress the tables */
3441         for (i = 0; i < 64; i++){
3442                 int row, col;
3443                 guint32 *values;
3444                 guint32 bitfield = meta->tables [i].size_bitfield;
3445                 if (!meta->tables [i].rows)
3446                         continue;
3447                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3448                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3449                 meta->tables [i].base = p;
3450                 for (row = 1; row <= meta->tables [i].rows; ++row) {
3451                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
3452                         for (col = 0; col < assembly->tables [i].columns; ++col) {
3453                                 switch (mono_metadata_table_size (bitfield, col)) {
3454                                 case 1:
3455                                         *p++ = values [col];
3456                                         break;
3457                                 case 2:
3458                                         *p++ = values [col] & 0xff;
3459                                         *p++ = (values [col] >> 8) & 0xff;
3460                                         break;
3461                                 case 4:
3462                                         *p++ = values [col] & 0xff;
3463                                         *p++ = (values [col] >> 8) & 0xff;
3464                                         *p++ = (values [col] >> 16) & 0xff;
3465                                         *p++ = (values [col] >> 24) & 0xff;
3466                                         break;
3467                                 default:
3468                                         g_assert_not_reached ();
3469                                 }
3470                         }
3471                 }
3472                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3473         }
3474         
3475         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3476         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3477         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3478         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3479         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3480
3481         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3482 }
3483
3484 /*
3485  * Some tables in metadata need to be sorted according to some criteria, but
3486  * when methods and fields are first created with reflection, they may be assigned a token
3487  * that doesn't correspond to the final token they will get assigned after the sorting.
3488  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3489  * with the reflection objects that represent them. Once all the tables are set up, the 
3490  * reflection objects will contains the correct table index. fixup_method() will fixup the
3491  * tokens for the method with ILGenerator @ilgen.
3492  */
3493 static void
3494 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3495         guint32 code_idx = GPOINTER_TO_UINT (value);
3496         MonoReflectionILTokenInfo *iltoken;
3497         MonoReflectionFieldBuilder *field;
3498         MonoReflectionCtorBuilder *ctor;
3499         MonoReflectionMethodBuilder *method;
3500         MonoReflectionTypeBuilder *tb;
3501         MonoReflectionArrayMethod *am;
3502         guint32 i, idx = 0;
3503         unsigned char *target;
3504
3505         for (i = 0; i < ilgen->num_token_fixups; ++i) {
3506                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3507                 target = assembly->code.data + code_idx + iltoken->code_pos;
3508                 switch (target [3]) {
3509                 case MONO_TABLE_FIELD:
3510                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3511                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
3512                                 idx = field->table_idx;
3513                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3514                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3515                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3516                         } else {
3517                                 g_assert_not_reached ();
3518                         }
3519                         break;
3520                 case MONO_TABLE_METHOD:
3521                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3522                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
3523                                 idx = method->table_idx;
3524                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3525                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3526                                 idx = ctor->table_idx;
3527                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
3528                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3529                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3530                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3531                         } else {
3532                                 g_assert_not_reached ();
3533                         }
3534                         break;
3535                 case MONO_TABLE_TYPEDEF:
3536                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3537                                 g_assert_not_reached ();
3538                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
3539                         idx = tb->table_idx;
3540                         break;
3541                 case MONO_TABLE_MEMBERREF:
3542                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3543                                 am = (MonoReflectionArrayMethod*)iltoken->member;
3544                                 idx = am->table_idx;
3545                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3546                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3547                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3548                                 g_assert (m->klass->generic_inst);
3549                                 continue;
3550                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3551                                 continue;
3552                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3553                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3554                                 g_assert (f->generic_info);
3555                                 continue;
3556                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3557                                 continue;
3558                         } else {
3559                                 g_assert_not_reached ();
3560                         }
3561                         break;
3562                 case MONO_TABLE_METHODSPEC:
3563                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3564                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3565                                 g_assert (m->signature->generic_param_count);
3566                                 continue;
3567                         } else {
3568                                 g_assert_not_reached ();
3569                         }
3570                         break;
3571                 default:
3572                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
3573                 }
3574                 target [0] = idx & 0xff;
3575                 target [1] = (idx >> 8) & 0xff;
3576                 target [2] = (idx >> 16) & 0xff;
3577         }
3578 }
3579
3580 /*
3581  * fixup_cattrs:
3582  *
3583  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3584  * value is not known when the table is emitted.
3585  */
3586 static void
3587 fixup_cattrs (MonoDynamicImage *assembly)
3588 {
3589         MonoDynamicTable *table;
3590         guint32 *values;
3591         guint32 type, i, idx, token;
3592         MonoObject *ctor;
3593
3594         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3595
3596         for (i = 0; i < table->rows; ++i) {
3597                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3598
3599                 type = values [MONO_CUSTOM_ATTR_TYPE];
3600                 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
3601                         idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
3602                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3603                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3604                         g_assert (ctor);
3605
3606                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3607                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3608                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3609                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
3610                         }
3611                 }
3612         }
3613 }
3614
3615 static void
3616 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3617 {
3618         MonoDynamicTable *table;
3619         guint32 *values;
3620         char *name;
3621
3622         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3623         table->rows++;
3624         alloc_table (table, table->rows);
3625         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3626         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3627         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3628         name = mono_string_to_utf8 (rsrc->name);
3629         values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3630         g_free (name);
3631         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3632         table->next_idx++;
3633 }
3634
3635 static void
3636 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3637 {
3638         MonoDynamicTable *table;
3639         guint32 *values;
3640         char blob_size [6];
3641         guchar hash [20];
3642         char *b = blob_size;
3643         char *name, *sname;
3644         guint32 idx, offset;
3645
3646         if (rsrc->filename) {
3647                 name = mono_string_to_utf8 (rsrc->filename);
3648                 sname = g_path_get_basename (name);
3649         
3650                 table = &assembly->tables [MONO_TABLE_FILE];
3651                 table->rows++;
3652                 alloc_table (table, table->rows);
3653                 values = table->values + table->next_idx * MONO_FILE_SIZE;
3654                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3655                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3656                 g_free (sname);
3657
3658                 mono_sha1_get_digest_from_file (name, hash);
3659                 mono_metadata_encode_value (20, b, &b);
3660                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3661                 mono_image_add_stream_data (&assembly->blob, hash, 20);
3662                 g_free (name);
3663                 idx = table->next_idx++;
3664                 rsrc->offset = 0;
3665                 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
3666         } else {
3667                 char sizebuf [4];
3668                 offset = mono_array_length (rsrc->data);
3669                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3670                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3671                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3672                 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3673
3674                 if (!mb->is_main)
3675                         /* 
3676                          * The entry should be emitted into the MANIFESTRESOURCE table of 
3677                          * the main module, but that needs to reference the FILE table
3678                          * which isn't emitted yet.
3679                          */
3680                         return;
3681                 else
3682                         idx = 0;
3683         }
3684
3685         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3686 }
3687
3688 static void
3689 set_version_from_string (MonoString *version, guint32 *values)
3690 {
3691         gchar *ver, *p, *str;
3692         guint32 i;
3693         
3694         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3695         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3696         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3697         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3698         if (!version)
3699                 return;
3700         ver = str = mono_string_to_utf8 (version);
3701         for (i = 0; i < 4; ++i) {
3702                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3703                 switch (*p) {
3704                 case '.':
3705                         p++;
3706                         break;
3707                 case '*':
3708                         /* handle Revision and Build */
3709                         p++;
3710                         break;
3711                 }
3712                 ver = p;
3713         }
3714         g_free (str);
3715 }
3716
3717 static guint32
3718 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3719         gsize len;
3720         guint32 token = 0;
3721         char blob_size [6];
3722         char *b = blob_size;
3723
3724         if (!pkey)
3725                 return token;
3726
3727         len = mono_array_length (pkey);
3728         mono_metadata_encode_value (len, b, &b);
3729         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3730         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3731
3732         /* need to get the actual value from the key type... */
3733         assembly->strong_name_size = 128;
3734         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3735
3736         return token;
3737 }
3738
3739 static void
3740 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3741 {
3742         MonoDynamicTable *table;
3743         MonoDynamicImage *assembly;
3744         MonoReflectionAssemblyBuilder *assemblyb;
3745         MonoDomain *domain;
3746         guint32 *values;
3747         char *name;
3748         int i;
3749         guint32 module_index;
3750
3751         assemblyb = moduleb->assemblyb;
3752         assembly = moduleb->dynamic_image;
3753         domain = mono_object_domain (assemblyb);
3754
3755         /* Emit ASSEMBLY table */
3756         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3757         alloc_table (table, 1);
3758         values = table->values + MONO_ASSEMBLY_SIZE;
3759         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3760         name = mono_string_to_utf8 (assemblyb->name);
3761         values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3762         g_free (name);
3763         if (assemblyb->culture) {
3764                 name = mono_string_to_utf8 (assemblyb->culture);
3765                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3766                 g_free (name);
3767         } else {
3768                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3769         }
3770         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3771         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3772         set_version_from_string (assemblyb->version, values);
3773
3774         /* Emit FILE + EXPORTED_TYPE table */
3775         module_index = 0;
3776         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3777                 int j;
3778                 MonoReflectionModuleBuilder *file_module = 
3779                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3780                 if (file_module != moduleb) {
3781                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3782                         module_index ++;
3783                         if (file_module->types) {
3784                                 for (j = 0; j < file_module->num_types; ++j) {
3785                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3786                                         mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
3787                                 }
3788                         }
3789                 }
3790         }
3791         if (assemblyb->loaded_modules) {
3792                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3793                         MonoReflectionModule *file_module = 
3794                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3795                         mono_image_fill_file_table (domain, file_module, assembly);
3796                         module_index ++;
3797                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3798                 }
3799         }
3800
3801         /* Emit MANIFESTRESOURCE table */
3802         module_index = 0;
3803         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3804                 int j;
3805                 MonoReflectionModuleBuilder *file_module = 
3806                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3807                 /* The table for the main module is emitted later */
3808                 if (file_module != moduleb) {
3809                         module_index ++;
3810                         if (file_module->resources) {
3811                                 int len = mono_array_length (file_module->resources);
3812                                 for (j = 0; j < len; ++j) {
3813                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3814                                         assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
3815                                 }
3816                         }
3817                 }
3818         }               
3819 }
3820
3821 /*
3822  * mono_image_build_metadata() will fill the info in all the needed metadata tables
3823  * for the modulebuilder @moduleb.
3824  * At the end of the process, method and field tokens are fixed up and the 
3825  * on-disk compressed metadata representation is created.
3826  */
3827 void
3828 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3829 {
3830         MonoDynamicTable *table;
3831         MonoDynamicImage *assembly;
3832         MonoReflectionAssemblyBuilder *assemblyb;
3833         MonoDomain *domain;
3834         guint32 *values;
3835         int i;
3836
3837         assemblyb = moduleb->assemblyb;
3838         assembly = moduleb->dynamic_image;
3839         domain = mono_object_domain (assemblyb);
3840
3841         if (assembly->text_rva)
3842                 return;
3843
3844         assembly->text_rva = START_TEXT_RVA;
3845
3846         if (moduleb->is_main) {
3847                 mono_image_emit_manifest (moduleb);
3848         }
3849
3850         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3851         table->rows = 1; /* .<Module> */
3852         table->next_idx++;
3853         alloc_table (table, table->rows);
3854         /*
3855          * Set the first entry.
3856          */
3857         values = table->values + table->columns;
3858         values [MONO_TYPEDEF_FLAGS] = 0;
3859         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3860         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3861         values [MONO_TYPEDEF_EXTENDS] = 0;
3862         values [MONO_TYPEDEF_FIELD_LIST] = 1;
3863         values [MONO_TYPEDEF_METHOD_LIST] = 1;
3864
3865         /* 
3866          * handle global methods 
3867          * FIXME: test what to do when global methods are defined in multiple modules.
3868          */
3869         if (moduleb->global_methods) {
3870                 table = &assembly->tables [MONO_TABLE_METHOD];
3871                 table->rows += mono_array_length (moduleb->global_methods);
3872                 alloc_table (table, table->rows);
3873                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3874                         mono_image_get_method_info (
3875                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3876         }
3877         if (moduleb->global_fields) {
3878                 table = &assembly->tables [MONO_TABLE_FIELD];
3879                 table->rows += mono_array_length (moduleb->global_fields);
3880                 alloc_table (table, table->rows);
3881                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3882                         mono_image_get_field_info (
3883                                 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3884         }
3885
3886         table = &assembly->tables [MONO_TABLE_MODULE];
3887         alloc_table (table, 1);
3888         mono_image_fill_module_table (domain, moduleb, assembly);
3889
3890         /* Emit types */
3891         {
3892                 /* Collect all types into a list sorted by their table_idx */
3893                 GPtrArray *types = g_ptr_array_new ();
3894
3895                 if (moduleb->types)
3896                         for (i = 0; i < moduleb->num_types; ++i) {
3897                                 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3898                                 collect_types (types, type);
3899                         }
3900
3901                 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3902                 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3903                 table->rows += types->len;
3904                 alloc_table (table, table->rows);
3905
3906                 for (i = 0; i < types->len; ++i) {
3907                         MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3908                         mono_image_get_type_info (domain, type, assembly);
3909                 }
3910                 g_ptr_array_free (types, TRUE);
3911         }
3912
3913         /* 
3914          * table->rows is already set above and in mono_image_fill_module_table.
3915          */
3916         /* add all the custom attributes at the end, once all the indexes are stable */
3917         mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3918
3919         /* CAS assembly permissions */
3920         if (assemblyb->permissions_minimum)
3921                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
3922         if (assemblyb->permissions_optional)
3923                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
3924         if (assemblyb->permissions_refused)
3925                 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
3926
3927         module_add_cattrs (assembly, moduleb);
3928
3929         /* fixup tokens */
3930         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3931         fixup_cattrs (assembly);
3932 }
3933
3934 /*
3935  * mono_image_insert_string:
3936  * @module: module builder object
3937  * @str: a string
3938  *
3939  * Insert @str into the user string stream of @module.
3940  */
3941 guint32
3942 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3943 {
3944         MonoDynamicImage *assembly;
3945         guint32 idx;
3946         char buf [16];
3947         char *b = buf;
3948         
3949         MONO_ARCH_SAVE_REGS;
3950
3951         if (!module->dynamic_image)
3952                 mono_image_module_basic_init (module);
3953
3954         assembly = module->dynamic_image;
3955         
3956         if (assembly->save) {
3957                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3958                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3959 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3960         {
3961                 char *swapped = g_malloc (2 * mono_string_length (str));
3962                 const char *p = (const char*)mono_string_chars (str);
3963
3964                 swap_with_size (swapped, p, 2, mono_string_length (str));
3965                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3966                 g_free (swapped);
3967         }
3968 #else
3969                 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3970 #endif
3971                 mono_image_add_stream_data (&assembly->us, "", 1);
3972         } else {
3973                 idx = assembly->us.index ++;
3974         }
3975
3976         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3977
3978         return MONO_TOKEN_STRING | idx;
3979 }
3980
3981 guint32
3982 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
3983 {
3984         MonoClass *klass;
3985         guint32 token = 0;
3986
3987         klass = obj->vtable->klass;
3988         if (strcmp (klass->name, "MonoMethod") == 0) {
3989                 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
3990                 MonoMethodSignature *sig, *old;
3991                 guint32 sig_token, parent;
3992                 int nargs, i;
3993
3994                 g_assert (opt_param_types && (method->signature->sentinelpos >= 0));
3995
3996                 nargs = mono_array_length (opt_param_types);
3997                 old = method->signature;
3998                 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
3999
4000                 sig->hasthis = old->hasthis;
4001                 sig->explicit_this = old->explicit_this;
4002                 sig->call_convention = old->call_convention;
4003                 sig->generic_param_count = old->generic_param_count;
4004                 sig->param_count = old->param_count + nargs;
4005                 sig->sentinelpos = old->param_count;
4006                 sig->ret = old->ret;
4007
4008                 for (i = 0; i < old->param_count; i++)
4009                         sig->params [i] = old->params [i];
4010
4011                 for (i = 0; i < nargs; i++) {
4012                         MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4013                         sig->params [old->param_count + i] = rt->type;
4014                 }
4015
4016                 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4017                 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4018                 parent >>= MONO_TYPEDEFORREF_BITS;
4019
4020                 parent <<= MONO_MEMBERREF_PARENT_BITS;
4021                 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4022
4023                 sig_token = method_encode_signature (assembly, sig);
4024                 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4025         } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4026                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4027                 ReflectionMethodBuilder rmb;
4028                 guint32 parent, sig;
4029         
4030                 reflection_methodbuilder_from_method_builder (&rmb, mb);
4031                 rmb.opt_types = opt_param_types;
4032
4033                 sig = method_builder_encode_signature (assembly, &rmb);
4034
4035                 parent = mono_image_create_token (assembly, obj, TRUE);
4036                 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4037
4038                 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4039                 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4040
4041                 token = mono_image_get_varargs_method_token (
4042                         assembly, parent, mono_string_to_utf8 (rmb.name), sig);
4043         } else {
4044                 g_error ("requested method token for %s\n", klass->name);
4045         }
4046
4047         return token;
4048 }
4049
4050 /*
4051  * mono_image_create_token:
4052  * @assembly: a dynamic assembly
4053  * @obj:
4054  *
4055  * Get a token to insert in the IL code stream for the given MemberInfo.
4056  * @obj can be one of:
4057  *      ConstructorBuilder
4058  *      MethodBuilder
4059  *      FieldBuilder
4060  *      MonoCMethod
4061  *      MonoMethod
4062  *      MonoField
4063  *      MonoType
4064  *      TypeBuilder
4065  */
4066 guint32
4067 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj, gboolean create_methodspec)
4068 {
4069         MonoClass *klass;
4070         guint32 token = 0;
4071
4072         klass = obj->vtable->klass;
4073         if (strcmp (klass->name, "MethodBuilder") == 0) {
4074                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4075
4076                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4077                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4078                 else
4079                         token = mono_image_get_methodbuilder_token (assembly, mb);
4080                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4081         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4082                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4083
4084                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
4085                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4086                 else
4087                         token = mono_image_get_ctorbuilder_token (assembly, mb);
4088                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4089         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4090                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4091                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4092                 if (tb->generic_params) {
4093                         token = mono_image_get_generic_field_token (assembly, fb);
4094                 } else {
4095                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4096                 }
4097         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4098                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4099                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4100         } else if (strcmp (klass->name, "MonoType") == 0 ||
4101                  strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4102                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4103                 token = mono_metadata_token_from_dor (
4104                         mono_image_typedef_or_ref (assembly, tb->type));
4105         } else if (strcmp (klass->name, "MonoGenericInst") == 0) {
4106                 MonoReflectionType *tb = (MonoReflectionType *)obj;
4107                 token = mono_metadata_token_from_dor (
4108                         mono_image_typedef_or_ref (assembly, tb->type));
4109         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4110                         strcmp (klass->name, "MonoMethod") == 0) {
4111                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4112                 if (m->method->signature->is_inflated) {
4113                         if (create_methodspec)
4114                                 token = mono_image_get_methodspec_token (assembly, m->method);
4115                         else
4116                                 token = mono_image_get_inflated_method_token (assembly, m->method);
4117                 } else if (m->method->signature->generic_param_count) {
4118                         g_assert_not_reached ();
4119                 } else if ((m->method->klass->image == &assembly->image) &&
4120                          !m->method->klass->generic_inst) {
4121                         static guint32 method_table_idx = 0xffffff;
4122                         if (m->method->klass->wastypebuilder) {
4123                                 /* we use the same token as the one that was assigned
4124                                  * to the Methodbuilder.
4125                                  * FIXME: do the equivalent for Fields.
4126                                  */
4127                                 token = m->method->token;
4128                         } else {
4129                                 /*
4130                                  * Each token should have a unique index, but the indexes are
4131                                  * assigned by managed code, so we don't know about them. An
4132                                  * easy solution is to count backwards...
4133                                  */
4134                                 method_table_idx --;
4135                                 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4136                         }
4137                 } else {
4138                         token = mono_image_get_methodref_token (assembly, m->method);
4139                 }
4140                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4141         } else if (strcmp (klass->name, "MonoField") == 0) {
4142                 MonoReflectionField *f = (MonoReflectionField *)obj;
4143                 if ((f->klass->image == &assembly->image) && !f->field->generic_info) {
4144                         static guint32 field_table_idx = 0xffffff;
4145                         field_table_idx --;
4146                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4147                 } else {
4148                         token = mono_image_get_fieldref_token (assembly, f);
4149                 }
4150                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4151         } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4152                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4153                 token = mono_image_get_array_token (assembly, m);
4154         } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4155                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4156                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4157         } else {
4158                 g_error ("requested token for %s\n", klass->name);
4159         }
4160
4161         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4162
4163         return token;
4164 }
4165
4166 typedef struct {
4167         guint32 import_lookup_table;
4168         guint32 timestamp;
4169         guint32 forwarder;
4170         guint32 name_rva;
4171         guint32 import_address_table_rva;
4172 } MonoIDT;
4173
4174 typedef struct {
4175         guint32 name_rva;
4176         guint32 flags;
4177 } MonoILT;
4178
4179 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
4180
4181 static MonoDynamicImage*
4182 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4183 {
4184         static const guchar entrycode [16] = {0xff, 0x25, 0};
4185         MonoDynamicImage *image;
4186         int i;
4187
4188         const char *version = mono_get_runtime_version ();
4189
4190 #if HAVE_BOEHM_GC
4191         image = GC_MALLOC (sizeof (MonoDynamicImage));
4192 #else
4193         image = g_new0 (MonoDynamicImage, 1);
4194 #endif
4195
4196         /* keep in sync with image.c */
4197         image->image.name = assembly_name;
4198         image->image.assembly_name = image->image.name; /* they may be different */
4199         image->image.module_name = module_name;
4200         image->image.version = g_strdup (version);
4201         image->image.dynamic = TRUE;
4202
4203         image->image.references = g_new0 (MonoAssembly*, 1);
4204         image->image.references [0] = NULL;
4205
4206         mono_image_init (&image->image);
4207
4208         image->token_fixups = mono_g_hash_table_new (NULL, NULL);
4209         image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4210         image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
4211         image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
4212         image->handleref = g_hash_table_new (NULL, NULL);
4213         image->tokens = mono_g_hash_table_new (NULL, NULL);
4214         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4215         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
4216         image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
4217         image->gen_params = g_ptr_array_new ();
4218
4219         string_heap_init (&image->sheap);
4220         mono_image_add_stream_data (&image->us, "", 1);
4221         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
4222         /* import tables... */
4223         mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4224         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4225         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4226         mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4227         image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4228         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4229         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4230         stream_data_align (&image->code);
4231
4232         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4233
4234         for (i=0; i < 64; ++i) {
4235                 image->tables [i].next_idx = 1;
4236                 image->tables [i].columns = table_sizes [i];
4237         }
4238
4239         image->image.assembly = (MonoAssembly*)assembly;
4240         image->run = assembly->run;
4241         image->save = assembly->save;
4242
4243         return image;
4244 }
4245
4246 /*
4247  * mono_image_basic_init:
4248  * @assembly: an assembly builder object
4249  *
4250  * Create the MonoImage that represents the assembly builder and setup some
4251  * of the helper hash table and the basic metadata streams.
4252  */
4253 void
4254 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4255 {
4256         MonoDynamicAssembly *assembly;
4257         MonoDynamicImage *image;
4258         
4259         MONO_ARCH_SAVE_REGS;
4260
4261         if (assemblyb->dynamic_assembly)
4262                 return;
4263
4264 #if HAVE_BOEHM_GC
4265         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4266 #else
4267         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4268 #endif
4269
4270         assembly->assembly.dynamic = TRUE;
4271         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4272         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4273         if (assemblyb->culture)
4274                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4275         else
4276                 assembly->assembly.aname.culture = g_strdup ("");
4277
4278         assembly->run = assemblyb->access != 2;
4279         assembly->save = assemblyb->access != 1;
4280
4281         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4282         assembly->assembly.aname.name = image->image.name;
4283         assembly->assembly.image = &image->image;
4284
4285         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4286         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4287 }
4288
4289 static int
4290 calc_section_size (MonoDynamicImage *assembly)
4291 {
4292         int nsections = 0;
4293
4294         /* alignment constraints */
4295         assembly->code.index += 3;
4296         assembly->code.index &= ~3;
4297         assembly->meta_size += 3;
4298         assembly->meta_size &= ~3;
4299         assembly->resources.index += 3;
4300         assembly->resources.index &= ~3;
4301
4302         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4303         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4304         nsections++;
4305
4306         if (assembly->win32_res) {
4307                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4308
4309                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4310                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4311                 nsections++;
4312         }
4313
4314         assembly->sections [MONO_SECTION_RELOC].size = 12;
4315         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4316         nsections++;
4317
4318         return nsections;
4319 }
4320
4321 typedef struct {
4322         guint32 id;
4323         guint32 offset;
4324         GSList *children;
4325         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4326 } ResTreeNode;
4327
4328 static int
4329 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4330 {
4331         ResTreeNode *t1 = (ResTreeNode*)a;
4332         ResTreeNode *t2 = (ResTreeNode*)b;
4333
4334         return t1->id - t2->id;
4335 }
4336
4337 /*
4338  * resource_tree_create:
4339  *
4340  *  Organize the resources into a resource tree.
4341  */
4342 static ResTreeNode *
4343 resource_tree_create (MonoArray *win32_resources)
4344 {
4345         ResTreeNode *tree, *res_node, *type_node, *lang_node;
4346         GSList *l;
4347         int i;
4348
4349         tree = g_new0 (ResTreeNode, 1);
4350         
4351         for (i = 0; i < mono_array_length (win32_resources); ++i) {
4352                 MonoReflectionWin32Resource *win32_res =
4353                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4354
4355                 /* Create node */
4356
4357                 lang_node = g_new0 (ResTreeNode, 1);
4358                 lang_node->id = win32_res->lang_id;
4359                 lang_node->win32_res = win32_res;
4360
4361                 /* Create type node if neccesary */
4362                 type_node = NULL;
4363                 for (l = tree->children; l; l = l->next)
4364                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4365                                 type_node = (ResTreeNode*)l->data;
4366                                 break;
4367                         }
4368
4369                 if (!type_node) {
4370                         type_node = g_new0 (ResTreeNode, 1);
4371                         type_node->id = win32_res->res_type;
4372
4373                         /* 
4374                          * The resource types have to be sorted otherwise
4375                          * Windows Explorer can't display the version information.
4376                          */
4377                         tree->children = g_slist_insert_sorted (tree->children, 
4378                                 type_node, resource_tree_compare_by_id);
4379                 }
4380
4381                 /* Create res node if neccesary */
4382                 res_node = NULL;
4383                 for (l = type_node->children; l; l = l->next)
4384                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4385                                 res_node = (ResTreeNode*)l->data;
4386                                 break;
4387                         }
4388
4389                 if (!res_node) {
4390                         res_node = g_new0 (ResTreeNode, 1);
4391                         res_node->id = win32_res->res_id;
4392                         type_node->children = g_slist_append (type_node->children, res_node);
4393                 }
4394
4395                 res_node->children = g_slist_append (res_node->children, lang_node);
4396         }
4397
4398         return tree;
4399 }
4400
4401 /*
4402  * resource_tree_encode:
4403  * 
4404  *   Encode the resource tree into the format used in the PE file.
4405  */
4406 static void
4407 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4408 {
4409         char *entries;
4410         MonoPEResourceDir dir;
4411         MonoPEResourceDirEntry dir_entry;
4412         MonoPEResourceDataEntry data_entry;
4413         GSList *l;
4414
4415         /*
4416          * For the format of the resource directory, see the article
4417          * "An In-Depth Look into the Win32 Portable Executable File Format" by
4418          * Matt Pietrek
4419          */
4420
4421         memset (&dir, 0, sizeof (dir));
4422         memset (&dir_entry, 0, sizeof (dir_entry));
4423         memset (&data_entry, 0, sizeof (data_entry));
4424
4425         g_assert (sizeof (dir) == 16);
4426         g_assert (sizeof (dir_entry) == 8);
4427         g_assert (sizeof (data_entry) == 16);
4428
4429         node->offset = p - begin;
4430
4431         /* IMAGE_RESOURCE_DIRECTORY */
4432         dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4433
4434         memcpy (p, &dir, sizeof (dir));
4435         p += sizeof (dir);
4436
4437         /* Reserve space for entries */
4438         entries = p;
4439         p += sizeof (dir_entry) * dir.res_id_entries;
4440
4441         /* Write children */
4442         for (l = node->children; l; l = l->next) {
4443                 ResTreeNode *child = (ResTreeNode*)l->data;
4444
4445                 if (child->win32_res) {
4446
4447                         child->offset = p - begin;
4448
4449                         /* IMAGE_RESOURCE_DATA_ENTRY */
4450                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4451                         data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4452
4453                         memcpy (p, &data_entry, sizeof (data_entry));
4454                         p += sizeof (data_entry);
4455
4456                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4457                         p += data_entry.rde_size;
4458                 } else {
4459                         resource_tree_encode (child, begin, p, &p);
4460                 }
4461         }
4462
4463         /* IMAGE_RESOURCE_ENTRY */
4464         for (l = node->children; l; l = l->next) {
4465                 ResTreeNode *child = (ResTreeNode*)l->data;
4466                 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4467
4468                 dir_entry.is_dir = child->win32_res ? 0 : 1;
4469                 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4470
4471                 memcpy (entries, &dir_entry, sizeof (dir_entry));
4472                 entries += sizeof (dir_entry);
4473         }
4474
4475         *endbuf = p;
4476 }
4477
4478 static void
4479 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4480 {
4481         char *buf;
4482         char *p;
4483         guint32 size, i;
4484         MonoReflectionWin32Resource *win32_res;
4485         ResTreeNode *tree;
4486
4487         if (!assemblyb->win32_resources)
4488                 return;
4489
4490         /*
4491          * Resources are stored in a three level tree inside the PE file.
4492          * - level one contains a node for each type of resource
4493          * - level two contains a node for each resource
4494          * - level three contains a node for each instance of a resource for a
4495          *   specific language.
4496          */
4497
4498         tree = resource_tree_create (assemblyb->win32_resources);
4499
4500         /* Estimate the size of the encoded tree */
4501         size = 0;
4502         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4503                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4504                 size += mono_array_length (win32_res->res_data);
4505         }
4506         /* Directory structure */
4507         size += mono_array_length (assemblyb->win32_resources) * 256;
4508         p = buf = g_malloc (size);
4509
4510         resource_tree_encode (tree, p, p, &p);
4511
4512         g_assert (p - buf < size);
4513
4514         assembly->win32_res = g_malloc (p - buf);
4515         assembly->win32_res_size = p - buf;
4516         memcpy (assembly->win32_res, buf, p - buf);
4517
4518         g_free (buf);
4519 }
4520
4521 static void
4522 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4523 {
4524         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4525         int i;
4526
4527         p += sizeof (MonoPEResourceDir);
4528         for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4529                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4530                 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4531                 if (dir_entry->is_dir) {
4532                         fixup_resource_directory (res_section, child, rva);
4533                 } else {
4534                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4535                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4536                 }
4537
4538                 p += sizeof (MonoPEResourceDirEntry);
4539         }
4540 }
4541
4542 /*
4543  * mono_image_create_pefile:
4544  * @mb: a module builder object
4545  * 
4546  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
4547  * assembly->pefile where it can be easily retrieved later in chunks.
4548  */
4549 void
4550 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4551         MonoMSDOSHeader *msdos;
4552         MonoDotNetHeader *header;
4553         MonoSectionTable *section;
4554         MonoCLIHeader *cli_header;
4555         guint32 size, image_size, virtual_base, text_offset;
4556         guint32 header_start, section_start, file_offset, virtual_offset;
4557         MonoDynamicImage *assembly;
4558         MonoReflectionAssemblyBuilder *assemblyb;
4559         MonoDynamicStream *pefile;
4560         int i, nsections;
4561         guint32 *rva, value;
4562         guint16 *data16;
4563         guchar *p;
4564         static const unsigned char msheader[] = {
4565                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4566                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4567                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4568                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4569                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4570                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4571                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4572                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4573         };
4574
4575         assemblyb = mb->assemblyb;
4576
4577         mono_image_basic_init (assemblyb);
4578         assembly = mb->dynamic_image;
4579
4580         /* already created */
4581         if (assembly->pefile.index)
4582                 return;
4583         
4584         mono_image_build_metadata (mb);
4585
4586         if (mb->is_main && assemblyb->resources) {
4587                 int len = mono_array_length (assemblyb->resources);
4588                 for (i = 0; i < len; ++i)
4589                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4590         }
4591
4592         if (mb->resources) {
4593                 int len = mono_array_length (mb->resources);
4594                 for (i = 0; i < len; ++i)
4595                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4596         }
4597
4598         build_compressed_metadata (assembly);
4599
4600         if (mb->is_main)
4601                 assembly_add_win32_resources (assembly, assemblyb);
4602
4603         nsections = calc_section_size (assembly);
4604
4605         pefile = &assembly->pefile;
4606
4607         /* The DOS header and stub */
4608         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4609         mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4610
4611         /* the dotnet header */
4612         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4613
4614         /* the section tables */
4615         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4616
4617         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4618         virtual_offset = VIRT_ALIGN;
4619         image_size = 0;
4620
4621         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4622                 if (!assembly->sections [i].size)
4623                         continue;
4624                 /* align offsets */
4625                 file_offset += FILE_ALIGN - 1;
4626                 file_offset &= ~(FILE_ALIGN - 1);
4627                 virtual_offset += VIRT_ALIGN - 1;
4628                 virtual_offset &= ~(VIRT_ALIGN - 1);
4629
4630                 assembly->sections [i].offset = file_offset;
4631                 assembly->sections [i].rva = virtual_offset;
4632
4633                 file_offset += assembly->sections [i].size;
4634                 virtual_offset += assembly->sections [i].size;
4635                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4636         }
4637
4638         file_offset += FILE_ALIGN - 1;
4639         file_offset &= ~(FILE_ALIGN - 1);
4640         mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4641
4642         image_size += section_start + sizeof (MonoSectionTable) * nsections;
4643
4644         /* back-patch info */
4645         msdos = (MonoMSDOSHeader*)pefile->data;
4646         msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4647         msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4648         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4649
4650         header = (MonoDotNetHeader*)(pefile->data + header_start);
4651         header->pesig [0] = 'P';
4652         header->pesig [1] = 'E';
4653         
4654         header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4655         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4656         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4657         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4658         if (assemblyb->pekind == 1) {
4659                 /* it's a dll */
4660                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4661         } else {
4662                 /* it's an exe */
4663                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4664         }
4665
4666         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4667
4668         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4669         header->pe.pe_major = 6;
4670         header->pe.pe_minor = 0;
4671         size = assembly->sections [MONO_SECTION_TEXT].size;
4672         size += FILE_ALIGN - 1;
4673         size &= ~(FILE_ALIGN - 1);
4674         header->pe.pe_code_size = GUINT32_FROM_LE(size);
4675         size = assembly->sections [MONO_SECTION_RSRC].size;
4676         size += FILE_ALIGN - 1;
4677         size &= ~(FILE_ALIGN - 1);
4678         header->pe.pe_data_size = GUINT32_FROM_LE(size);
4679         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4680         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4681         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4682         /* pe_rva_entry_point always at the beginning of the text section */
4683         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4684
4685         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4686         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4687         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4688         header->nt.pe_os_major = GUINT16_FROM_LE (4);
4689         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4690         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4691         size = section_start;
4692         size += FILE_ALIGN - 1;
4693         size &= ~(FILE_ALIGN - 1);
4694         header->nt.pe_header_size = GUINT32_FROM_LE (size);
4695         size = image_size;
4696         size += VIRT_ALIGN - 1;
4697         size &= ~(VIRT_ALIGN - 1);
4698         header->nt.pe_image_size = GUINT32_FROM_LE (size);
4699
4700         /*
4701         // Translate the PEFileKind value to the value expected by the Windows loader
4702         */
4703         {
4704                 short kind;
4705
4706                 /*
4707                 // PEFileKinds.Dll == 1
4708                 // PEFileKinds.ConsoleApplication == 2
4709                 // PEFileKinds.WindowApplication == 3
4710                 //
4711                 // need to get:
4712                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4713                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4714                 */
4715                 if (assemblyb->pekind == 3)
4716                         kind = 2;
4717                 else
4718                         kind = 3;
4719                 
4720                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4721         }    
4722         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4723         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4724         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4725         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4726         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4727         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4728
4729         /* fill data directory entries */
4730
4731         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4732         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4733
4734         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4735         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4736
4737         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4738         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4739         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4740         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4741         /* patch imported function RVA name */
4742         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4743         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4744
4745         /* the import table */
4746         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4747         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4748         /* patch imported dll RVA name and other entries in the dir */
4749         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4750         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4751         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4752         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4753         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4754         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4755
4756         p = (assembly->code.data + assembly->ilt_offset);
4757         value = (assembly->text_rva + assembly->imp_names_offset - 2);
4758         *p++ = (value) & 0xff;
4759         *p++ = (value >> 8) & (0xff);
4760         *p++ = (value >> 16) & (0xff);
4761         *p++ = (value >> 24) & (0xff);
4762
4763         /* the CLI header info */
4764         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4765         cli_header->ch_size = GUINT32_FROM_LE (72);
4766         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4767         cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4768         if (assemblyb->entry_point) {
4769                 guint32 table_idx = 0;
4770                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4771                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4772                         table_idx = methodb->table_idx;
4773                 } else {
4774                         table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4775                 }
4776                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4777         } else {
4778                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4779         }
4780         /* The embedded managed resources */
4781         text_offset = assembly->text_rva + assembly->code.index;
4782         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4783         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4784         text_offset += assembly->resources.index;
4785         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4786         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4787         text_offset += assembly->meta_size;
4788         if (assembly->strong_name_size) {
4789                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4790                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4791                 text_offset += assembly->strong_name_size;
4792         }
4793
4794         /* write the section tables and section content */
4795         section = (MonoSectionTable*)(pefile->data + section_start);
4796         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4797                 static const char *section_names [] = {
4798                         ".text", ".rsrc", ".reloc"
4799                 };
4800                 if (!assembly->sections [i].size)
4801                         continue;
4802                 strcpy (section->st_name, section_names [i]);
4803                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4804                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4805                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4806                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4807                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4808                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4809                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4810                 switch (i) {
4811                 case MONO_SECTION_TEXT:
4812                         /* patch entry point */
4813                         p = (assembly->code.data + 2);
4814                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4815                         *p++ = (value) & 0xff;
4816                         *p++ = (value >> 8) & 0xff;
4817                         *p++ = (value >> 16) & 0xff;
4818                         *p++ = (value >> 24) & 0xff;
4819
4820                         text_offset = assembly->sections [i].offset;
4821                         memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4822                         text_offset += assembly->code.index;
4823                         memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4824                         text_offset += assembly->resources.index;
4825                         memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4826                         text_offset += assembly->meta_size;
4827                         memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4828
4829                         g_free (assembly->image.raw_metadata);
4830                         break;
4831                 case MONO_SECTION_RELOC:
4832                         rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4833                         *rva = GUINT32_FROM_LE (assembly->text_rva);
4834                         ++rva;
4835                         *rva = GUINT32_FROM_LE (12);
4836                         ++rva;
4837                         data16 = (guint16*)rva;
4838                         /* 
4839                          * the entrypoint is always at the start of the text section 
4840                          * 3 is IMAGE_REL_BASED_HIGHLOW
4841                          * 2 is patch_size_rva - text_rva
4842                          */
4843                         *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4844                         data16++;
4845                         *data16 = 0; /* terminate */
4846                         break;
4847                 case MONO_SECTION_RSRC:
4848                         if (assembly->win32_res) {
4849                                 text_offset = assembly->sections [i].offset;
4850
4851                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4852                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4853
4854                                 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4855                         }
4856                         break;
4857                 default:
4858                         g_assert_not_reached ();
4859                 }
4860                 section++;
4861         }
4862         
4863         /* check that the file is properly padded */
4864 #if 0
4865         {
4866                 FILE *f = fopen ("mypetest.exe", "w");
4867                 fwrite (pefile->data, pefile->index, 1, f);
4868                 fclose (f);
4869         }
4870 #endif
4871 }
4872
4873 MonoReflectionModule *
4874 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4875 {
4876         char *name;
4877         MonoImage *image;
4878         MonoImageOpenStatus status;
4879         MonoDynamicAssembly *assembly;
4880         
4881         name = mono_string_to_utf8 (fileName);
4882
4883         image = mono_image_open (name, &status);
4884         if (status) {
4885                 MonoException *exc;
4886                 if (status == MONO_IMAGE_ERROR_ERRNO)
4887                         exc = mono_get_exception_file_not_found (fileName);
4888                 else
4889                         exc = mono_get_exception_bad_image_format (name);
4890                 g_free (name);
4891                 mono_raise_exception (exc);
4892         }
4893
4894         g_free (name);
4895
4896         assembly = ab->dynamic_assembly;
4897         image->assembly = (MonoAssembly*)assembly;
4898
4899         mono_assembly_load_references (image, &status);
4900         if (status) {
4901                 mono_image_close (image);
4902                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4903         }
4904
4905         return mono_module_get_object (mono_domain_get (), image);
4906 }
4907
4908 /*
4909  * We need to return always the same object for MethodInfo, FieldInfo etc..
4910  * but we need to consider the reflected type.
4911  * type uses a different hash, since it uses custom hash/equal functions.
4912  */
4913
4914 typedef struct {
4915         gpointer item;
4916         MonoClass *refclass;
4917 } ReflectedEntry;
4918
4919 static gboolean
4920 reflected_equal (gconstpointer a, gconstpointer b) {
4921         const ReflectedEntry *ea = a;
4922         const ReflectedEntry *eb = b;
4923
4924         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4925 }
4926
4927 static guint
4928 reflected_hash (gconstpointer a) {
4929         const ReflectedEntry *ea = a;
4930         return GPOINTER_TO_UINT (ea->item);
4931 }
4932
4933 #define CHECK_OBJECT(t,p,k)     \
4934         do {    \
4935                 t _obj; \
4936                 ReflectedEntry e;       \
4937                 e.item = (p);   \
4938                 e.refclass = (k);       \
4939                 mono_domain_lock (domain);      \
4940                 if (!domain->refobject_hash)    \
4941                         domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);       \
4942                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
4943                         mono_domain_unlock (domain);    \
4944                         return _obj;    \
4945                 }       \
4946         } while (0)
4947
4948 #if HAVE_BOEHM_GC
4949 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4950 #else
4951 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4952 #endif
4953
4954 #define CACHE_OBJECT(p,o,k)     \
4955         do {    \
4956                 ReflectedEntry *e = ALLOC_REFENTRY;     \
4957                 e->item = (p);  \
4958                 e->refclass = (k);      \
4959                 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4960                 mono_domain_unlock (domain);    \
4961         } while (0)
4962
4963 static void 
4964 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4965 {
4966         /* this is done only once */
4967         mono_domain_lock (domain);
4968         CACHE_OBJECT (assembly, res, NULL);
4969 }
4970
4971 static void
4972 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4973 {
4974         /* this is done only once */
4975         mono_domain_lock (domain);
4976         CACHE_OBJECT (module, res, NULL);
4977 }
4978
4979 void
4980 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4981 {
4982         MonoDynamicImage *image = moduleb->dynamic_image;
4983         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4984         if (!image) {
4985                 /*
4986                  * FIXME: we already created an image in mono_image_basic_init (), but
4987                  * we don't know which module it belongs to, since that is only 
4988                  * determined at assembly save time.
4989                  */
4990                 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
4991                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4992
4993                 moduleb->module.image = &image->image;
4994                 moduleb->dynamic_image = image;
4995                 register_module (mono_object_domain (moduleb), moduleb, image);
4996         }
4997 }
4998
4999 /*
5000  * mono_assembly_get_object:
5001  * @domain: an app domain
5002  * @assembly: an assembly
5003  *
5004  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5005  */
5006 MonoReflectionAssembly*
5007 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
5008 {
5009         static MonoClass *System_Reflection_Assembly;
5010         MonoReflectionAssembly *res;
5011         
5012         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
5013         if (!System_Reflection_Assembly)
5014                 System_Reflection_Assembly = mono_class_from_name (
5015                         mono_defaults.corlib, "System.Reflection", "Assembly");
5016         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
5017         res->assembly = assembly;
5018         CACHE_OBJECT (assembly, res, NULL);
5019         return res;
5020 }
5021
5022
5023
5024 MonoReflectionModule*   
5025 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
5026 {
5027         static MonoClass *System_Reflection_Module;
5028         MonoReflectionModule *res;
5029         
5030         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
5031         if (!System_Reflection_Module)
5032                 System_Reflection_Module = mono_class_from_name (
5033                         mono_defaults.corlib, "System.Reflection", "Module");
5034         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5035
5036         res->image = image;
5037         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5038
5039         res->fqname    = mono_string_new (domain, image->name);
5040         res->name      = mono_string_new (domain, g_path_get_basename (image->name));
5041         res->scopename = mono_string_new (domain, image->module_name);
5042
5043         if (image->assembly->image == image) {
5044                 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
5045         } else {
5046                 int i;
5047                 g_assert (image->assembly->image->modules);
5048                 res->token = 0;
5049                 while (image->assembly->image->modules [i]) {
5050                         if (image->assembly->image->modules [i] == image)
5051                                 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
5052                 }
5053                 g_assert (res->token);
5054         }
5055
5056         mono_image_addref (image);
5057
5058         CACHE_OBJECT (image, res, NULL);
5059         return res;
5060 }
5061
5062 MonoReflectionModule*   
5063 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
5064 {
5065         static MonoClass *System_Reflection_Module;
5066         MonoReflectionModule *res;
5067         MonoTableInfo *table;
5068         guint32 cols [MONO_FILE_SIZE];
5069         const char *name;
5070         guint32 i, name_idx;
5071         const char *val;
5072         
5073         if (!System_Reflection_Module)
5074                 System_Reflection_Module = mono_class_from_name (
5075                         mono_defaults.corlib, "System.Reflection", "Module");
5076         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
5077
5078         table = &image->tables [MONO_TABLE_FILE];
5079         g_assert (table_index < table->rows);
5080         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
5081
5082         res->image = 0;
5083         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
5084         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
5085
5086         /* Check whenever the row has a corresponding row in the moduleref table */
5087         table = &image->tables [MONO_TABLE_MODULEREF];
5088         for (i = 0; i < table->rows; ++i) {
5089                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
5090                 val = mono_metadata_string_heap (image, name_idx);
5091                 if (strcmp (val, name) == 0)
5092                         res->image = image->modules [i];
5093         }
5094
5095         res->fqname    = mono_string_new (domain, name);
5096         res->name      = mono_string_new (domain, name);
5097         res->scopename = mono_string_new (domain, name);
5098         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
5099         res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
5100
5101         return res;
5102 }
5103
5104 static gboolean
5105 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
5106 {
5107         if ((t1->type != t2->type) ||
5108             (t1->byref != t2->byref))
5109                 return FALSE;
5110
5111         switch (t1->type) {
5112         case MONO_TYPE_VOID:
5113         case MONO_TYPE_BOOLEAN:
5114         case MONO_TYPE_CHAR:
5115         case MONO_TYPE_I1:
5116         case MONO_TYPE_U1:
5117         case MONO_TYPE_I2:
5118         case MONO_TYPE_U2:
5119         case MONO_TYPE_I4:
5120         case MONO_TYPE_U4:
5121         case MONO_TYPE_I8:
5122         case MONO_TYPE_U8:
5123         case MONO_TYPE_R4:
5124         case MONO_TYPE_R8:
5125         case MONO_TYPE_STRING:
5126         case MONO_TYPE_I:
5127         case MONO_TYPE_U:
5128         case MONO_TYPE_OBJECT:
5129         case MONO_TYPE_TYPEDBYREF:
5130                 return TRUE;
5131         case MONO_TYPE_VALUETYPE:
5132         case MONO_TYPE_CLASS:
5133         case MONO_TYPE_SZARRAY:
5134                 return t1->data.klass == t2->data.klass;
5135         case MONO_TYPE_PTR:
5136                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
5137         case MONO_TYPE_ARRAY:
5138                 if (t1->data.array->rank != t2->data.array->rank)
5139                         return FALSE;
5140                 return t1->data.array->eklass == t2->data.array->eklass;
5141         case MONO_TYPE_GENERICINST: {
5142                 int i;
5143                 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
5144                         return FALSE;
5145                 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
5146                         return FALSE;
5147                 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
5148                         if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
5149                                 return FALSE;
5150                 }
5151                 return TRUE;
5152         }
5153         case MONO_TYPE_VAR:
5154         case MONO_TYPE_MVAR:
5155                 return t1->data.generic_param == t2->data.generic_param;
5156         default:
5157                 g_error ("implement type compare for %0x!", t1->type);
5158                 return FALSE;
5159         }
5160
5161         return FALSE;
5162 }
5163
5164 static guint
5165 mymono_metadata_type_hash (MonoType *t1)
5166 {
5167         guint hash;
5168
5169         hash = t1->type;
5170
5171         hash |= t1->byref << 6; /* do not collide with t1->type values */
5172         switch (t1->type) {
5173         case MONO_TYPE_VALUETYPE:
5174         case MONO_TYPE_CLASS:
5175         case MONO_TYPE_SZARRAY:
5176                 /* check if the distribution is good enough */
5177                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
5178         case MONO_TYPE_PTR:
5179                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
5180         }
5181         return hash;
5182 }
5183
5184 static MonoReflectionGenericInst*
5185 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
5186 {
5187         static MonoClass *System_Reflection_MonoGenericInst;
5188         MonoReflectionGenericInst *res;
5189         MonoGenericInst *ginst;
5190         MonoClass *gklass;
5191
5192         if (!System_Reflection_MonoGenericInst) {
5193                 System_Reflection_MonoGenericInst = mono_class_from_name (
5194                         mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
5195                 g_assert (System_Reflection_MonoGenericInst);
5196         }
5197
5198         ginst = geninst->data.generic_inst;
5199         gklass = mono_class_from_mono_type (ginst->generic_type);
5200
5201         mono_class_init (ginst->klass);
5202
5203         res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
5204
5205         res->type.type = geninst;
5206         if (gklass->wastypebuilder && gklass->reflection_info)
5207                 res->generic_type = gklass->reflection_info;
5208         else
5209                 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
5210
5211         return res;
5212 }
5213
5214 /*
5215  * mono_type_get_object:
5216  * @domain: an app domain
5217  * @type: a type
5218  *
5219  * Return an System.MonoType object representing the type @type.
5220  */
5221 MonoReflectionType*
5222 mono_type_get_object (MonoDomain *domain, MonoType *type)
5223 {
5224         MonoReflectionType *res;
5225         MonoClass *klass = mono_class_from_mono_type (type);
5226
5227         mono_domain_lock (domain);
5228         if (!domain->type_hash)
5229                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
5230                                 (GCompareFunc)mymono_metadata_type_equal);
5231         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
5232                 mono_domain_unlock (domain);
5233                 return res;
5234         }
5235         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
5236                 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
5237                 mono_g_hash_table_insert (domain->type_hash, type, res);
5238                 mono_domain_unlock (domain);
5239                 return res;
5240         }
5241         if (klass->reflection_info && !klass->wastypebuilder) {
5242                 /* g_assert_not_reached (); */
5243                 /* should this be considered an error condition? */
5244                 if (!type->byref) {
5245                         mono_domain_unlock (domain);
5246                         return klass->reflection_info;
5247                 }
5248         }
5249         mono_class_init (klass);
5250         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5251         res->type = type;
5252         mono_g_hash_table_insert (domain->type_hash, type, res);
5253         mono_domain_unlock (domain);
5254         return res;
5255 }
5256
5257 /*
5258  * mono_method_get_object:
5259  * @domain: an app domain
5260  * @method: a method
5261  * @refclass: the reflected type (can be NULL)
5262  *
5263  * Return an System.Reflection.MonoMethod object representing the method @method.
5264  */
5265 MonoReflectionMethod*
5266 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5267 {
5268         /*
5269          * We use the same C representation for methods and constructors, but the type 
5270          * name in C# is different.
5271          */
5272         const char *cname;
5273         MonoClass *klass;
5274         MonoReflectionMethod *ret;
5275
5276         if (!refclass)
5277                 refclass = method->klass;
5278
5279         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5280         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5281                 cname = "MonoCMethod";
5282         else
5283                 cname = "MonoMethod";
5284         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5285
5286         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5287         ret->method = method;
5288         ret->name = mono_string_new (domain, method->name);
5289         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5290         CACHE_OBJECT (method, ret, refclass);
5291         return ret;
5292 }
5293
5294 /*
5295  * mono_field_get_object:
5296  * @domain: an app domain
5297  * @klass: a type
5298  * @field: a field
5299  *
5300  * Return an System.Reflection.MonoField object representing the field @field
5301  * in class @klass.
5302  */
5303 MonoReflectionField*
5304 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5305 {
5306         MonoReflectionField *res;
5307         MonoClass *oklass;
5308
5309         CHECK_OBJECT (MonoReflectionField *, field, klass);
5310         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5311         res = (MonoReflectionField *)mono_object_new (domain, oklass);
5312         res->klass = klass;
5313         res->field = field;
5314         res->name = mono_string_new (domain, field->name);
5315         if (field->generic_info)
5316                 res->attrs = field->generic_info->generic_type->attrs;
5317         else
5318                 res->attrs = field->type->attrs;
5319         res->type = mono_type_get_object (domain, field->type);
5320         CACHE_OBJECT (field, res, klass);
5321         return res;
5322 }
5323
5324 /*
5325  * mono_property_get_object:
5326  * @domain: an app domain
5327  * @klass: a type
5328  * @property: a property
5329  *
5330  * Return an System.Reflection.MonoProperty object representing the property @property
5331  * in class @klass.
5332  */
5333 MonoReflectionProperty*
5334 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5335 {
5336         MonoReflectionProperty *res;
5337         MonoClass *oklass;
5338
5339         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5340         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5341         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5342         res->klass = klass;
5343         res->property = property;
5344         CACHE_OBJECT (property, res, klass);
5345         return res;
5346 }
5347
5348 /*
5349  * mono_event_get_object:
5350  * @domain: an app domain
5351  * @klass: a type
5352  * @event: a event
5353  *
5354  * Return an System.Reflection.MonoEvent object representing the event @event
5355  * in class @klass.
5356  */
5357 MonoReflectionEvent*
5358 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5359 {
5360         MonoReflectionEvent *res;
5361         MonoClass *oklass;
5362
5363         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5364         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5365         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5366         res->klass = klass;
5367         res->event = event;
5368         CACHE_OBJECT (event, res, klass);
5369         return res;
5370 }
5371
5372 /*
5373  * mono_param_get_objects:
5374  * @domain: an app domain
5375  * @method: a method
5376  *
5377  * Return an System.Reflection.ParameterInfo array object representing the parameters
5378  * in the method @method.
5379  */
5380 MonoArray*
5381 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5382 {
5383         static MonoClass *System_Reflection_ParameterInfo;
5384         MonoClass *klass;
5385         MonoArray *res = NULL;
5386         MonoReflectionMethod *member = NULL;
5387         MonoReflectionParameter *param = NULL;
5388         char **names, **blobs = NULL;
5389         MonoObject *dbnull = mono_get_dbnull_object (domain);
5390         int i;
5391
5392         if (!System_Reflection_ParameterInfo)
5393                 System_Reflection_ParameterInfo = mono_class_from_name (
5394                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5395         
5396         if (!method->signature->param_count)
5397                 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5398
5399         /* Note: the cache is based on the address of the signature into the method
5400          * since we already cache MethodInfos with the method as keys.
5401          */
5402         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5403
5404         member = mono_method_get_object (domain, method, NULL);
5405         names = g_new (char *, method->signature->param_count);
5406         mono_method_get_param_names (method, (const char **) names);
5407
5408         res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5409         for (i = 0; i < method->signature->param_count; ++i) {
5410                 param = (MonoReflectionParameter *)mono_object_new (domain, System_Reflection_ParameterInfo);
5411                 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5412                 param->MemberImpl = (MonoObject*)member;
5413                 param->NameImpl = mono_string_new (domain, names [i]);
5414                 param->PositionImpl = i;
5415                 param->AttrsImpl = method->signature->params [i]->attrs;
5416
5417                 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
5418                         param->DefaultValueImpl = dbnull;
5419                 } else {
5420                         MonoType *type = param->ClassImpl->type;
5421                         
5422                         if (!blobs) {
5423                                 blobs = g_new0 (char *, method->signature->param_count);
5424                                 get_default_param_value_blobs (method, blobs); 
5425                         }
5426
5427                         param->DefaultValueImpl = mono_get_object_from_blob (domain, type, blobs [i]);
5428
5429                         if (!param->DefaultValueImpl) {
5430                                 param->DefaultValueImpl = dbnull;
5431                         }
5432                 }
5433                 
5434                 mono_array_set (res, gpointer, i, param);
5435         }
5436         g_free (names);
5437         g_free (blobs);
5438         
5439         CACHE_OBJECT (&(method->signature), res, NULL);
5440         return res;
5441 }
5442
5443 MonoObject *
5444 mono_get_dbnull_object (MonoDomain *domain)
5445 {
5446         MonoObject *obj;
5447         MonoClass *klass;
5448         static MonoClassField *dbnull_value_field = NULL;
5449         
5450         if (!dbnull_value_field) {
5451                 klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
5452                 mono_class_init (klass);
5453                 dbnull_value_field = mono_class_get_field_from_name (klass, "Value");
5454                 g_assert (dbnull_value_field);
5455         }
5456         obj = mono_field_get_value_object (domain, dbnull_value_field, NULL); 
5457         g_assert (obj);
5458         return obj;
5459 }
5460
5461
5462 static void
5463 get_default_param_value_blobs (MonoMethod *method, char **blobs)
5464 {
5465         guint32 param_index, i, lastp, crow = 0;
5466         guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
5467         gint32 idx = -1;
5468
5469         MonoClass *klass = method->klass;
5470         MonoImage *image = klass->image;
5471         MonoDomain *domain = mono_domain_get ();
5472         MonoMethodSignature *methodsig = method->signature;
5473
5474         MonoTableInfo *constt;
5475         MonoTableInfo *methodt;
5476         MonoTableInfo *paramt;
5477
5478         if (!methodsig->param_count)
5479                 return;
5480
5481         if (klass->generic_inst) {
5482                 return; /* FIXME - ??? */
5483         }
5484
5485         mono_class_init (klass);
5486
5487         if (klass->image->dynamic) {
5488                 return; /* FIXME */
5489         }
5490
5491         methodt = &klass->image->tables [MONO_TABLE_METHOD];
5492         paramt = &klass->image->tables [MONO_TABLE_PARAM];
5493         constt = &image->tables [MONO_TABLE_CONSTANT];
5494
5495         for (i = 0; i < klass->method.count; ++i) {
5496                 if (method == klass->methods [i]) {
5497                         idx = klass->method.first + i;
5498                         break;
5499                 }
5500         }
5501
5502         g_assert (idx != -1);
5503
5504         param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
5505         if (idx + 1 < methodt->rows)
5506                 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
5507         else
5508                 lastp = paramt->rows + 1;
5509
5510         for (i = param_index; i < lastp; ++i) {
5511                 guint32 paramseq;
5512
5513                 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
5514                 paramseq = param_cols [MONO_PARAM_SEQUENCE];
5515
5516                 if (!param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT) 
5517                         continue;
5518
5519                 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
5520                 if (!crow) {
5521                         continue;
5522                 }
5523         
5524                 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
5525                 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
5526         }
5527
5528         return;
5529 }
5530
5531 static MonoObject *
5532 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
5533 {
5534         void *retval;
5535         MonoClass *klass;
5536         MonoObject *object;
5537
5538         if (!blob)
5539                 return NULL;
5540         
5541         klass = mono_class_from_mono_type (type);
5542         if (klass->valuetype) {
5543                 object = mono_object_new (domain, klass);
5544                 retval = ((gchar *) object + sizeof (MonoObject));
5545         } else {
5546                 retval = &object;
5547         }
5548                         
5549         if (!mono_get_constant_value_from_blob (domain, type->type,  blob, retval))
5550                 return object;
5551         else
5552                 return NULL;
5553 }
5554
5555 static int
5556 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5557         int found_sep;
5558         char *s;
5559
5560         memset (assembly, 0, sizeof (MonoAssemblyName));
5561         assembly->name = p;
5562         assembly->culture = "";
5563         memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
5564
5565         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5566                 p++;
5567         found_sep = 0;
5568         while (*p == ' ' || *p == ',') {
5569                 *p++ = 0;
5570                 found_sep = 1;
5571                 continue;
5572         }
5573         /* failed */
5574         if (!found_sep)
5575                 return 1;
5576         while (*p) {
5577                 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
5578                         p += 8;
5579                         assembly->major = strtoul (p, &s, 10);
5580                         if (s == p || *s != '.')
5581                                 return 1;
5582                         p = ++s;
5583                         assembly->minor = strtoul (p, &s, 10);
5584                         if (s == p || *s != '.')
5585                                 return 1;
5586                         p = ++s;
5587                         assembly->build = strtoul (p, &s, 10);
5588                         if (s == p || *s != '.')
5589                                 return 1;
5590                         p = ++s;
5591                         assembly->revision = strtoul (p, &s, 10);
5592                         if (s == p)
5593                                 return 1;
5594                         p = s;
5595                 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
5596                         p += 8;
5597                         if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
5598                                 assembly->culture = "";
5599                                 p += 7;
5600                         } else {
5601                                 assembly->culture = p;
5602                                 while (*p && *p != ',') {
5603                                         p++;
5604                                 }
5605                         }
5606                 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
5607                         p += 15;
5608                         if (strncmp (p, "null", 4) == 0) {
5609                                 p += 4;
5610                         } else {
5611                                 int len;
5612                                 gchar *start = p;
5613                                 while (*p && *p != ',') {
5614                                         p++;
5615                                 }
5616                                 len = (p - start + 1);
5617                                 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
5618                                         len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
5619                                 g_strlcpy (assembly->public_key_token, start, len);
5620                         }
5621                 } else {
5622                         while (*p && *p != ',')
5623                                 p++;
5624                 }
5625                 found_sep = 0;
5626                 while (*p == ' ' || *p == ',') {
5627                         *p++ = 0;
5628                         found_sep = 1;
5629                         continue;
5630                 }
5631                 /* failed */
5632                 if (!found_sep)
5633                         return 1;
5634         }
5635
5636         return 0;
5637 }
5638
5639 /*
5640  * mono_reflection_parse_type:
5641  * @name: type name
5642  *
5643  * Parse a type name as accepted by the GetType () method and output the info
5644  * extracted in the info structure.
5645  * the name param will be mangled, so, make a copy before passing it to this function.
5646  * The fields in info will be valid until the memory pointed to by name is valid.
5647  * Returns 0 on parse error.
5648  * See also mono_type_get_name () below.
5649  */
5650 int
5651 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5652
5653         char *start, *p, *w, *last_point, *startn;
5654         int in_modifiers = 0;
5655         int isbyref = 0, rank;
5656
5657         start = p = w = name;
5658
5659         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5660         info->name = info->name_space = NULL;
5661         info->nested = NULL;
5662         info->modifiers = NULL;
5663
5664         /* last_point separates the namespace from the name */
5665         last_point = NULL;
5666
5667         while (*p) {
5668                 switch (*p) {
5669                 case '+':
5670                         *p = 0; /* NULL terminate the name */
5671                         startn = p + 1;
5672                         info->nested = g_list_append (info->nested, startn);
5673                         /* we have parsed the nesting namespace + name */
5674                         if (info->name)
5675                                 break;
5676                         if (last_point) {
5677                                 info->name_space = start;
5678                                 *last_point = 0;
5679                                 info->name = last_point + 1;
5680                         } else {
5681                                 info->name_space = (char *)"";
5682                                 info->name = start;
5683                         }
5684                         break;
5685                 case '.':
5686                         last_point = w;
5687                         break;
5688                 case '\\':
5689                         ++p;
5690                         break;
5691                 case '&':
5692                 case '*':
5693                 case '[':
5694                 case ',':
5695                         in_modifiers = 1;
5696                         break;
5697                 default:
5698                         break;
5699                 }
5700                 if (in_modifiers)
5701                         break;
5702                 *w++ = *p++;
5703         }
5704         
5705         if (!info->name) {
5706                 if (last_point) {
5707                         info->name_space = start;
5708                         *last_point = 0;
5709                         info->name = last_point + 1;
5710                 } else {
5711                         info->name_space = (char *)"";
5712                         info->name = start;
5713                 }
5714         }
5715         while (*p) {
5716                 switch (*p) {
5717                 case '&':
5718                         if (isbyref) /* only one level allowed by the spec */
5719                                 return 0;
5720                         isbyref = 1;
5721                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5722                         *p++ = 0;
5723                         break;
5724                 case '*':
5725                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5726                         *p++ = 0;
5727                         break;
5728                 case '[':
5729                         rank = 1;
5730                         *p++ = 0;
5731                         while (*p) {
5732                                 if (*p == ']')
5733                                         break;
5734                                 if (*p == ',')
5735                                         rank++;
5736                                 else if (*p != '*') /* '*' means unknown lower bound */
5737                                         return 0;
5738                                 ++p;
5739                         }
5740                         if (*p++ != ']')
5741                                 return 0;
5742                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5743                         break;
5744                 case ',':
5745                         *p++ = 0;
5746                         while (*p) {
5747                                 if (*p == ' ') {
5748                                         ++p;
5749                                         continue;
5750                                 }
5751                                 break;
5752                         }
5753                         if (!*p)
5754                                 return 0; /* missing assembly name */
5755                         if (!assembly_name_to_aname (&info->assembly, p))
5756                                 return 0;
5757                         break;
5758                 default:
5759                         return 0;
5760                         break;
5761                 }
5762                 if (info->assembly.name)
5763                         break;
5764         }
5765         *w = 0; /* terminate class name */
5766         if (!info->name || !*info->name)
5767                 return 0;
5768         /* add other consistency checks */
5769         return 1;
5770 }
5771
5772 static MonoType*
5773 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5774 {
5775         MonoClass *klass;
5776         GList *mod;
5777         int modval;
5778         
5779         if (!image)
5780                 image = mono_defaults.corlib;
5781
5782         if (ignorecase)
5783                 klass = mono_class_from_name_case (image, info->name_space, info->name);
5784         else
5785                 klass = mono_class_from_name (image, info->name_space, info->name);
5786         if (!klass)
5787                 return NULL;
5788         for (mod = info->nested; mod; mod = mod->next) {
5789                 GList *nested;
5790
5791                 mono_class_init (klass);
5792                 nested = klass->nested_classes;
5793                 klass = NULL;
5794                 while (nested) {
5795                         klass = nested->data;
5796                         if (ignorecase) {
5797                                 if (g_strcasecmp (klass->name, mod->data) == 0)
5798                                         break;
5799                         } else {
5800                                 if (strcmp (klass->name, mod->data) == 0)
5801                                         break;
5802                         }
5803                         klass = NULL;
5804                         nested = nested->next;
5805                 }
5806                 if (!klass)
5807                         break;
5808         }
5809         if (!klass)
5810                 return NULL;
5811         mono_class_init (klass);
5812         for (mod = info->modifiers; mod; mod = mod->next) {
5813                 modval = GPOINTER_TO_UINT (mod->data);
5814                 if (!modval) { /* byref: must be last modifier */
5815                         return &klass->this_arg;
5816                 } else if (modval == -1) {
5817                         klass = mono_ptr_class_get (&klass->byval_arg);
5818                 } else { /* array rank */
5819                         klass = mono_array_class_get (klass, modval);
5820                 }
5821                 mono_class_init (klass);
5822         }
5823
5824         return &klass->byval_arg;
5825 }
5826
5827 /*
5828  * mono_reflection_get_type:
5829  * @image: a metadata context
5830  * @info: type description structure
5831  * @ignorecase: flag for case-insensitive string compares
5832  * @type_resolve: whenever type resolve was already tried
5833  *
5834  * Build a MonoType from the type description in @info.
5835  * 
5836  */
5837
5838 MonoType*
5839 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5840 {
5841         MonoType *type;
5842         MonoReflectionAssembly *assembly;
5843         GString *fullName;
5844         GList *mod;
5845
5846         type = mono_reflection_get_type_internal (image, info, ignorecase);
5847         if (type)
5848                 return type;
5849         if (!mono_domain_has_type_resolve (mono_domain_get ()))
5850                 return NULL;
5851
5852         /* FIXME: Enabling this causes regressions (#65577) */
5853         /*
5854         if (type_resolve) {
5855                 if (*type_resolve) 
5856                         return NULL;
5857                 else
5858                         *type_resolve = TRUE;
5859         }
5860         */
5861         
5862         /* Reconstruct the type name */
5863         fullName = g_string_new ("");
5864         if (info->name_space && (info->name_space [0] != '\0'))
5865                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5866         else
5867                 g_string_printf (fullName, info->name);
5868         for (mod = info->nested; mod; mod = mod->next)
5869                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5870
5871         assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
5872         if (assembly && (!image || (assembly->assembly->image == image))) {
5873
5874                 if (assembly->assembly->dynamic) {
5875                         /* Enumerate all modules */
5876                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5877                         int i;
5878
5879                         type = NULL;
5880                         if (abuilder->modules) {
5881                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5882                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5883                                         type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5884                                         if (type)
5885                                                 break;
5886                                 }
5887                         }
5888
5889                         if (!type && abuilder->loaded_modules) {
5890                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5891                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5892                                         type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5893                                         if (type)
5894                                                 break;
5895                                 }
5896                         }
5897                 }
5898                 else
5899                         type = mono_reflection_get_type_internal (assembly->assembly->image, 
5900                                                                                                           info, ignorecase);
5901         }
5902         g_string_free (fullName, TRUE);
5903         return type;
5904 }
5905
5906 /*
5907  * mono_reflection_type_from_name:
5908  * @name: type name.
5909  * @image: a metadata context (can be NULL).
5910  *
5911  * Retrieves a MonoType from its @name. If the name is not fully qualified,
5912  * it defaults to get the type from @image or, if @image is NULL or loading
5913  * from it fails, uses corlib.
5914  * 
5915  */
5916 MonoType*
5917 mono_reflection_type_from_name (char *name, MonoImage *image)
5918 {
5919         MonoType *type;
5920         MonoTypeNameParse info;
5921         MonoAssembly *assembly;
5922         char *tmp;
5923         gboolean type_resolve = FALSE;
5924
5925         /* Make a copy since parse_type modifies its argument */
5926         tmp = g_strdup (name);
5927         
5928         /*g_print ("requested type %s\n", str);*/
5929         if (!mono_reflection_parse_type (tmp, &info)) {
5930                 g_free (tmp);
5931                 g_list_free (info.modifiers);
5932                 g_list_free (info.nested);
5933                 return NULL;
5934         }
5935
5936         if (info.assembly.name) {
5937                 assembly = mono_assembly_loaded (&info.assembly);
5938                 if (!assembly) {
5939                         /* then we must load the assembly ourselve - see #60439 */
5940                         assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5941                         if (!assembly) {
5942                                 g_free (tmp);
5943                                 g_list_free (info.modifiers);
5944                                 g_list_free (info.nested);
5945                                 return NULL;
5946                         }
5947                 }
5948                 image = assembly->image;
5949         } else if (image == NULL) {
5950                 image = mono_defaults.corlib;
5951         }
5952
5953         type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5954         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5955                 image = mono_defaults.corlib;
5956                 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5957         }
5958
5959         g_free (tmp);
5960         g_list_free (info.modifiers);
5961         g_list_free (info.nested);
5962         return type;
5963 }
5964
5965 /*
5966  * mono_reflection_get_token:
5967  *
5968  *   Return the metadata token of OBJ which should be an object
5969  * representing a metadata element.
5970  */
5971 guint32
5972 mono_reflection_get_token (MonoObject *obj)
5973 {
5974         MonoClass *klass;
5975         guint32 token = 0;
5976
5977         klass = obj->vtable->klass;
5978
5979         if (strcmp (klass->name, "MethodBuilder") == 0) {
5980                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
5981
5982                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5983         } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
5984                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
5985
5986                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
5987         } else if (strcmp (klass->name, "FieldBuilder") == 0) {
5988                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
5989                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
5990                 if (tb->generic_params) {
5991                         g_assert_not_reached ();
5992                 } else {
5993                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
5994                 }
5995         } else if (strcmp (klass->name, "TypeBuilder") == 0) {
5996                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
5997                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
5998         } else if (strcmp (klass->name, "MonoType") == 0) {
5999                 MonoReflectionType *tb = (MonoReflectionType *)obj;
6000                 token = mono_class_from_mono_type (tb->type)->type_token;
6001         } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
6002                         strcmp (klass->name, "MonoMethod") == 0) {
6003                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
6004                 if (m->method->signature->is_inflated) {
6005                         g_assert_not_reached ();
6006                 } else if (m->method->signature->generic_param_count) {
6007                         g_assert_not_reached ();
6008                 } else if (m->method->klass->generic_inst) {
6009                         g_assert_not_reached ();
6010                 } else {
6011                         token = m->method->token;
6012                 }
6013         } else if (strcmp (klass->name, "MonoField") == 0) {
6014                 MonoReflectionField *f = (MonoReflectionField*)obj;
6015
6016                 token = mono_class_get_field_token (f->field);
6017         } else if (strcmp (klass->name, "MonoProperty") == 0) {
6018                 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
6019
6020                 token = mono_class_get_property_token (p->property);
6021         } else if (strcmp (klass->name, "MonoEvent") == 0) {
6022                 MonoReflectionEvent *p = (MonoReflectionEvent*)obj;
6023
6024                 token = mono_class_get_event_token (p->event);
6025         } else if (strcmp (klass->name, "ParameterInfo") == 0) {
6026                 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
6027
6028                 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
6029         } else if (strcmp (klass->name, "Module") == 0) {
6030                 MonoReflectionModule *m = (MonoReflectionModule*)obj;
6031
6032                 token = m->token;
6033         } else if (strcmp (klass->name, "Assembly") == 0) {
6034                 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
6035         } else {
6036                 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
6037                 MonoException *ex = mono_get_exception_not_implemented (msg);
6038                 g_free (msg);
6039                 mono_raise_exception (ex);
6040         }
6041
6042         return token;
6043 }
6044
6045 static void*
6046 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
6047 {
6048         int slen, type = t->type;
6049 handle_enum:
6050         switch (type) {
6051         case MONO_TYPE_U1:
6052         case MONO_TYPE_I1:
6053         case MONO_TYPE_BOOLEAN: {
6054                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
6055                 *bval = *p;
6056                 *end = p + 1;
6057                 return bval;
6058         }
6059         case MONO_TYPE_CHAR:
6060         case MONO_TYPE_U2:
6061         case MONO_TYPE_I2: {
6062                 guint16 *val = g_malloc (sizeof (guint16));
6063                 *val = read16 (p);
6064                 *end = p + 2;
6065                 return val;
6066         }
6067 #if SIZEOF_VOID_P == 4
6068         case MONO_TYPE_U:
6069         case MONO_TYPE_I:
6070 #endif
6071         case MONO_TYPE_R4:
6072         case MONO_TYPE_U4:
6073         case MONO_TYPE_I4: {
6074                 guint32 *val = g_malloc (sizeof (guint32));
6075                 *val = read32 (p);
6076                 *end = p + 4;
6077                 return val;
6078         }
6079 #if SIZEOF_VOID_P == 8
6080         case MONO_TYPE_U: /* error out instead? this should probably not happen */
6081         case MONO_TYPE_I:
6082 #endif
6083         case MONO_TYPE_R8:
6084         case MONO_TYPE_U8:
6085         case MONO_TYPE_I8: {
6086                 guint64 *val = g_malloc (sizeof (guint64));
6087                 *val = read64 (p);
6088                 *end = p + 8;
6089                 return val;
6090         }
6091         case MONO_TYPE_VALUETYPE:
6092                 if (t->data.klass->enumtype) {
6093                         type = t->data.klass->enum_basetype->type;
6094                         goto handle_enum;
6095                 } else {
6096                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
6097                 }
6098                 break;
6099         case MONO_TYPE_STRING:
6100                 if (*p == (char)0xFF) {
6101                         *end = p + 1;
6102                         return NULL;
6103                 }
6104                 slen = mono_metadata_decode_value (p, &p);
6105                 *end = p + slen;
6106                 return mono_string_new_len (mono_domain_get (), p, slen);
6107         case MONO_TYPE_CLASS: {
6108                 char *n;
6109                 MonoType *t;
6110                 if (*p == (char)0xFF) {
6111                         *end = p + 1;
6112                         return NULL;
6113                 }
6114 handle_type:
6115                 slen = mono_metadata_decode_value (p, &p);
6116                 n = g_memdup (p, slen + 1);
6117                 n [slen] = 0;
6118                 t = mono_reflection_type_from_name (n, image);
6119                 if (!t)
6120                         g_warning ("Cannot load type '%s'", n);
6121                 g_free (n);
6122                 *end = p + slen;
6123                 if (t)
6124                         return mono_type_get_object (mono_domain_get (), t);
6125                 else
6126                         return NULL;
6127         }
6128         case MONO_TYPE_OBJECT: {
6129                 char subt = *p++;
6130                 MonoObject *obj;
6131                 MonoClass *subc = NULL;
6132                 void *val;
6133
6134                 if (subt == 0x50) {
6135                         goto handle_type;
6136                 } else if (subt == 0x0E) {
6137                         type = MONO_TYPE_STRING;
6138                         goto handle_enum;
6139                 } else if (subt == 0x55) {
6140                         char *n;
6141                         MonoType *t;
6142                         slen = mono_metadata_decode_value (p, &p);
6143                         n = g_memdup (p, slen + 1);
6144                         n [slen] = 0;
6145                         t = mono_reflection_type_from_name (n, image);
6146                         if (!t)
6147                                 g_warning ("Cannot load type '%s'", n);
6148                         g_free (n);
6149                         p += slen;
6150                         subc = mono_class_from_mono_type (t);
6151                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
6152                         MonoType simple_type = {{0}};
6153                         simple_type.type = subt;
6154                         subc = mono_class_from_mono_type (&simple_type);
6155                 } else {
6156                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
6157                 }
6158                 val = load_cattr_value (image, &subc->byval_arg, p, end);
6159                 obj = mono_object_new (mono_domain_get (), subc);
6160                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
6161                 g_free (val);
6162                 return obj;
6163         }
6164         case MONO_TYPE_SZARRAY: {
6165                 MonoArray *arr;
6166                 guint32 i, alen, basetype;
6167                 alen = read32 (p);
6168                 p += 4;
6169                 if (alen == 0xffffffff) {
6170                         *end = p;
6171                         return NULL;
6172                 }
6173                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
6174                 basetype = t->data.klass->byval_arg.type;
6175                 switch (basetype)
6176                 {
6177                         case MONO_TYPE_U1:
6178                         case MONO_TYPE_I1:
6179                         case MONO_TYPE_BOOLEAN:
6180                                 for (i = 0; i < alen; i++) {
6181                                         MonoBoolean val = *p++;
6182                                         mono_array_set (arr, MonoBoolean, i, val);
6183                                 }
6184                                 break;
6185                         case MONO_TYPE_CHAR:
6186                         case MONO_TYPE_U2:
6187                         case MONO_TYPE_I2:
6188                                 for (i = 0; i < alen; i++) {
6189                                         guint16 val = read16 (p);
6190                                         mono_array_set (arr, guint16, i, val);
6191                                         p += 2;
6192                                 }
6193                                 break;
6194                         case MONO_TYPE_R4:
6195                         case MONO_TYPE_U4:
6196                         case MONO_TYPE_I4:
6197                                 for (i = 0; i < alen; i++) {
6198                                         guint32 val = read32 (p);
6199                                         mono_array_set (arr, guint32, i, val);
6200                                         p += 4;
6201                                 }
6202                                 break;
6203                         case MONO_TYPE_R8:
6204                         case MONO_TYPE_U8:
6205                         case MONO_TYPE_I8:
6206                                 for (i = 0; i < alen; i++) {
6207                                         guint64 val = read64 (p);
6208                                         mono_array_set (arr, guint64, i, val);
6209                                         p += 8;
6210                                 }
6211                                 break;
6212                         case MONO_TYPE_CLASS:
6213                         case MONO_TYPE_OBJECT:
6214                         case MONO_TYPE_STRING:
6215                                 for (i = 0; i < alen; i++) {
6216                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
6217                                         mono_array_set (arr, gpointer, i, item);
6218                                 }
6219                                 break;
6220                         default:
6221                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
6222                 }
6223                 *end=p;
6224                 return arr;
6225         }
6226         default:
6227                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
6228         }
6229         return NULL;
6230 }
6231
6232 static gboolean
6233 type_is_reference (MonoType *type)
6234 {
6235         switch (type->type) {
6236         case MONO_TYPE_BOOLEAN:
6237         case MONO_TYPE_CHAR:
6238         case MONO_TYPE_U:
6239         case MONO_TYPE_I:
6240         case MONO_TYPE_U1:
6241         case MONO_TYPE_I1:
6242         case MONO_TYPE_U2:
6243         case MONO_TYPE_I2:
6244         case MONO_TYPE_U4:
6245         case MONO_TYPE_I4:
6246         case MONO_TYPE_U8:
6247         case MONO_TYPE_I8:
6248         case MONO_TYPE_R8:
6249         case MONO_TYPE_R4:
6250         case MONO_TYPE_VALUETYPE:
6251                 return FALSE;
6252         default:
6253                 return TRUE;
6254         }
6255 }
6256
6257 static void
6258 free_param_data (MonoMethodSignature *sig, void **params) {
6259         int i;
6260         for (i = 0; i < sig->param_count; ++i) {
6261                 if (!type_is_reference (sig->params [i]))
6262                         g_free (params [i]);
6263         }
6264 }
6265
6266 /*
6267  * Find the method index in the metadata methodDef table.
6268  * Later put these three helper methods in metadata and export them.
6269  */
6270 static guint32
6271 find_method_index (MonoMethod *method) {
6272         MonoClass *klass = method->klass;
6273         int i;
6274
6275         for (i = 0; i < klass->method.count; ++i) {
6276                 if (method == klass->methods [i])
6277                         return klass->method.first + 1 + i;
6278         }
6279         return 0;
6280 }
6281
6282 /*
6283  * Find the field index in the metadata FieldDef table.
6284  */
6285 static guint32
6286 find_field_index (MonoClass *klass, MonoClassField *field) {
6287         int i;
6288
6289         for (i = 0; i < klass->field.count; ++i) {
6290                 if (field == &klass->fields [i])
6291                         return klass->field.first + 1 + i;
6292         }
6293         return 0;
6294 }
6295
6296 /*
6297  * Find the property index in the metadata Property table.
6298  */
6299 static guint32
6300 find_property_index (MonoClass *klass, MonoProperty *property) {
6301         int i;
6302
6303         for (i = 0; i < klass->property.count; ++i) {
6304                 if (property == &klass->properties [i])
6305                         return klass->property.first + 1 + i;
6306         }
6307         return 0;
6308 }
6309
6310 /*
6311  * Find the event index in the metadata Event table.
6312  */
6313 static guint32
6314 find_event_index (MonoClass *klass, MonoEvent *event) {
6315         int i;
6316
6317         for (i = 0; i < klass->event.count; ++i) {
6318                 if (event == &klass->events [i])
6319                         return klass->event.first + 1 + i;
6320         }
6321         return 0;
6322 }
6323
6324 static MonoObject*
6325 create_custom_attr (MonoImage *image, MonoMethod *method, const char *data, guint32 len)
6326 {
6327         const char *p = data;
6328         const char *named;
6329         guint32 i, j, num_named;
6330         MonoObject *attr;
6331         void **params;
6332
6333         mono_class_init (method->klass);
6334
6335         if (len == 0) {
6336                 attr = mono_object_new (mono_domain_get (), method->klass);
6337                 mono_runtime_invoke (method, attr, NULL, NULL);
6338                 return attr;
6339         }
6340
6341         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6342                 return NULL;
6343
6344         /*g_print ("got attr %s\n", method->klass->name);*/
6345         
6346         params = g_new (void*, method->signature->param_count);
6347
6348         /* skip prolog */
6349         p += 2;
6350         for (i = 0; i < method->signature->param_count; ++i) {
6351                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6352         }
6353
6354         named = p;
6355         attr = mono_object_new (mono_domain_get (), method->klass);
6356         mono_runtime_invoke (method, attr, params, NULL);
6357         free_param_data (method->signature, params);
6358         g_free (params);
6359         num_named = read16 (named);
6360         named += 2;
6361         for (j = 0; j < num_named; j++) {
6362                 gint name_len;
6363                 char *name, named_type, data_type;
6364                 named_type = *named++;
6365                 data_type = *named++; /* type of data */
6366                 if (data_type == 0x55) {
6367                         gint type_len;
6368                         char *type_name;
6369                         type_len = mono_metadata_decode_blob_size (named, &named);
6370                         type_name = g_malloc (type_len + 1);
6371                         memcpy (type_name, named, type_len);
6372                         type_name [type_len] = 0;
6373                         named += type_len;
6374                         /* FIXME: lookup the type and check type consistency */
6375                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6376                         /* this seems to be the type of the element of the array */
6377                         /* g_print ("skipping 0x%02x after prop\n", *named); */
6378                         named++;
6379                 }
6380                 name_len = mono_metadata_decode_blob_size (named, &named);
6381                 name = g_malloc (name_len + 1);
6382                 memcpy (name, named, name_len);
6383                 name [name_len] = 0;
6384                 named += name_len;
6385                 if (named_type == 0x53) {
6386                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6387                         void *val = load_cattr_value (image, field->type, named, &named);
6388                         mono_field_set_value (attr, field, val);
6389                         if (!type_is_reference (field->type))
6390                                 g_free (val);
6391                 } else if (named_type == 0x54) {
6392                         MonoProperty *prop;
6393                         void *pparams [1];
6394                         MonoType *prop_type;
6395
6396                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6397                         /* can we have more that 1 arg in a custom attr named property? */
6398                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6399                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
6400                         mono_property_set_value (prop, attr, pparams, NULL);
6401                         if (!type_is_reference (prop_type))
6402                                 g_free (pparams [0]);
6403                 }
6404                 g_free (name);
6405         }
6406
6407         return attr;
6408 }
6409
6410 MonoArray*
6411 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6412 {
6413         MonoArray *result;
6414         MonoClass *klass;
6415         MonoObject *attr;
6416         int i;
6417
6418         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6419         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6420         for (i = 0; i < cinfo->num_attrs; ++i) {
6421                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6422                 mono_array_set (result, gpointer, i, attr);
6423         }
6424         return result;
6425 }
6426
6427 MonoCustomAttrInfo*
6428 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6429 {
6430         guint32 mtoken, i, len;
6431         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6432         MonoTableInfo *ca;
6433         MonoCustomAttrInfo *ainfo;
6434         GList *tmp, *list = NULL;
6435         const char *data;
6436
6437         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6438
6439         i = mono_metadata_custom_attrs_from_index (image, idx);
6440         if (!i)
6441                 return NULL;
6442         i --;
6443         while (i < ca->rows) {
6444                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6445                         break;
6446                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6447                 ++i;
6448         }
6449         len = g_list_length (list);
6450         if (!len)
6451                 return NULL;
6452         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6453         ainfo->num_attrs = len;
6454         ainfo->image = image;
6455         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6456                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6457                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6458                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6459                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6460                         mtoken |= MONO_TOKEN_METHOD_DEF;
6461                         break;
6462                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6463                         mtoken |= MONO_TOKEN_MEMBER_REF;
6464                         break;
6465                 default:
6466                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6467                         break;
6468                 }
6469                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6470                 if (!ainfo->attrs [i].ctor)
6471                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6472                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6473                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6474                 ainfo->attrs [i].data = data;
6475         }
6476         g_list_free (list);
6477
6478         return ainfo;
6479 }
6480
6481 MonoCustomAttrInfo*
6482 mono_custom_attrs_from_method (MonoMethod *method)
6483 {
6484         MonoCustomAttrInfo *cinfo;
6485         guint32 idx;
6486         
6487         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6488                 return cinfo;
6489         idx = find_method_index (method);
6490         idx <<= MONO_CUSTOM_ATTR_BITS;
6491         idx |= MONO_CUSTOM_ATTR_METHODDEF;
6492         return mono_custom_attrs_from_index (method->klass->image, idx);
6493 }
6494
6495 MonoCustomAttrInfo*
6496 mono_custom_attrs_from_class (MonoClass *klass)
6497 {
6498         MonoCustomAttrInfo *cinfo;
6499         guint32 idx;
6500         
6501         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6502                 return cinfo;
6503         idx = mono_metadata_token_index (klass->type_token);
6504         idx <<= MONO_CUSTOM_ATTR_BITS;
6505         idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6506         return mono_custom_attrs_from_index (klass->image, idx);
6507 }
6508
6509 MonoCustomAttrInfo*
6510 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6511 {
6512         MonoCustomAttrInfo *cinfo;
6513         guint32 idx;
6514         
6515         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6516                 return cinfo;
6517         idx = 1; /* there is only one assembly */
6518         idx <<= MONO_CUSTOM_ATTR_BITS;
6519         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6520         return mono_custom_attrs_from_index (assembly->image, idx);
6521 }
6522
6523 static MonoCustomAttrInfo*
6524 mono_custom_attrs_from_module (MonoImage *image)
6525 {
6526         MonoCustomAttrInfo *cinfo;
6527         guint32 idx;
6528         
6529         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6530                 return cinfo;
6531         idx = 1; /* there is only one module */
6532         idx <<= MONO_CUSTOM_ATTR_BITS;
6533         idx |= MONO_CUSTOM_ATTR_MODULE;
6534         return mono_custom_attrs_from_index (image, idx);
6535 }
6536
6537 MonoCustomAttrInfo*
6538 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6539 {
6540         MonoCustomAttrInfo *cinfo;
6541         guint32 idx;
6542         
6543         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6544                 return cinfo;
6545         idx = find_property_index (klass, property);
6546         idx <<= MONO_CUSTOM_ATTR_BITS;
6547         idx |= MONO_CUSTOM_ATTR_PROPERTY;
6548         return mono_custom_attrs_from_index (klass->image, idx);
6549 }
6550
6551 MonoCustomAttrInfo*
6552 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6553 {
6554         MonoCustomAttrInfo *cinfo;
6555         guint32 idx;
6556         
6557         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6558                 return cinfo;
6559         idx = find_event_index (klass, event);
6560         idx <<= MONO_CUSTOM_ATTR_BITS;
6561         idx |= MONO_CUSTOM_ATTR_EVENT;
6562         return mono_custom_attrs_from_index (klass->image, idx);
6563 }
6564
6565 MonoCustomAttrInfo*
6566 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6567 {
6568         MonoCustomAttrInfo *cinfo;
6569         guint32 idx;
6570         
6571         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6572                 return cinfo;
6573         idx = find_field_index (klass, field);
6574         idx <<= MONO_CUSTOM_ATTR_BITS;
6575         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6576         return mono_custom_attrs_from_index (klass->image, idx);
6577 }
6578
6579 MonoCustomAttrInfo*
6580 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6581 {
6582         MonoTableInfo *ca;
6583         guint32 i, idx, method_index;
6584         guint32 param_list, param_last, param_pos, found;
6585         MonoImage *image;
6586         MonoReflectionMethodAux *aux;
6587
6588         if (method->klass->image->dynamic) {
6589                 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6590                 if (!aux || !aux->param_cattr)
6591                         return NULL;
6592                 return aux->param_cattr [param];
6593         }
6594
6595         image = method->klass->image;
6596         method_index = find_method_index (method);
6597         ca = &image->tables [MONO_TABLE_METHOD];
6598
6599         if (method->klass->generic_inst || method->klass->gen_params ||
6600                         method->signature->generic_param_count) {
6601                 /* FIXME FIXME FIXME */
6602                 return NULL;
6603         }
6604
6605         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6606         if (method_index == ca->rows) {
6607                 ca = &image->tables [MONO_TABLE_PARAM];
6608                 param_last = ca->rows + 1;
6609         } else {
6610                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6611                 ca = &image->tables [MONO_TABLE_PARAM];
6612         }
6613         found = FALSE;
6614         for (i = param_list; i < param_last; ++i) {
6615                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6616                 if (param_pos == param) {
6617                         found = TRUE;
6618                         break;
6619                 }
6620         }
6621         if (!found)
6622                 return NULL;
6623         idx = i;
6624         idx <<= MONO_CUSTOM_ATTR_BITS;
6625         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6626         return mono_custom_attrs_from_index (image, idx);
6627 }
6628
6629 /*
6630  * mono_reflection_get_custom_attrs:
6631  * @obj: a reflection object handle
6632  *
6633  * Return an array with all the custom attributes defined of the
6634  * reflection handle @obj. The objects are fully build.
6635  */
6636 MonoArray*
6637 mono_reflection_get_custom_attrs (MonoObject *obj)
6638 {
6639         MonoClass *klass;
6640         MonoArray *result;
6641         MonoCustomAttrInfo *cinfo = NULL;
6642         
6643         MONO_ARCH_SAVE_REGS;
6644
6645         klass = obj->vtable->klass;
6646         if (klass == mono_defaults.monotype_class) {
6647                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6648                 klass = mono_class_from_mono_type (rtype->type);
6649                 cinfo = mono_custom_attrs_from_class (klass);
6650         } else if (strcmp ("Assembly", klass->name) == 0) {
6651                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6652                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6653         } else if (strcmp ("Module", klass->name) == 0) {
6654                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6655                 cinfo = mono_custom_attrs_from_module (module->image);
6656         } else if (strcmp ("MonoProperty", klass->name) == 0) {
6657                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6658                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6659         } else if (strcmp ("MonoEvent", klass->name) == 0) {
6660                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6661                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6662         } else if (strcmp ("MonoField", klass->name) == 0) {
6663                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6664                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6665         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6666                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6667                 cinfo = mono_custom_attrs_from_method (rmethod->method);
6668         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6669                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6670                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6671                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6672         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6673                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6674                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6675         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6676                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6677                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6678         } else { /* handle other types here... */
6679                 g_error ("get custom attrs not yet supported for %s", klass->name);
6680         }
6681
6682         if (cinfo) {
6683                 result = mono_custom_attrs_construct (cinfo);
6684                 if (!cinfo->cached)
6685                         mono_custom_attrs_free (cinfo);
6686         } else {
6687                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6688                 result = mono_array_new (mono_domain_get (), klass, 0);
6689         }
6690
6691         return result;
6692 }
6693
6694 static MonoMethodSignature*
6695 parameters_to_signature (MonoArray *parameters) {
6696         MonoMethodSignature *sig;
6697         int count, i;
6698
6699         count = parameters? mono_array_length (parameters): 0;
6700
6701         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6702         sig->param_count = count;
6703         sig->sentinelpos = -1; /* FIXME */
6704         for (i = 0; i < count; ++i) {
6705                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6706                 sig->params [i] = pt->type;
6707         }
6708         return sig;
6709 }
6710
6711 static MonoMethodSignature*
6712 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6713         MonoMethodSignature *sig;
6714
6715         sig = parameters_to_signature (ctor->parameters);
6716         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6717         sig->ret = &mono_defaults.void_class->byval_arg;
6718         return sig;
6719 }
6720
6721 static MonoMethodSignature*
6722 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6723         MonoMethodSignature *sig;
6724
6725         sig = parameters_to_signature (method->parameters);
6726         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6727         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6728         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6729         return sig;
6730 }
6731
6732 static MonoMethodSignature*
6733 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6734         MonoMethodSignature *sig;
6735
6736         sig = parameters_to_signature (method->parameters);
6737         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6738         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6739         sig->generic_param_count = 0;
6740         return sig;
6741 }
6742
6743 static void
6744 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6745 {
6746         MonoClass *klass = mono_object_class (prop);
6747         if (strcmp (klass->name, "PropertyBuilder") == 0) {
6748                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6749                 *name = mono_string_to_utf8 (pb->name);
6750                 *type = pb->type->type;
6751         } else {
6752                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6753                 *name = g_strdup (p->property->name);
6754                 if (p->property->get)
6755                         *type = p->property->get->signature->ret;
6756                 else
6757                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6758         }
6759 }
6760
6761 static void
6762 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6763 {
6764         MonoClass *klass = mono_object_class (field);
6765         if (strcmp (klass->name, "FieldBuilder") == 0) {
6766                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6767                 *name = mono_string_to_utf8 (fb->name);
6768                 *type = fb->type->type;
6769         } else {
6770                 MonoReflectionField *f = (MonoReflectionField *)field;
6771                 *name = g_strdup (f->field->name);
6772                 *type = f->field->type;
6773         }
6774 }
6775
6776 /*
6777  * Encode a value in a custom attribute stream of bytes.
6778  * The value to encode is either supplied as an object in argument val
6779  * (valuetypes are boxed), or as a pointer to the data in the
6780  * argument argval.
6781  * @type represents the type of the value
6782  * @buffer is the start of the buffer
6783  * @p the current position in the buffer
6784  * @buflen contains the size of the buffer and is used to return the new buffer size
6785  * if this needs to be realloced.
6786  * @retbuffer and @retp return the start and the position of the buffer
6787  */
6788 static void
6789 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6790 {
6791         MonoTypeEnum simple_type;
6792         
6793         if ((p-buffer) + 10 >= *buflen) {
6794                 char *newbuf;
6795                 *buflen *= 2;
6796                 newbuf = g_realloc (buffer, *buflen);
6797                 p = newbuf + (p-buffer);
6798                 buffer = newbuf;
6799         }
6800         if (!argval)
6801                 argval = ((char*)arg + sizeof (MonoObject));
6802         simple_type = type->type;
6803 handle_enum:
6804         switch (simple_type) {
6805         case MONO_TYPE_BOOLEAN:
6806         case MONO_TYPE_U1:
6807         case MONO_TYPE_I1:
6808                 *p++ = *argval;
6809                 break;
6810         case MONO_TYPE_CHAR:
6811         case MONO_TYPE_U2:
6812         case MONO_TYPE_I2:
6813                 swap_with_size (p, argval, 2, 1);
6814                 p += 2;
6815                 break;
6816         case MONO_TYPE_U4:
6817         case MONO_TYPE_I4:
6818         case MONO_TYPE_R4:
6819                 swap_with_size (p, argval, 4, 1);
6820                 p += 4;
6821                 break;
6822         case MONO_TYPE_U8:
6823         case MONO_TYPE_I8:
6824         case MONO_TYPE_R8:
6825                 swap_with_size (p, argval, 8, 1);
6826                 p += 8;
6827                 break;
6828         case MONO_TYPE_VALUETYPE:
6829                 if (type->data.klass->enumtype) {
6830                         simple_type = type->data.klass->enum_basetype->type;
6831                         goto handle_enum;
6832                 } else {
6833                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6834                 }
6835                 break;
6836         case MONO_TYPE_STRING: {
6837                 char *str;
6838                 guint32 slen;
6839                 if (!arg) {
6840                         *p++ = 0xFF;
6841                         break;
6842                 }
6843                 str = mono_string_to_utf8 ((MonoString*)arg);
6844                 slen = strlen (str);
6845                 if ((p-buffer) + 10 + slen >= *buflen) {
6846                         char *newbuf;
6847                         *buflen *= 2;
6848                         *buflen += slen;
6849                         newbuf = g_realloc (buffer, *buflen);
6850                         p = newbuf + (p-buffer);
6851                         buffer = newbuf;
6852                 }
6853                 mono_metadata_encode_value (slen, p, &p);
6854                 memcpy (p, str, slen);
6855                 p += slen;
6856                 g_free (str);
6857                 break;
6858         }
6859         case MONO_TYPE_CLASS: {
6860                 char *str;
6861                 guint32 slen;
6862                 MonoClass *k;
6863                 if (!arg) {
6864                         *p++ = 0xFF;
6865                         break;
6866                 }
6867                 k = mono_object_class (arg);
6868                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6869                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6870                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6871 handle_type:
6872                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6873                 slen = strlen (str);
6874                 if ((p-buffer) + 10 + slen >= *buflen) {
6875                         char *newbuf;
6876                         *buflen *= 2;
6877                         *buflen += slen;
6878                         newbuf = g_realloc (buffer, *buflen);
6879                         p = newbuf + (p-buffer);
6880                         buffer = newbuf;
6881                 }
6882                 mono_metadata_encode_value (slen, p, &p);
6883                 memcpy (p, str, slen);
6884                 p += slen;
6885                 g_free (str);
6886                 break;
6887         }
6888         case MONO_TYPE_SZARRAY: {
6889                 int len, i;
6890                 MonoClass *eclass, *arg_eclass;
6891
6892                 if (!arg) {
6893                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6894                         break;
6895                 }
6896                 len = mono_array_length ((MonoArray*)arg);
6897                 *p++ = len & 0xff;
6898                 *p++ = (len >> 8) & 0xff;
6899                 *p++ = (len >> 16) & 0xff;
6900                 *p++ = (len >> 24) & 0xff;
6901                 *retp = p;
6902                 *retbuffer = buffer;
6903                 eclass = type->data.klass;
6904                 arg_eclass = mono_object_class (arg)->element_class;
6905                 if (eclass->valuetype && arg_eclass->valuetype) {
6906                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6907                         int elsize = mono_class_array_element_size (eclass);
6908                         for (i = 0; i < len; ++i) {
6909                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6910                                 elptr += elsize;
6911                         }
6912                 } else {
6913                         for (i = 0; i < len; ++i) {
6914                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6915                         }
6916                 }
6917                 break;
6918         }
6919         /* it may be a boxed value or a Type */
6920         case MONO_TYPE_OBJECT: {
6921                 MonoClass *klass = mono_object_class (arg);
6922                 char *str;
6923                 guint32 slen;
6924                 
6925                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6926                         *p++ = 0x50;
6927                         goto handle_type;
6928                 } else if (klass->enumtype) {
6929                         *p++ = 0x55;
6930                 } else if (klass == mono_defaults.string_class) {
6931                         simple_type = MONO_TYPE_STRING;
6932                         *p++ = 0x0E;
6933                         goto handle_enum;
6934                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6935                         *p++ = simple_type = klass->byval_arg.type;
6936                         goto handle_enum;
6937                 } else {
6938                         g_error ("unhandled type in custom attr");
6939                 }
6940                 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
6941                 slen = strlen (str);
6942                 if ((p-buffer) + 10 + slen >= *buflen) {
6943                         char *newbuf;
6944                         *buflen *= 2;
6945                         *buflen += slen;
6946                         newbuf = g_realloc (buffer, *buflen);
6947                         p = newbuf + (p-buffer);
6948                         buffer = newbuf;
6949                 }
6950                 mono_metadata_encode_value (slen, p, &p);
6951                 memcpy (p, str, slen);
6952                 p += slen;
6953                 g_free (str);
6954                 simple_type = klass->enum_basetype->type;
6955                 goto handle_enum;
6956         }
6957         default:
6958                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6959         }
6960         *retp = p;
6961         *retbuffer = buffer;
6962 }
6963
6964 /*
6965  * mono_reflection_get_custom_attrs_blob:
6966  * @ctor: custom attribute constructor
6967  * @ctorArgs: arguments o the constructor
6968  * @properties:
6969  * @propValues:
6970  * @fields:
6971  * @fieldValues:
6972  * 
6973  * Creates the blob of data that needs to be saved in the metadata and that represents
6974  * the custom attributed described by @ctor, @ctorArgs etc.
6975  * Returns: a Byte array representing the blob of data.
6976  */
6977 MonoArray*
6978 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
6979 {
6980         MonoArray *result;
6981         MonoMethodSignature *sig;
6982         MonoObject *arg;
6983         char *buffer, *p;
6984         guint32 buflen, i;
6985
6986         MONO_ARCH_SAVE_REGS;
6987
6988         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6989                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6990         } else {
6991                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6992         }
6993         g_assert (mono_array_length (ctorArgs) == sig->param_count);
6994         buflen = 256;
6995         p = buffer = g_malloc (buflen);
6996         /* write the prolog */
6997         *p++ = 1;
6998         *p++ = 0;
6999         for (i = 0; i < sig->param_count; ++i) {
7000                 arg = mono_array_get (ctorArgs, MonoObject*, i);
7001                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
7002         }
7003         i = 0;
7004         if (properties)
7005                 i += mono_array_length (properties);
7006         if (fields)
7007                 i += mono_array_length (fields);
7008         *p++ = i & 0xff;
7009         *p++ = (i >> 8) & 0xff;
7010         if (properties) {
7011                 MonoObject *prop;
7012                 for (i = 0; i < mono_array_length (properties); ++i) {
7013                         MonoType *ptype;
7014                         char *pname;
7015                         int len;
7016                         
7017                         prop = mono_array_get (properties, gpointer, i);
7018                         get_prop_name_and_type (prop, &pname, &ptype);
7019                         *p++ = 0x54; /* PROPERTY signature */
7020
7021                         /* Preallocate a large enough buffer */
7022                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7023                                 char *str = type_get_qualified_name (ptype, NULL);
7024                                 len = strlen (str);
7025                                 g_free (str);
7026                         }
7027                         else
7028                                 len = 0;
7029                         len += strlen (pname);
7030
7031                         if ((p-buffer) + 20 + len >= buflen) {
7032                                 char *newbuf;
7033                                 buflen *= 2;
7034                                 buflen += len;
7035                                 newbuf = g_realloc (buffer, buflen);
7036                                 p = newbuf + (p-buffer);
7037                                 buffer = newbuf;
7038                         }
7039
7040                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
7041                                 char *str = type_get_qualified_name (ptype, NULL);
7042                                 int slen = strlen (str);
7043
7044                                 *p++ = 0x55;
7045                                 /*
7046                                  * This seems to be optional...
7047                                  * *p++ = 0x80;
7048                                  */
7049                                 mono_metadata_encode_value (slen, p, &p);
7050                                 memcpy (p, str, slen);
7051                                 p += slen;
7052                                 g_free (str);
7053                         } else {
7054                                 mono_metadata_encode_value (ptype->type, p, &p);
7055                                 if (ptype->type == MONO_TYPE_SZARRAY)
7056                                         mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
7057                         }
7058                         len = strlen (pname);
7059                         mono_metadata_encode_value (len, p, &p);
7060                         memcpy (p, pname, len);
7061                         p += len;
7062                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
7063                         g_free (pname);
7064                 }
7065         }
7066
7067         if (fields) {
7068                 MonoObject *field;
7069                 for (i = 0; i < mono_array_length (fields); ++i) {
7070                         MonoType *ftype;
7071                         char *fname;
7072                         int len;
7073                         
7074                         field = mono_array_get (fields, gpointer, i);
7075                         get_field_name_and_type (field, &fname, &ftype);
7076                         *p++ = 0x53; /* FIELD signature */
7077                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
7078                                 char *str = type_get_qualified_name (ftype, NULL);
7079                                 int slen = strlen (str);
7080                                 if ((p-buffer) + 10 + slen >= buflen) {
7081                                         char *newbuf;
7082                                         buflen *= 2;
7083                                         buflen += slen;
7084                                         newbuf = g_realloc (buffer, buflen);
7085                                         p = newbuf + (p-buffer);
7086                                         buffer = newbuf;
7087                                 }
7088                                 *p++ = 0x55;
7089                                 /*
7090                                  * This seems to be optional...
7091                                  * *p++ = 0x80;
7092                                  */
7093                                 mono_metadata_encode_value (slen, p, &p);
7094                                 memcpy (p, str, slen);
7095                                 p += slen;
7096                                 g_free (str);
7097                         } else {
7098                                 mono_metadata_encode_value (ftype->type, p, &p);
7099                                 if (ftype->type == MONO_TYPE_SZARRAY)
7100                                         mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
7101                         }
7102                         len = strlen (fname);
7103                         mono_metadata_encode_value (len, p, &p);
7104                         memcpy (p, fname, len);
7105                         p += len;
7106                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
7107                         g_free (fname);
7108                 }
7109         }
7110
7111         g_assert (p - buffer <= buflen);
7112         buflen = p - buffer;
7113         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7114         p = mono_array_addr (result, char, 0);
7115         memcpy (p, buffer, buflen);
7116         g_free (buffer);
7117         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
7118                 g_free (sig);
7119         return result;
7120 }
7121
7122 /*
7123  * mono_reflection_setup_internal_class:
7124  * @tb: a TypeBuilder object
7125  *
7126  * Creates a MonoClass that represents the TypeBuilder.
7127  * This is a trick that lets us simplify a lot of reflection code
7128  * (and will allow us to support Build and Run assemblies easier).
7129  */
7130 void
7131 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
7132 {
7133         MonoClass *klass, *parent;
7134
7135         MONO_ARCH_SAVE_REGS;
7136
7137         if (tb->parent) {
7138                 /* check so we can compile corlib correctly */
7139                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
7140                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
7141                         parent = tb->parent->type->data.klass;
7142                 } else {
7143                         parent = my_mono_class_from_mono_type (tb->parent->type);
7144                 }
7145         } else {
7146                 parent = NULL;
7147         }
7148         
7149         /* the type has already being created: it means we just have to change the parent */
7150         if (tb->type.type) {
7151                 klass = mono_class_from_mono_type (tb->type.type);
7152                 klass->parent = NULL;
7153                 /* fool mono_class_setup_parent */
7154                 g_free (klass->supertypes);
7155                 klass->supertypes = NULL;
7156                 mono_class_setup_parent (klass, parent);
7157                 mono_class_setup_mono_type (klass);
7158                 return;
7159         }
7160         
7161         klass = g_new0 (MonoClass, 1);
7162
7163         klass->image = &tb->module->dynamic_image->image;
7164
7165         klass->inited = 1; /* we lie to the runtime */
7166         klass->name = mono_string_to_utf8 (tb->name);
7167         klass->name_space = mono_string_to_utf8 (tb->nspace);
7168         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
7169         klass->flags = tb->attrs;
7170
7171         klass->element_class = klass;
7172         klass->reflection_info = tb; /* need to pin. */
7173
7174         /* Put into cache so mono_class_get () will find it */
7175         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
7176
7177         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
7178                 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
7179
7180         if (parent != NULL) {
7181                 mono_class_setup_parent (klass, parent);
7182         } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
7183                 const char *old_n = klass->name;
7184                 /* trick to get relative numbering right when compiling corlib */
7185                 klass->name = "BuildingObject";
7186                 mono_class_setup_parent (klass, mono_defaults.object_class);
7187                 klass->name = old_n;
7188         }
7189
7190         if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
7191                         (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
7192                         (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
7193                 klass->instance_size = sizeof (MonoObject);
7194                 klass->size_inited = 1;
7195                 mono_class_setup_vtable (klass, NULL, 0);
7196         }
7197
7198         mono_class_setup_mono_type (klass);
7199
7200         mono_class_setup_supertypes (klass);
7201
7202         /*
7203          * FIXME: handle interfaces.
7204          */
7205
7206         tb->type.type = &klass->byval_arg;
7207
7208         if (tb->nesting_type) {
7209                 g_assert (tb->nesting_type->type);
7210                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
7211         }
7212
7213         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
7214 }
7215
7216 /*
7217  * mono_reflection_setup_generic_class:
7218  * @tb: a TypeBuilder object
7219  *
7220  * Setup the generic class after all generic parameters have been added.
7221  */
7222 void
7223 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
7224 {
7225         MonoClass *klass;
7226         int count, i;
7227
7228         MONO_ARCH_SAVE_REGS;
7229
7230         klass = my_mono_class_from_mono_type (tb->type.type);
7231
7232         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
7233
7234         if (klass->gen_params || (count == 0))
7235                 return;
7236
7237         klass->num_gen_params = count;
7238         klass->gen_params = g_new0 (MonoGenericParam, count);
7239
7240         for (i = 0; i < count; i++) {
7241                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
7242                 klass->gen_params [i] = *gparam->type.type->data.generic_param;
7243         }
7244 }
7245
7246 /*
7247  * mono_reflection_create_internal_class:
7248  * @tb: a TypeBuilder object
7249  *
7250  * Actually create the MonoClass that is associated with the TypeBuilder.
7251  */
7252 void
7253 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
7254 {
7255         MonoClass *klass;
7256
7257         MONO_ARCH_SAVE_REGS;
7258
7259         klass = my_mono_class_from_mono_type (tb->type.type);
7260
7261         if (klass->enumtype && klass->enum_basetype == NULL) {
7262                 MonoReflectionFieldBuilder *fb;
7263                 MonoClass *ec;
7264
7265                 g_assert (tb->fields != NULL);
7266                 g_assert (mono_array_length (tb->fields) >= 1);
7267
7268                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7269
7270                 klass->enum_basetype = fb->type->type;
7271                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7272                 if (!klass->element_class)
7273                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7274
7275                 /*
7276                  * get the element_class from the current corlib.
7277                  */
7278                 ec = default_class_from_mono_type (klass->enum_basetype);
7279                 klass->instance_size = ec->instance_size;
7280                 klass->size_inited = 1;
7281                 /* 
7282                  * this is almost safe to do with enums and it's needed to be able
7283                  * to create objects of the enum type (for use in SetConstant).
7284                  */
7285                 /* FIXME: Does this mean enums can't have method overrides ? */
7286                 mono_class_setup_vtable (klass, NULL, 0);
7287         }
7288 }
7289
7290 static MonoMarshalSpec*
7291 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7292                                                                 MonoReflectionMarshal *minfo)
7293 {
7294         MonoMarshalSpec *res;
7295
7296         res = g_new0 (MonoMarshalSpec, 1);
7297         res->native = minfo->type;
7298
7299         switch (minfo->type) {
7300         case MONO_NATIVE_LPARRAY:
7301                 res->data.array_data.elem_type = minfo->eltype;
7302                 res->data.array_data.param_num = 0; /* Not yet */
7303                 res->data.array_data.num_elem = minfo->count;
7304                 break;
7305
7306         case MONO_NATIVE_BYVALTSTR:
7307         case MONO_NATIVE_BYVALARRAY:
7308                 res->data.array_data.num_elem = minfo->count;
7309                 break;
7310
7311         case MONO_NATIVE_CUSTOM:
7312                 if (minfo->marshaltyperef)
7313                         res->data.custom_data.custom_name =
7314                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7315                 if (minfo->mcookie)
7316                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7317                 break;
7318
7319         default:
7320                 break;
7321         }
7322
7323         return res;
7324 }
7325
7326 static MonoMethod*
7327 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7328                                          ReflectionMethodBuilder *rmb,
7329                                          MonoMethodSignature *sig)
7330 {
7331         MonoMethod *m;
7332         MonoMethodNormal *pm;
7333         MonoMarshalSpec **specs;
7334         MonoReflectionMethodAux *method_aux;
7335         int i;
7336
7337         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7338                         (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7339                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7340         else if (rmb->refs)
7341                 m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7342         else
7343                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7344
7345         pm = (MonoMethodNormal*)m;
7346
7347         m->slot = -1;
7348         m->flags = rmb->attrs;
7349         m->iflags = rmb->iattrs;
7350         m->name = mono_string_to_utf8 (rmb->name);
7351         m->klass = klass;
7352         m->signature = sig;
7353         if (rmb->table_idx)
7354                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7355
7356         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7357                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7358                         m->string_ctor = 1;
7359
7360                 m->signature->pinvoke = 1;
7361         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7362                 m->signature->pinvoke = 1;
7363
7364                 method_aux = g_new0 (MonoReflectionMethodAux, 1);
7365
7366                 method_aux->dllentry = g_strdup (mono_string_to_utf8 (rmb->dllentry));
7367                 method_aux->dll = g_strdup (mono_string_to_utf8 (rmb->dll));
7368                 
7369                 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 1) | rmb->lasterr;
7370
7371                 if (klass->image->dynamic)
7372                         mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7373
7374                 return m;
7375         } else if (!m->klass->dummy && 
7376                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7377                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7378                 MonoMethodHeader *header;
7379                 guint32 code_size;
7380                 gint32 max_stack, i;
7381                 gint32 num_locals = 0;
7382                 gint32 num_clauses = 0;
7383                 guint8 *code;
7384
7385                 if (rmb->ilgen) {
7386                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7387                         code_size = rmb->ilgen->code_len;
7388                         max_stack = rmb->ilgen->max_stack;
7389                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7390                         if (rmb->ilgen->ex_handlers)
7391                                 num_clauses = method_count_clauses (rmb->ilgen);
7392                 } else {
7393                         if (rmb->code) {
7394                                 code = mono_array_addr (rmb->code, guint8, 0);
7395                                 code_size = mono_array_length (rmb->code);
7396                                 /* we probably need to run a verifier on the code... */
7397                                 max_stack = 8; 
7398                         }
7399                         else {
7400                                 code = NULL;
7401                                 code_size = 0;
7402                                 max_stack = 8;
7403                         }
7404                 }
7405
7406                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
7407                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7408                 header->code_size = code_size;
7409                 header->code = g_malloc (code_size);
7410                 memcpy ((char*)header->code, code, code_size);
7411                 header->max_stack = max_stack;
7412                 header->init_locals = rmb->init_locals;
7413                 header->num_locals = num_locals;
7414
7415                 for (i = 0; i < num_locals; ++i) {
7416                         MonoReflectionLocalBuilder *lb = 
7417                                 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
7418
7419                         header->locals [i] = g_new0 (MonoType, 1);
7420                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7421                 }
7422
7423                 header->num_clauses = num_clauses;
7424                 if (num_clauses) {
7425                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7426                                  rmb->ilgen, num_clauses);
7427                 }
7428
7429                 pm->header = header;
7430         }
7431
7432         if (rmb->generic_params) {
7433                 int count = mono_array_length (rmb->generic_params);
7434                 pm->gen_params = g_new0 (MonoGenericParam, count);
7435                 for (i = 0; i < count; i++) {
7436                         MonoReflectionGenericParam *gp =
7437                                 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
7438
7439                         pm->gen_params [i] = *gp->type.type->data.generic_param;
7440                 }
7441         }
7442
7443         if (rmb->refs) {
7444                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7445                 int i;
7446
7447                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7448
7449                 for (i = 0; i < rmb->nrefs; ++i)
7450                         mw->data = g_list_append (mw->data, rmb->refs [i]);
7451         }
7452
7453         method_aux = NULL;
7454
7455         /* Parameter names */
7456         if (rmb->pinfo) {
7457                 if (!method_aux)
7458                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7459                 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7460                 for (i = 0; i <= m->signature->param_count; ++i) {
7461                         MonoReflectionParamBuilder *pb;
7462                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7463                                 if (pb->name)
7464                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7465                                 if (pb->cattrs) {
7466                                         if (!method_aux->param_cattr)
7467                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7468                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7469                                 }
7470                         }
7471                 }
7472         }
7473
7474         /* Parameter marshalling */
7475         specs = NULL;
7476         if (rmb->pinfo)         
7477                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7478                         MonoReflectionParamBuilder *pb;
7479                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7480                                 if (pb->marshal_info) {
7481                                         if (specs == NULL)
7482                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7483                                         specs [pb->position] = 
7484                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7485                                 }
7486                         }
7487                 }
7488         if (specs != NULL) {
7489                 if (!method_aux)
7490                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7491                 method_aux->param_marshall = specs;
7492         }
7493
7494         if (klass->image->dynamic && method_aux)
7495                 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7496
7497         return m;
7498 }       
7499
7500 static MonoMethod*
7501 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7502 {
7503         ReflectionMethodBuilder rmb;
7504         MonoMethodSignature *sig;
7505
7506         sig = ctor_builder_to_signature (mb);
7507
7508         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7509
7510         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7511         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7512
7513         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7514                 /* ilgen is no longer needed */
7515                 mb->ilgen = NULL;
7516         }
7517
7518         return mb->mhandle;
7519 }
7520
7521 static MonoMethod*
7522 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7523 {
7524         ReflectionMethodBuilder rmb;
7525         MonoMethodSignature *sig;
7526
7527         sig = method_builder_to_signature (mb);
7528
7529         reflection_methodbuilder_from_method_builder (&rmb, mb);
7530
7531         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7532         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7533
7534         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7535                 /* ilgen is no longer needed */
7536                 mb->ilgen = NULL;
7537         }
7538         return mb->mhandle;
7539 }
7540
7541 static MonoClassField*
7542 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7543 {
7544         MonoClassField *field;
7545         const char *p, *p2;
7546         guint32 len, idx;
7547
7548         if (fb->handle)
7549                 return fb->handle;
7550
7551         field = g_new0 (MonoClassField, 1);
7552
7553         field->name = mono_string_to_utf8 (fb->name);
7554         if (fb->attrs) {
7555                 /* FIXME: handle type modifiers */
7556                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7557                 field->type->attrs = fb->attrs;
7558         } else {
7559                 field->type = fb->type->type;
7560         }
7561         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7562                 field->data = mono_array_addr (fb->rva_data, char, 0);
7563         if (fb->offset != -1)
7564                 field->offset = fb->offset;
7565         field->parent = klass;
7566         fb->handle = field;
7567         mono_save_custom_attrs (klass->image, field, fb->cattrs);
7568
7569         if (fb->def_value) {
7570                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7571                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7572                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7573                 /* Copy the data from the blob since it might get realloc-ed */
7574                 p = assembly->blob.data + idx;
7575                 len = mono_metadata_decode_blob_size (p, &p2);
7576                 len += p2 - p;
7577                 field->data = g_malloc (len);
7578                 memcpy ((gpointer)field->data, p, len);
7579         }
7580
7581         return field;
7582 }
7583
7584 static MonoType*
7585 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7586 {
7587         MonoClass *klass;
7588         MonoReflectionTypeBuilder *tb = NULL;
7589         MonoGenericInst *ginst, *cached;
7590         MonoDomain *domain;
7591         MonoType *geninst;
7592         int icount, i;
7593
7594         klass = mono_class_from_mono_type (type->type);
7595         if (!klass->gen_params && !klass->generic_inst &&
7596                         !(klass->nested_in && klass->nested_in->gen_params))
7597                 return NULL;
7598
7599         mono_loader_lock ();
7600
7601         domain = mono_object_domain (type);
7602
7603         ginst = g_new0 (MonoGenericInst, 1);
7604
7605         if (!klass->generic_inst) {
7606                 ginst->type_argc = type_argc;
7607                 ginst->type_argv = types;
7608
7609                 for (i = 0; i < ginst->type_argc; ++i) {
7610                         if (!ginst->is_open)
7611                                 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7612                 }
7613
7614                 ginst->generic_type = &klass->byval_arg;
7615         } else {
7616                 MonoGenericInst *kginst = klass->generic_inst;
7617
7618                 ginst->type_argc = kginst->type_argc;
7619                 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7620
7621                 for (i = 0; i < ginst->type_argc; i++) {
7622                         MonoType *t = kginst->type_argv [i];
7623
7624                         if (t->type == MONO_TYPE_VAR)
7625                                 t = types [t->data.generic_param->num];
7626
7627                         if (!ginst->is_open)
7628                                 ginst->is_open = mono_class_is_open_constructed_type (t);
7629
7630                         ginst->type_argv [i] = t;
7631                 }
7632
7633                 ginst->generic_type = kginst->generic_type;
7634         }
7635
7636         geninst = g_new0 (MonoType, 1);
7637         geninst->type = MONO_TYPE_GENERICINST;
7638
7639         cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7640         if (cached) {
7641                 g_free (ginst);
7642                 mono_loader_unlock ();
7643                 geninst->data.generic_inst = cached;
7644                 return geninst;
7645         }
7646
7647         geninst->data.generic_inst = ginst;
7648
7649         ginst->context = g_new0 (MonoGenericContext, 1);
7650         ginst->context->ginst = ginst;
7651
7652         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7653                 tb = (MonoReflectionTypeBuilder *) type;
7654
7655                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7656                 ginst->is_dynamic = TRUE;
7657         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7658                 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7659                 MonoReflectionType *rgt = rgi->generic_type;
7660
7661                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7662                 tb = (MonoReflectionTypeBuilder *) rgt;
7663
7664                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7665                 ginst->is_dynamic = TRUE;
7666         } else {
7667                 icount = klass->interface_count;
7668         }
7669
7670         ginst->ifaces = g_new0 (MonoType *, icount);
7671         ginst->count_ifaces = icount;
7672
7673         for (i = 0; i < icount; i++) {
7674                 MonoReflectionType *itype;
7675
7676                 if (tb)
7677                         itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7678                 else
7679                         itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7680                 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7681                 if (!ginst->ifaces [i])
7682                         ginst->ifaces [i] = itype->type;
7683         }
7684
7685         mono_class_create_generic (ginst);
7686
7687         g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7688
7689         mono_loader_unlock ();
7690
7691         return geninst;
7692 }
7693
7694 MonoType*
7695 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7696 {
7697         MonoClass *klass, *pklass = NULL;
7698         MonoReflectionType *parent = NULL;
7699         MonoType *geninst;
7700         MonoReflectionTypeBuilder *tb = NULL;
7701         MonoGenericInst *ginst;
7702         MonoDomain *domain;
7703
7704         domain = mono_object_domain (type);
7705         klass = mono_class_from_mono_type (type->type);
7706
7707         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7708                 tb = (MonoReflectionTypeBuilder *) type;
7709
7710                 if (tb->parent) {
7711                         parent = tb->parent;
7712                         pklass = mono_class_from_mono_type (parent->type);
7713                 }
7714         } else {
7715                 pklass = klass->parent;
7716                 if (pklass)
7717                         parent = mono_type_get_object (domain, &pklass->byval_arg);
7718         }
7719
7720         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7721         if (!geninst)
7722                 return NULL;
7723
7724         ginst = geninst->data.generic_inst;
7725
7726         if (pklass && pklass->generic_inst)
7727                 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7728
7729         return geninst;
7730 }
7731
7732 MonoReflectionMethod*
7733 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7734 {
7735         MonoMethod *method, *inflated;
7736         MonoReflectionMethodBuilder *mb = NULL;
7737         MonoGenericMethod *gmethod;
7738         MonoGenericContext *context;
7739         int count, i;
7740
7741         MONO_ARCH_SAVE_REGS;
7742         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7743                 MonoReflectionTypeBuilder *tb;
7744                 MonoClass *klass;
7745
7746                 mb = (MonoReflectionMethodBuilder *) rmethod;
7747                 tb = (MonoReflectionTypeBuilder *) mb->type;
7748                 klass = mono_class_from_mono_type (tb->type.type);
7749
7750                 method = methodbuilder_to_mono_method (klass, mb);
7751         } else {
7752                 method = rmethod->method;
7753         }
7754
7755         count = method->signature->generic_param_count;
7756         if (count != mono_array_length (types))
7757                 return NULL;
7758
7759         gmethod = g_new0 (MonoGenericMethod, 1);
7760         gmethod->mtype_argc = count;
7761         gmethod->mtype_argv = g_new0 (MonoType *, count);
7762         for (i = 0; i < count; i++) {
7763                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7764                 gmethod->mtype_argv [i] = garg->type;
7765         }
7766
7767         gmethod->reflection_info = rmethod;
7768
7769         context = g_new0 (MonoGenericContext, 1);
7770         context->ginst = method->klass->generic_inst;
7771         context->gmethod = gmethod;
7772
7773         inflated = mono_class_inflate_generic_method (method, context, NULL);
7774
7775         return mono_method_get_object (
7776                 mono_object_domain (rmethod), inflated, NULL);
7777 }
7778
7779 static MonoMethod *
7780 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7781 {
7782         MonoGenericMethod *gmethod;
7783         MonoGenericInst *ginst;
7784         MonoGenericContext *context;
7785         int i;
7786
7787         ginst = type->type.type->data.generic_inst;
7788
7789         gmethod = g_new0 (MonoGenericMethod, 1);
7790         gmethod->reflection_info = obj;
7791
7792         gmethod->mtype_argc = method->signature->generic_param_count;
7793         gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7794
7795         for (i = 0; i < gmethod->mtype_argc; i++) {
7796                 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7797                 MonoGenericParam *gparam = &mn->gen_params [i];
7798
7799                 g_assert (gparam->pklass);
7800                 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7801         }
7802
7803         context = g_new0 (MonoGenericContext, 1);
7804         context->ginst = ginst;
7805         context->gmethod = gmethod;
7806
7807         return mono_class_inflate_generic_method (method, context, ginst->klass);
7808 }
7809
7810 static MonoMethod *
7811 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7812 {
7813         MonoMethod *method;
7814         MonoClass *klass;
7815
7816         klass = mono_class_from_mono_type (type->type.type);
7817
7818         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7819                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7820         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7821                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7822         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7823                 method = ((MonoReflectionMethod *) obj)->method;
7824         else {
7825                 method = NULL; /* prevent compiler warning */
7826                 g_assert_not_reached ();
7827         }
7828
7829         return inflate_mono_method (type, method, obj);
7830 }
7831
7832 void
7833 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type, MonoArray *methods, 
7834         MonoArray *ctors, MonoArray *fields, MonoArray *properties, MonoArray *events)
7835 {
7836         MonoGenericInst *ginst;
7837         MonoDynamicGenericInst *dginst;
7838         MonoClass *klass, *gklass, *pklass;
7839         int i;
7840
7841         MONO_ARCH_SAVE_REGS;
7842
7843         klass = mono_class_from_mono_type (type->type.type);
7844         ginst = type->type.type->data.generic_inst;
7845
7846         if (ginst->initialized)
7847                 return;
7848
7849         dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7850
7851         gklass = mono_class_from_mono_type (ginst->generic_type);
7852         mono_class_init (gklass);
7853
7854         if (ginst->parent)
7855                 pklass = mono_class_from_mono_type (ginst->parent);
7856         else
7857                 pklass = gklass->parent;
7858
7859         mono_class_setup_parent (klass, pklass);
7860
7861         dginst->count_methods = methods ? mono_array_length (methods) : 0;
7862         dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7863         dginst->count_fields = fields ? mono_array_length (fields) : 0;
7864         dginst->count_properties = properties ? mono_array_length (properties) : 0;
7865         dginst->count_events = events ? mono_array_length (events) : 0;
7866
7867         dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7868         dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7869         dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7870         dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7871         dginst->events = g_new0 (MonoEvent, dginst->count_events);
7872
7873         for (i = 0; i < dginst->count_methods; i++) {
7874                 MonoObject *obj = mono_array_get (methods, gpointer, i);
7875
7876                 dginst->methods [i] = inflate_method (type, obj);
7877         }
7878
7879         for (i = 0; i < dginst->count_ctors; i++) {
7880                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7881
7882                 dginst->ctors [i] = inflate_method (type, obj);
7883         }
7884
7885         for (i = 0; i < dginst->count_fields; i++) {
7886                 MonoObject *obj = mono_array_get (fields, gpointer, i);
7887                 MonoClassField *field;
7888                 MonoInflatedField *ifield;
7889
7890                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7891                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7892                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7893                         field = ((MonoReflectionField *) obj)->field;
7894                 else {
7895                         field = NULL; /* prevent compiler warning */
7896                         g_assert_not_reached ();
7897                 }
7898
7899                 ifield = g_new0 (MonoInflatedField, 1);
7900                 ifield->generic_type = field->type;
7901                 ifield->reflection_info = obj;
7902
7903                 dginst->fields [i] = *field;
7904                 dginst->fields [i].generic_info = ifield;
7905                 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7906         }
7907
7908         for (i = 0; i < dginst->count_properties; i++) {
7909                 MonoObject *obj = mono_array_get (properties, gpointer, i);
7910                 MonoProperty *property = &dginst->properties [i];
7911
7912                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7913                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7914
7915                         property->parent = klass;
7916                         property->attrs = pb->attrs;
7917                         property->name = mono_string_to_utf8 (pb->name);
7918                         if (pb->get_method)
7919                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7920                         if (pb->set_method)
7921                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7922                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7923                         *property = *((MonoReflectionProperty *) obj)->property;
7924
7925                         if (property->get)
7926                                 property->get = inflate_mono_method (type, property->get, NULL);
7927                         if (property->set)
7928                                 property->set = inflate_mono_method (type, property->set, NULL);
7929                 } else
7930                         g_assert_not_reached ();
7931         }
7932
7933         for (i = 0; i < dginst->count_events; i++) {
7934                 MonoObject *obj = mono_array_get (events, gpointer, i);
7935                 MonoEvent *event = &dginst->events [i];
7936
7937                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7938                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7939
7940                         event->parent = klass;
7941                         event->attrs = eb->attrs;
7942                         event->name = mono_string_to_utf8 (eb->name);
7943                         if (eb->add_method)
7944                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7945                         if (eb->remove_method)
7946                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7947                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7948                         *event = *((MonoReflectionEvent *) obj)->event;
7949
7950                         if (event->add)
7951                                 event->add = inflate_mono_method (type, event->add, NULL);
7952                         if (event->remove)
7953                                 event->remove = inflate_mono_method (type, event->remove, NULL);
7954                 } else
7955                         g_assert_not_reached ();
7956         }
7957
7958         ginst->initialized = TRUE;
7959 }
7960
7961 static void
7962 ensure_runtime_vtable (MonoClass *klass)
7963 {
7964         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7965         int i, num, j, onum;
7966         MonoMethod **overrides;
7967
7968         if (!tb || klass->wastypebuilder)
7969                 return;
7970         if (klass->parent)
7971                 ensure_runtime_vtable (klass->parent);
7972
7973         num = tb->ctors? mono_array_length (tb->ctors): 0;
7974         num += tb->num_methods;
7975         klass->method.count = num;
7976         klass->methods = g_new (MonoMethod*, num);
7977         num = tb->ctors? mono_array_length (tb->ctors): 0;
7978         for (i = 0; i < num; ++i)
7979                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7980         num = tb->num_methods;
7981         j = i;
7982         for (i = 0; i < num; ++i)
7983                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7984
7985         klass->wastypebuilder = TRUE;
7986         if (tb->interfaces) {
7987                 klass->interface_count = mono_array_length (tb->interfaces);
7988                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7989                 for (i = 0; i < klass->interface_count; ++i) {
7990                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7991                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7992                 }
7993         }
7994
7995         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7996                 for (i = 0; i < klass->method.count; ++i)
7997                         klass->methods [i]->slot = i;
7998
7999         /* Overrides */
8000         onum = 0;
8001         if (tb->methods) {
8002                 for (i = 0; i < tb->num_methods; ++i) {
8003                         MonoReflectionMethodBuilder *mb = 
8004                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8005                         if (mb->override_method)
8006                                 onum ++;
8007                 }
8008         }
8009
8010         overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
8011
8012         if (tb->methods) {
8013                 onum = 0;
8014                 for (i = 0; i < tb->num_methods; ++i) {
8015                         MonoReflectionMethodBuilder *mb = 
8016                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
8017                         if (mb->override_method) {
8018                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
8019                                 overrides [onum * 2] = 
8020                                         mb->override_method->method;
8021                                 overrides [onum * 2 + 1] =
8022                                         mb->mhandle;
8023
8024                                 g_assert (mb->mhandle);
8025
8026                                 onum ++;
8027                         }
8028                 }
8029         }
8030
8031         mono_class_setup_vtable (klass, overrides, onum);
8032 }
8033
8034 static void
8035 typebuilder_setup_fields (MonoClass *klass)
8036 {
8037         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8038         MonoReflectionFieldBuilder *fb;
8039         MonoClassField *field;
8040         const char *p, *p2;
8041         int i;
8042         guint32 len, idx;
8043
8044         klass->field.count = tb->num_fields;
8045         klass->field.first = 0;
8046         klass->field.last = klass->field.count;
8047
8048         if (!klass->field.count)
8049                 return;
8050         
8051         klass->fields = g_new0 (MonoClassField, klass->field.count);
8052
8053         for (i = 0; i < klass->field.count; ++i) {
8054                 fb = mono_array_get (tb->fields, gpointer, i);
8055                 field = &klass->fields [i];
8056                 field->name = mono_string_to_utf8 (fb->name);
8057                 if (fb->attrs) {
8058                         /* FIXME: handle type modifiers */
8059                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
8060                         field->type->attrs = fb->attrs;
8061                 } else {
8062                         field->type = fb->type->type;
8063                 }
8064                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
8065                         field->data = mono_array_addr (fb->rva_data, char, 0);
8066                 if (fb->offset != -1)
8067                         field->offset = fb->offset;
8068                 field->parent = klass;
8069                 fb->handle = field;
8070                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
8071
8072                 if (fb->def_value) {
8073                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
8074                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
8075                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
8076                         /* Copy the data from the blob since it might get realloc-ed */
8077                         p = assembly->blob.data + idx;
8078                         len = mono_metadata_decode_blob_size (p, &p2);
8079                         len += p2 - p;
8080                         field->data = g_malloc (len);
8081                         memcpy ((gpointer)field->data, p, len);
8082                 }
8083         }
8084         mono_class_layout_fields (klass);
8085 }
8086
8087 static void
8088 typebuilder_setup_properties (MonoClass *klass)
8089 {
8090         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8091         MonoReflectionPropertyBuilder *pb;
8092         int i;
8093
8094         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
8095         klass->property.first = 0;
8096         klass->property.last = klass->property.count;
8097
8098         klass->properties = g_new0 (MonoProperty, klass->property.count);
8099         for (i = 0; i < klass->property.count; ++i) {
8100                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
8101                 klass->properties [i].parent = klass;
8102                 klass->properties [i].attrs = pb->attrs;
8103                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
8104                 if (pb->get_method)
8105                         klass->properties [i].get = pb->get_method->mhandle;
8106                 if (pb->set_method)
8107                         klass->properties [i].set = pb->set_method->mhandle;
8108         }
8109 }
8110
8111 MonoReflectionEvent *
8112 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
8113 {
8114         MonoEvent *event = g_new0 (MonoEvent, 1);
8115         MonoClass *klass;
8116         int j;
8117
8118         klass = my_mono_class_from_mono_type (tb->type.type);
8119
8120         event->parent = klass;
8121         event->attrs = eb->attrs;
8122         event->name = mono_string_to_utf8 (eb->name);
8123         if (eb->add_method)
8124                 event->add = eb->add_method->mhandle;
8125         if (eb->remove_method)
8126                 event->remove = eb->remove_method->mhandle;
8127         if (eb->raise_method)
8128                 event->raise = eb->raise_method->mhandle;
8129
8130         if (eb->other_methods) {
8131                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8132                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8133                         MonoReflectionMethodBuilder *mb = 
8134                                 mono_array_get (eb->other_methods,
8135                                                 MonoReflectionMethodBuilder*, j);
8136                         event->other [j] = mb->mhandle;
8137                 }
8138         }
8139
8140         return mono_event_get_object (mono_object_domain (tb), klass, event);
8141 }
8142
8143 static void
8144 typebuilder_setup_events (MonoClass *klass)
8145 {
8146         MonoReflectionTypeBuilder *tb = klass->reflection_info;
8147         MonoReflectionEventBuilder *eb;
8148         int i, j;
8149
8150         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
8151         klass->event.first = 0;
8152         klass->event.last = klass->event.count;
8153
8154         klass->events = g_new0 (MonoEvent, klass->event.count);
8155         for (i = 0; i < klass->event.count; ++i) {
8156                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
8157                 klass->events [i].parent = klass;
8158                 klass->events [i].attrs = eb->attrs;
8159                 klass->events [i].name = mono_string_to_utf8 (eb->name);
8160                 if (eb->add_method)
8161                         klass->events [i].add = eb->add_method->mhandle;
8162                 if (eb->remove_method)
8163                         klass->events [i].remove = eb->remove_method->mhandle;
8164                 if (eb->raise_method)
8165                         klass->events [i].raise = eb->raise_method->mhandle;
8166
8167                 if (eb->other_methods) {
8168                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
8169                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
8170                                 MonoReflectionMethodBuilder *mb = 
8171                                         mono_array_get (eb->other_methods,
8172                                                                         MonoReflectionMethodBuilder*, j);
8173                                 klass->events [i].other [j] = mb->mhandle;
8174                         }
8175                 }
8176         }
8177 }
8178
8179 MonoReflectionType*
8180 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
8181 {
8182         MonoClass *klass;
8183         MonoReflectionType* res;
8184         int i;
8185
8186         MONO_ARCH_SAVE_REGS;
8187
8188         klass = my_mono_class_from_mono_type (tb->type.type);
8189
8190         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
8191
8192         /*
8193          * Fields to set in klass:
8194          * the various flags: delegate/unicode/contextbound etc.
8195          */
8196         klass->flags = tb->attrs;
8197
8198         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
8199                 /* No need to fully construct the type */
8200                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8201
8202         /* enums are done right away */
8203         if (!klass->enumtype)
8204                 ensure_runtime_vtable (klass);
8205
8206         if (tb->subtypes) {
8207                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
8208                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
8209                         klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
8210                 }
8211         }
8212
8213         /* fields and object layout */
8214         if (klass->parent) {
8215                 if (!klass->parent->size_inited)
8216                         mono_class_init (klass->parent);
8217                 klass->instance_size += klass->parent->instance_size;
8218                 klass->class_size += klass->parent->class_size;
8219                 klass->min_align = klass->parent->min_align;
8220         } else {
8221                 klass->instance_size = sizeof (MonoObject);
8222                 klass->min_align = 1;
8223         }
8224
8225         /* FIXME: handle packing_size and instance_size */
8226         typebuilder_setup_fields (klass);
8227
8228         typebuilder_setup_properties (klass);
8229
8230         typebuilder_setup_events (klass);
8231
8232         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
8233         /* with enums res == tb: need to fix that. */
8234         if (!klass->enumtype)
8235                 g_assert (res != (MonoReflectionType*)tb);
8236         return res;
8237 }
8238
8239 void
8240 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
8241 {
8242         MonoGenericParam *param;
8243         MonoImage *image;
8244
8245         MONO_ARCH_SAVE_REGS;
8246
8247         param = g_new0 (MonoGenericParam, 1);
8248
8249         param->method = NULL;
8250         param->name = mono_string_to_utf8 (gparam->name);
8251         param->num = gparam->index;
8252
8253         image = &gparam->tbuilder->module->dynamic_image->image;
8254         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
8255
8256         param->pklass->reflection_info = gparam;
8257
8258         gparam->type.type = g_new0 (MonoType, 1);
8259         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
8260         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
8261         gparam->type.type->data.generic_param = param;
8262 }
8263
8264 MonoArray *
8265 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
8266 {
8267         MonoDynamicImage *assembly = sig->module->dynamic_image;
8268         guint32 na = mono_array_length (sig->arguments);
8269         guint32 buflen, i;
8270         MonoArray *result;
8271         char *buf, *p;
8272
8273         MONO_ARCH_SAVE_REGS;
8274
8275         p = buf = g_malloc (10 + na * 10);
8276
8277         mono_metadata_encode_value (0x07, p, &p);
8278         mono_metadata_encode_value (na, p, &p);
8279         for (i = 0; i < na; ++i) {
8280                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8281                 encode_reflection_type (assembly, type, p, &p);
8282         }
8283
8284         buflen = p - buf;
8285         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8286         p = mono_array_addr (result, char, 0);
8287         memcpy (p, buf, buflen);
8288         g_free (buf);
8289
8290         return result;
8291 }
8292
8293 MonoArray *
8294 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8295 {
8296         MonoDynamicImage *assembly = sig->module->dynamic_image;
8297         guint32 na = mono_array_length (sig->arguments);
8298         guint32 buflen, i;
8299         MonoArray *result;
8300         char *buf, *p;
8301
8302         MONO_ARCH_SAVE_REGS;
8303
8304         p = buf = g_malloc (10 + na * 10);
8305
8306         mono_metadata_encode_value (0x06, p, &p);
8307         for (i = 0; i < na; ++i) {
8308                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8309                 encode_reflection_type (assembly, type, p, &p);
8310         }
8311
8312         buflen = p - buf;
8313         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8314         p = mono_array_addr (result, char, 0);
8315         memcpy (p, buf, buflen);
8316         g_free (buf);
8317
8318         return result;
8319 }
8320
8321 void 
8322 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8323 {
8324         ReflectionMethodBuilder rmb;
8325         MonoMethodSignature *sig;
8326         int i;
8327
8328         sig = dynamic_method_to_signature (mb);
8329
8330         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8331
8332         /*
8333          * Resolve references.
8334          */
8335         rmb.nrefs = mb->nrefs;
8336         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8337         for (i = 0; i < mb->nrefs; ++i) {
8338                 gpointer ref = resolve_object (mb->module->image, 
8339                                                mono_array_get (mb->refs, MonoObject*, i));
8340                 if (!ref) {
8341                         g_free (rmb.refs);
8342                         mono_raise_exception (mono_get_exception_type_load (NULL));
8343                         return;
8344                 }
8345                 rmb.refs [i] = ref;
8346         }               
8347
8348         /* FIXME: class */
8349         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8350
8351         g_free (rmb.refs);
8352
8353         /* ilgen is no longer needed */
8354         mb->ilgen = NULL;
8355 }
8356
8357 /**
8358  * mono_reflection_lookup_dynamic_token:
8359  *
8360  *  Finish the Builder object pointed to by TOKEN and return the corresponding
8361  * runtime structure.
8362  */
8363 gpointer
8364 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8365 {
8366         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8367         MonoObject *obj;
8368
8369         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8370         g_assert (obj);
8371
8372         return resolve_object (image, obj);
8373 }
8374
8375 static gpointer
8376 resolve_object (MonoImage *image, MonoObject *obj)
8377 {
8378         gpointer result = NULL;
8379
8380         if (strcmp (obj->vtable->klass->name, "String") == 0) {
8381                 result = mono_string_intern ((MonoString*)obj);
8382                 g_assert (result);
8383         } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8384                 MonoReflectionType *tb = (MonoReflectionType*)obj;
8385                 result = mono_class_from_mono_type (tb->type);
8386                 g_assert (result);
8387         } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8388                 result = ((MonoReflectionMethod*)obj)->method;
8389                 g_assert (result);
8390         } else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8391                 result = ((MonoReflectionMethod*)obj)->method;
8392                 g_assert (result);
8393         } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8394                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8395                 result = mb->mhandle;
8396                 if (!result) {
8397                         /* Type is not yet created */
8398                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8399
8400                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8401
8402                         /*
8403                          * Hopefully this has been filled in by calling CreateType() on the
8404                          * TypeBuilder.
8405                          */
8406                         /**
8407                          * TODO: This won't work if the application finishes another 
8408                          * TypeBuilder instance instead of this one.
8409                          */
8410                         result = mb->mhandle;
8411                 }
8412         } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8413                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8414
8415                 result = cb->mhandle;
8416                 if (!result) {
8417                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8418
8419                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8420                         result = cb->mhandle;
8421                 }
8422         } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8423                 result = ((MonoReflectionField*)obj)->field;
8424                 g_assert (result);
8425         } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8426                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8427                 result = fb->handle;
8428
8429                 if (!result) {
8430                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8431
8432                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8433                         result = fb->handle;
8434                 }
8435         } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8436                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8437                 MonoClass *klass;
8438
8439                 klass = tb->type.type->data.klass;
8440                 if (klass->wastypebuilder) {
8441                         /* Already created */
8442                         result = klass;
8443                 }
8444                 else {
8445                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8446                         result = tb->type.type->data.klass;
8447                         g_assert (result);
8448                 }
8449         } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8450                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8451                 MonoMethodSignature *sig;
8452                 int nargs, i;
8453
8454                 if (helper->arguments)
8455                         nargs = mono_array_length (helper->arguments);
8456                 else
8457                         nargs = 0;
8458
8459                 sig = mono_metadata_signature_alloc (image, nargs);
8460                 sig->explicit_this = helper->call_conv & 64;
8461                 sig->hasthis = helper->call_conv & 32;
8462
8463                 if (helper->call_conv == 0) /* unmanaged */
8464                         sig->call_convention = helper->unmanaged_call_conv - 1;
8465                 else
8466                         if (helper->call_conv & 0x02)
8467                                 sig->call_convention = MONO_CALL_VARARG;
8468                 else
8469                         sig->call_convention = MONO_CALL_DEFAULT;
8470
8471                 sig->param_count = nargs;
8472                 /* TODO: Copy type ? */
8473                 sig->ret = helper->return_type->type;
8474                 for (i = 0; i < nargs; ++i) {
8475                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8476                         sig->params [i] = rt->type;
8477                 }
8478
8479                 result = sig;
8480         } else {
8481                 g_print (obj->vtable->klass->name);
8482                 g_assert_not_reached ();
8483         }
8484         return result;
8485 }
8486