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