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