aafd0235a3726851c7ec50a1f2c73c071219e873
[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->type->type->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 ((pubkey = mono_image_get_public_key (image, &publen))) {
2018                 guchar pubtoken [9];
2019                 pubtoken [0] = 8;
2020                 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2021                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2022         } else {
2023                 /* 
2024                  * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
2025                  * This is currently only a problem with references to System.Xml (see bug#27706),
2026                  * but there may be other cases that makes this necessary. Note, we need to set 
2027                  * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken 
2028                  * recognized by ms, yuck!
2029                  * FIXME: need to add more assembly names, as needed.
2030                  */
2031                 if (strcmp (image->assembly_name, "corlib") == 0 ||
2032                                 strcmp (image->assembly_name, "mscorlib") == 0 ||
2033                                 strcmp (image->assembly_name, "System") == 0 ||
2034                                 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
2035                                 strcmp (image->assembly_name, "System.Xml") == 0 ||
2036                                 strcmp (image->assembly_name, "System.Data") == 0 ||
2037                                 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
2038                         static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
2039                         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2040                         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2041                         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2042                 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
2043                                 strcmp (image->assembly_name, "cscompmgd") == 0 ||
2044                                 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2045                                 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
2046                                 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
2047                                 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
2048                                 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
2049                                 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
2050                                 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
2051                                 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
2052                                 strcmp (image->assembly_name, "System.Design") == 0 ||
2053                                 strcmp (image->assembly_name, "System.Drawing") == 0 ||
2054                                 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
2055                                 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
2056                                 strcmp (image->assembly_name, "System.Management") == 0 ||
2057                                 strcmp (image->assembly_name, "System.Messaging") == 0 ||
2058                                 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
2059                                 strcmp (image->assembly_name, "System.Security") == 0 ||
2060                                 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
2061                                 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
2062                                 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2063                                 strcmp (image->assembly_name, "System.Web") == 0) {
2064                         static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
2065                         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2066                         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2067                         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2068                 } else {
2069                         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2070                 }
2071         }
2072         token <<= RESOLTION_SCOPE_BITS;
2073         token |= RESOLTION_SCOPE_ASSEMBLYREF;
2074         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2075         return token;
2076 }
2077
2078 static guint32
2079 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2080 {
2081         MonoDynamicTable *table;
2082         guint32 *values;
2083         guint32 token;
2084         char sig [128];
2085         char *p = sig;
2086         char blob_size [6];
2087         char *b = blob_size;
2088
2089         switch (type->type) {
2090         case MONO_TYPE_FNPTR:
2091         case MONO_TYPE_PTR:
2092         case MONO_TYPE_SZARRAY:
2093         case MONO_TYPE_ARRAY:
2094         case MONO_TYPE_VAR:
2095         case MONO_TYPE_MVAR:
2096         case MONO_TYPE_GENERICINST:
2097                 encode_type (assembly, type, p, &p);
2098                 break;
2099         case MONO_TYPE_CLASS:
2100         case MONO_TYPE_VALUETYPE: {
2101                 MonoClass *k = mono_class_from_mono_type (type);
2102                 if (!k || !k->generic_inst)
2103                         return 0;
2104                 encode_generic_inst (assembly, k->generic_inst, p, &p);
2105                 break;
2106         }
2107         default:
2108                 return 0;
2109         }
2110
2111         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2112         if (assembly->save) {
2113                 g_assert (p-sig < 128);
2114                 mono_metadata_encode_value (p-sig, b, &b);
2115                 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2116                 alloc_table (table, table->rows + 1);
2117                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2118                 values [MONO_TYPESPEC_SIGNATURE] = token;
2119         }
2120
2121         token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2122         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2123         table->next_idx ++;
2124         return token;
2125 }
2126
2127 /*
2128  * Despite the name, we handle also TypeSpec (with the above helper).
2129  */
2130 static guint32
2131 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2132 {
2133         MonoDynamicTable *table;
2134         guint32 *values;
2135         guint32 token, scope, enclosing;
2136         MonoClass *klass;
2137
2138         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2139         if (token)
2140                 return token;
2141         token = create_typespec (assembly, type);
2142         if (token)
2143                 return token;
2144         klass = my_mono_class_from_mono_type (type);
2145         if (!klass)
2146                 klass = mono_class_from_mono_type (type);
2147
2148         /*
2149          * If it's in the same module and not a generic type parameter:
2150          */
2151         if ((klass->image == &assembly->image) &&
2152             (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2153                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2154                 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
2155                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2156                 return token;
2157         }
2158
2159         if (klass->nested_in) {
2160                 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2161                 /* get the typeref idx of the enclosing type */
2162                 enclosing >>= TYPEDEFORREF_BITS;
2163                 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
2164         } else {
2165                 scope = resolution_scope_from_image (assembly, klass->image);
2166         }
2167         table = &assembly->tables [MONO_TABLE_TYPEREF];
2168         if (assembly->save) {
2169                 alloc_table (table, table->rows + 1);
2170                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2171                 values [MONO_TYPEREF_SCOPE] = scope;
2172                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2173                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2174         }
2175         token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2176         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2177         table->next_idx ++;
2178         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2179         return token;
2180 }
2181
2182 /*
2183  * Insert a memberef row into the metadata: the token that point to the memberref
2184  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2185  * mono_image_get_fieldref_token()).
2186  * The sig param is an index to an already built signature.
2187  */
2188 static guint32
2189 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2190 {
2191         MonoDynamicTable *table;
2192         guint32 *values;
2193         guint32 token, pclass;
2194         guint32 parent;
2195
2196         parent = mono_image_typedef_or_ref (assembly, type);
2197         switch (parent & TYPEDEFORREF_MASK) {
2198         case TYPEDEFORREF_TYPEREF:
2199                 pclass = MEMBERREF_PARENT_TYPEREF;
2200                 break;
2201         case TYPEDEFORREF_TYPESPEC:
2202                 pclass = MEMBERREF_PARENT_TYPESPEC;
2203                 break;
2204         case TYPEDEFORREF_TYPEDEF:
2205                 pclass = MEMBERREF_PARENT_TYPEDEF;
2206                 break;
2207         default:
2208                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2209                 return 0;
2210         }
2211         /* extract the index */
2212         parent >>= TYPEDEFORREF_BITS;
2213
2214         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2215
2216         if (assembly->save) {
2217                 alloc_table (table, table->rows + 1);
2218                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2219                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2220                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2221                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2222         }
2223
2224         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2225         table->next_idx ++;
2226
2227         return token;
2228 }
2229
2230 static guint32
2231 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2232 {
2233         guint32 token;
2234         
2235         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2236         if (token)
2237                 return token;
2238         token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2239                 method->name,  method_encode_signature (assembly, method->signature));
2240         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2241         return token;
2242 }
2243
2244 static guint32
2245 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2246 {
2247         guint32 token;
2248         ReflectionMethodBuilder rmb;
2249         
2250         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2251         if (token)
2252                 return token;
2253
2254         reflection_methodbuilder_from_method_builder (&rmb, mb);
2255         
2256         token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2257                                                                                         mono_string_to_utf8 (rmb.name),
2258                                                                                         method_builder_encode_signature (assembly, &rmb));
2259         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2260         return token;
2261 }
2262
2263 static guint32
2264 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2265 {
2266         guint32 token;
2267         ReflectionMethodBuilder rmb;
2268         
2269         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2270         if (token)
2271                 return token;
2272
2273         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2274
2275         token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2276                                                                                         mono_string_to_utf8 (rmb.name),
2277                                                                                         method_builder_encode_signature (assembly, &rmb));
2278         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2279         return token;
2280 }
2281
2282 static guint32
2283 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2284 {
2285         MonoType *type;
2286         guint32 token;
2287
2288         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2289         if (token)
2290                 return token;
2291         g_assert (f->field->parent);
2292         type = f->field->generic_type ? f->field->generic_type : f->field->type;
2293         token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg, 
2294                 f->field->name,  fieldref_encode_signature (assembly, type));
2295         g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2296         return token;
2297 }
2298
2299 static guint32
2300 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2301 {
2302         char *buf;
2303         char *p;
2304         int i;
2305         guint32 nparams =  gmethod->mtype_argc;
2306         guint32 size = 10 + nparams * 10;
2307         guint32 idx;
2308         char blob_size [6];
2309         char *b = blob_size;
2310
2311         if (!assembly->save)
2312                 return 0;
2313
2314         p = buf = g_malloc (size);
2315         /*
2316          * FIXME: vararg, explicit_this, differenc call_conv values...
2317          */
2318         mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2319         mono_metadata_encode_value (nparams, p, &p);
2320
2321         for (i = 0; i < nparams; i++)
2322                 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2323
2324         /* store length */
2325         g_assert (p - buf < size);
2326         mono_metadata_encode_value (p-buf, b, &b);
2327         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2328         g_free (buf);
2329         return idx;
2330 }
2331
2332 static guint32
2333 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2334 {
2335         MonoDynamicTable *table;
2336         guint32 *values;
2337         guint32 token, mtoken = 0, sig;
2338         MonoMethodInflated *imethod;
2339         MonoMethod *declaring;
2340
2341         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2342
2343         g_assert (method->signature->is_inflated);
2344         imethod = (MonoMethodInflated *) method;
2345         declaring = imethod->declaring;
2346
2347         sig = method_encode_signature (assembly, declaring->signature);
2348         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2349                                                  declaring->name, sig);
2350
2351         if (!declaring->signature->generic_param_count)
2352                 return mtoken;
2353
2354         switch (mono_metadata_token_table (mtoken)) {
2355         case MONO_TABLE_MEMBERREF:
2356                 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2357                 break;
2358         case MONO_TABLE_METHOD:
2359                 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2360                 break;
2361         default:
2362                 g_assert_not_reached ();
2363         }
2364
2365         sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2366
2367         if (assembly->save) {
2368                 alloc_table (table, table->rows + 1);
2369                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2370                 values [MONO_METHODSPEC_METHOD] = mtoken;
2371                 values [MONO_METHODSPEC_SIGNATURE] = sig;
2372         }
2373
2374         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2375         table->next_idx ++;
2376
2377         return token;
2378 }
2379
2380 static guint32
2381 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2382 {
2383         MonoMethodInflated *imethod;
2384         guint32 token;
2385         
2386         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2387         if (token)
2388                 return token;
2389
2390         g_assert (m->signature->is_inflated);
2391         imethod = (MonoMethodInflated *) m;
2392
2393         if (imethod->declaring->signature->generic_param_count)
2394                 token = method_encode_methodspec (assembly, m);
2395         else {
2396                 guint32 sig = method_encode_signature (
2397                         assembly, imethod->declaring->signature);
2398                 token = mono_image_get_memberref_token (
2399                         assembly, &m->klass->byval_arg, m->name, sig);
2400         }
2401
2402         g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2403         return token;
2404 }
2405
2406 static guint32
2407 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2408 {
2409         MonoDynamicTable *table;
2410         MonoClass *klass;
2411         guint32 *values;
2412         guint32 token;
2413         char sig [128];
2414         char *p = sig;
2415         char blob_size [6];
2416         char *b = blob_size;
2417         int count, i;
2418
2419         g_assert (tb->generic_params);
2420         klass = mono_class_from_mono_type (tb->type.type);
2421
2422         mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2423         encode_type (assembly, &klass->byval_arg, p, &p);
2424
2425         count = mono_array_length (tb->generic_params);
2426         mono_metadata_encode_value (count, p, &p);
2427         for (i = 0; i < count; i++) {
2428                 MonoReflectionGenericParam *gparam;
2429
2430                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2431
2432                 encode_type (assembly, gparam->type.type, p, &p);
2433         }
2434
2435         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2436         if (assembly->save) {
2437                 g_assert (p-sig < 128);
2438                 mono_metadata_encode_value (p-sig, b, &b);
2439                 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2440                 alloc_table (table, table->rows + 1);
2441                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2442                 values [MONO_TYPESPEC_SIGNATURE] = token;
2443         }
2444
2445         token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2446         g_hash_table_insert (assembly->typeref, tb->type.type, GUINT_TO_POINTER(token));
2447         table->next_idx ++;
2448         return token;
2449 }
2450
2451 static guint32
2452 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2453 {
2454         MonoDynamicTable *table;
2455         MonoClass *klass;
2456         guint32 *values;
2457         guint32 token, pclass, parent, sig;
2458         gchar *name;
2459
2460         klass = mono_class_from_mono_type (fb->typeb->type);
2461         name = mono_string_to_utf8 (fb->name);
2462
2463         sig = fieldref_encode_signature (assembly, fb->type->type);
2464
2465         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2466         g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2467         
2468         pclass = MEMBERREF_PARENT_TYPESPEC;
2469         parent >>= TYPEDEFORREF_BITS;
2470
2471         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2472
2473         if (assembly->save) {
2474                 alloc_table (table, table->rows + 1);
2475                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2476                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2477                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2478                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2479         }
2480
2481         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2482         table->next_idx ++;
2483
2484         return token;
2485 }
2486
2487 static guint32
2488 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2489 {
2490         char *buf;
2491         char *p;
2492         guint32 nargs;
2493         guint32 size;
2494         guint32 i, idx;
2495         char blob_size [6];
2496         char *b = blob_size;
2497
2498         if (!assembly->save)
2499                 return 0;
2500
2501         /* FIXME: */
2502         g_assert (helper->type == 2);
2503
2504         if (helper->arguments)
2505                 nargs = mono_array_length (helper->arguments);
2506         else
2507                 nargs = 0;
2508
2509         size = 10 + (nargs * 10);
2510         
2511         p = buf = g_malloc (size);
2512
2513         /* Encode calling convention */
2514         /* Change Any to Standard */
2515         if ((helper->call_conv & 0x03) == 0x03)
2516                 helper->call_conv = 0x01;
2517         /* explicit_this implies has_this */
2518         if (helper->call_conv & 0x40)
2519                 helper->call_conv &= 0x20;
2520
2521         if (helper->call_conv == 0) /* Unmanaged */
2522                 *p = helper->unmanaged_call_conv - 1;
2523         else {
2524                 /* Managed */
2525                 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2526                 if (helper->call_conv & 0x02) /* varargs */
2527                         *p += 0x05;
2528         }
2529
2530         p++;
2531         mono_metadata_encode_value (nargs, p, &p);
2532         encode_reflection_type (assembly, helper->return_type, p, &p);
2533         for (i = 0; i < nargs; ++i) {
2534                 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2535                 encode_reflection_type (assembly, pt, p, &p);
2536         }
2537         /* store length */
2538         g_assert (p - buf < size);
2539         mono_metadata_encode_value (p-buf, b, &b);
2540         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2541         g_free (buf);
2542
2543         return idx;
2544 }
2545         
2546 static guint32 
2547 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2548 {
2549         guint32 idx;
2550         MonoDynamicTable *table;
2551         guint32 *values;
2552
2553         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2554         idx = table->next_idx ++;
2555         table->rows ++;
2556         alloc_table (table, table->rows);
2557         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2558
2559         values [MONO_STAND_ALONE_SIGNATURE] =
2560                 mono_reflection_encode_sighelper (assembly, helper);
2561
2562         return idx;
2563 }
2564
2565 static int
2566 reflection_cc_to_file (int call_conv) {
2567         switch (call_conv & 0x3) {
2568         case 0:
2569         case 1: return MONO_CALL_DEFAULT;
2570         case 2: return MONO_CALL_VARARG;
2571         default:
2572                 g_assert_not_reached ();
2573         }
2574         return 0;
2575 }
2576
2577 typedef struct {
2578         MonoType *parent;
2579         MonoMethodSignature *sig;
2580         char *name;
2581         guint32 token;
2582 } ArrayMethod;
2583
2584 static guint32
2585 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2586 {
2587         guint32 nparams, i;
2588         GList *tmp;
2589         char *name;
2590         MonoMethodSignature *sig;
2591         ArrayMethod *am;
2592         
2593         name = mono_string_to_utf8 (m->name);
2594         nparams = mono_array_length (m->parameters);
2595         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2596         sig->hasthis = 1;
2597         sig->call_convention = reflection_cc_to_file (m->call_conv);
2598         sig->param_count = nparams;
2599         sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2600         for (i = 0; i < nparams; ++i) {
2601                 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2602                 sig->params [i] = t->type;
2603         }
2604
2605         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2606                 am = tmp->data;
2607                 if (strcmp (name, am->name) == 0 && 
2608                                 mono_metadata_type_equal (am->parent, m->parent->type) &&
2609                                 mono_metadata_signature_equal (am->sig, sig)) {
2610                         g_free (name);
2611                         g_free (sig);
2612                         m->table_idx = am->token & 0xffffff;
2613                         return am->token;
2614                 }
2615         }
2616         am = g_new0 (ArrayMethod, 1);
2617         am->name = name;
2618         am->sig = sig;
2619         am->parent = m->parent->type;
2620         am->token = mono_image_get_memberref_token (assembly, am->parent,
2621                         name,  method_encode_signature (assembly, sig));
2622         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2623         m->table_idx = am->token & 0xffffff;
2624         return am->token;
2625 }
2626
2627 /*
2628  * Insert into the metadata tables all the info about the TypeBuilder tb.
2629  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2630  */
2631 static void
2632 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2633 {
2634         MonoDynamicTable *table;
2635         guint *values;
2636         int i, is_object = 0, is_system = 0;
2637         char *n;
2638
2639         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2640         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2641         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2642         n = mono_string_to_utf8 (tb->name);
2643         if (strcmp (n, "Object") == 0)
2644                 is_object++;
2645         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2646         g_free (n);
2647         n = mono_string_to_utf8 (tb->nspace);
2648         if (strcmp (n, "System") == 0)
2649                 is_system++;
2650         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2651         g_free (n);
2652         if (tb->parent && !(is_system && is_object) && 
2653                 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2654                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2655         } else
2656                 values [MONO_TYPEDEF_EXTENDS] = 0;
2657         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2658         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2659
2660         /*
2661          * if we have explicitlayout or sequentiallayouts, output data in the
2662          * ClassLayout table.
2663          */
2664         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2665                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2666                 table->rows++;
2667                 alloc_table (table, table->rows);
2668                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2669                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2670                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2671                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2672         }
2673
2674         /* handle interfaces */
2675         if (tb->interfaces) {
2676                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2677                 i = table->rows;
2678                 table->rows += mono_array_length (tb->interfaces);
2679                 alloc_table (table, table->rows);
2680                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2681                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2682                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2683                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2684                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2685                         values += MONO_INTERFACEIMPL_SIZE;
2686                 }
2687         }
2688
2689         /* handle generic parameters */
2690         if (tb->generic_params) {
2691                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2692                 table->rows += mono_array_length (tb->generic_params);
2693                 alloc_table (table, table->rows);
2694                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2695                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2696
2697                         mono_image_get_generic_param_info (
2698                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2699                 }
2700         }
2701
2702         /* handle fields */
2703         if (tb->fields) {
2704                 table = &assembly->tables [MONO_TABLE_FIELD];
2705                 table->rows += tb->num_fields;
2706                 alloc_table (table, table->rows);
2707                 for (i = 0; i < tb->num_fields; ++i)
2708                         mono_image_get_field_info (
2709                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2710         }
2711
2712         /* handle constructors */
2713         if (tb->ctors) {
2714                 table = &assembly->tables [MONO_TABLE_METHOD];
2715                 table->rows += mono_array_length (tb->ctors);
2716                 alloc_table (table, table->rows);
2717                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2718                         mono_image_get_ctor_info (domain,
2719                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2720         }
2721
2722         /* handle methods */
2723         if (tb->methods) {
2724                 table = &assembly->tables [MONO_TABLE_METHOD];
2725                 table->rows += tb->num_methods;
2726                 alloc_table (table, table->rows);
2727                 for (i = 0; i < tb->num_methods; ++i)
2728                         mono_image_get_method_info (
2729                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2730         }
2731
2732         /* Do the same with properties etc.. */
2733         if (tb->events && mono_array_length (tb->events)) {
2734                 table = &assembly->tables [MONO_TABLE_EVENT];
2735                 table->rows += mono_array_length (tb->events);
2736                 alloc_table (table, table->rows);
2737                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2738                 table->rows ++;
2739                 alloc_table (table, table->rows);
2740                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2741                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2742                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2743                 for (i = 0; i < mono_array_length (tb->events); ++i)
2744                         mono_image_get_event_info (
2745                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2746         }
2747         if (tb->properties && mono_array_length (tb->properties)) {
2748                 table = &assembly->tables [MONO_TABLE_PROPERTY];
2749                 table->rows += mono_array_length (tb->properties);
2750                 alloc_table (table, table->rows);
2751                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2752                 table->rows ++;
2753                 alloc_table (table, table->rows);
2754                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2755                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2756                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2757                 for (i = 0; i < mono_array_length (tb->properties); ++i)
2758                         mono_image_get_property_info (
2759                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2760         }
2761
2762         mono_image_add_decl_security (assembly, 
2763                                                                   mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2764                                                                   tb->permissions);
2765
2766         if (tb->subtypes) {
2767                 MonoDynamicTable *ntable;
2768                 
2769                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2770                 ntable->rows += mono_array_length (tb->subtypes);
2771                 alloc_table (ntable, ntable->rows);
2772                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2773
2774                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2775                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2776
2777                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2778                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2779                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2780                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2781                                 mono_string_to_utf8 (tb->name), tb->table_idx,
2782                                 ntable->next_idx, ntable->rows);*/
2783                         values += MONO_NESTED_CLASS_SIZE;
2784                         ntable->next_idx++;
2785                 }
2786         }
2787 }
2788
2789 static void
2790 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2791 {
2792         int i;
2793
2794         g_ptr_array_add (types, type);
2795
2796         if (!type->subtypes)
2797                 return;
2798
2799         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2800                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2801                 collect_types (types, subtype);
2802         }
2803 }
2804
2805 static gint
2806 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, 
2807                                                         MonoReflectionTypeBuilder **type2)
2808 {
2809         if ((*type1)->table_idx < (*type2)->table_idx)
2810                 return -1;
2811         else
2812                 if ((*type1)->table_idx > (*type2)->table_idx)
2813                         return 1;
2814         else
2815                 return 0;
2816 }
2817
2818 static void
2819 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2820         int i;
2821
2822         if (!pinfo)
2823                 return;
2824         for (i = 0; i < mono_array_length (pinfo); ++i) {
2825                 MonoReflectionParamBuilder *pb;
2826                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2827                 if (!pb)
2828                         continue;
2829                 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2830         }
2831 }
2832
2833 static void
2834 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2835         int i;
2836         
2837         mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2838         if (tb->fields) {
2839                 for (i = 0; i < tb->num_fields; ++i) {
2840                         MonoReflectionFieldBuilder* fb;
2841                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2842                         mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2843                 }
2844         }
2845         if (tb->events) {
2846                 for (i = 0; i < mono_array_length (tb->events); ++i) {
2847                         MonoReflectionEventBuilder* eb;
2848                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2849                         mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2850                 }
2851         }
2852         if (tb->properties) {
2853                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2854                         MonoReflectionPropertyBuilder* pb;
2855                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2856                         mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2857                 }
2858         }
2859         if (tb->ctors) {
2860                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2861                         MonoReflectionCtorBuilder* cb;
2862                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2863                         mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2864                         params_add_cattrs (assembly, cb->pinfo);
2865                 }
2866         }
2867
2868         if (tb->methods) {
2869                 for (i = 0; i < tb->num_methods; ++i) {
2870                         MonoReflectionMethodBuilder* mb;
2871                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2872                         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2873                         params_add_cattrs (assembly, mb->pinfo);
2874                 }
2875         }
2876
2877         if (tb->subtypes) {
2878                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2879                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2880         }
2881 }
2882
2883 static void
2884 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2885         int i;
2886         
2887         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2888         
2889         /* no types in the module */
2890         if (!mb->types)
2891                 return;
2892         
2893         for (i = 0; i < mb->num_types; ++i)
2894                 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2895 }
2896
2897 static void
2898 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2899                                                         MonoDynamicImage *assembly)
2900 {
2901         MonoDynamicTable *table;
2902         guint32 *values;
2903         char blob_size [6];
2904         guchar hash [20];
2905         char *b = blob_size;
2906         char *dir, *path;
2907
2908         table = &assembly->tables [MONO_TABLE_FILE];
2909         table->rows++;
2910         alloc_table (table, table->rows);
2911         values = table->values + table->next_idx * MONO_FILE_SIZE;
2912         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2913         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2914         if (module->image->dynamic) {
2915                 /* This depends on the fact that the main module is emitted last */
2916                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2917                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2918         }
2919         else {
2920                 dir = NULL;
2921                 path = g_strdup (module->image->name);
2922         }
2923         mono_sha1_get_digest_from_file (path, hash);
2924         g_free (dir);
2925         g_free (path);
2926         mono_metadata_encode_value (20, b, &b);
2927         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2928         mono_image_add_stream_data (&assembly->blob, hash, 20);
2929         table->next_idx ++;
2930 }
2931
2932 static void
2933 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2934 {
2935         MonoDynamicTable *table;
2936         int i;
2937         char *name;
2938
2939         table = &assembly->tables [MONO_TABLE_MODULE];
2940         mb->table_idx = table->next_idx ++;
2941         name = mono_string_to_utf8 (mb->module.name);
2942         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2943         g_free (name);
2944         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2945         i /= 16;
2946         ++i;
2947         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2948         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2949         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2950 }
2951
2952 static guint32
2953 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2954                                                                                  guint32 module_index, guint32 parent_index, 
2955                                                                                  MonoDynamicImage *assembly)
2956 {
2957         MonoDynamicTable *table;
2958         guint32 *values;
2959         guint32 visib, res;
2960
2961         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2962         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
2963                 return 0;
2964
2965         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
2966         table->rows++;
2967         alloc_table (table, table->rows);
2968         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
2969
2970         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
2971         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
2972         if (klass->nested_in)
2973                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
2974         else
2975                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
2976         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2977         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2978
2979         res = table->next_idx;
2980
2981         table->next_idx ++;
2982
2983         /* Emit nested types */
2984         if (klass->nested_classes) {
2985                 GList *tmp;
2986
2987                 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
2988                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
2989         }
2990
2991         return res;
2992 }
2993
2994 static void
2995 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
2996                                                           guint32 module_index, guint32 parent_index, 
2997                                                           MonoDynamicImage *assembly)
2998 {
2999         MonoClass *klass;
3000         guint32 idx, i;
3001
3002         klass = mono_class_from_mono_type (tb->type.type);
3003
3004         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3005
3006         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3007                                                                                                    parent_index, assembly);
3008
3009         /* 
3010          * Emit nested types
3011          * We need to do this ourselves since klass->nested_classes is not set up.
3012          */
3013         if (tb->subtypes) {
3014                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3015                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3016         }
3017 }
3018
3019 static void
3020 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3021                                                                                   guint32 module_index,
3022                                                                                   MonoDynamicImage *assembly)
3023 {
3024         MonoImage *image = module->image;
3025         MonoTableInfo  *t;
3026         guint32 i;
3027
3028         t = &image->tables [MONO_TABLE_TYPEDEF];
3029
3030         for (i = 0; i < t->rows; ++i) {
3031                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3032
3033                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3034                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3035         }
3036 }
3037
3038 #define align_pointer(base,p)\
3039         do {\
3040                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3041                 if (__diff & 3)\
3042                         (p) += 4 - (__diff & 3);\
3043         } while (0)
3044
3045 static int
3046 compare_semantics (const void *a, const void *b)
3047 {
3048         const guint32 *a_values = a;
3049         const guint32 *b_values = b;
3050         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3051         if (assoc)
3052                 return assoc;
3053         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3054 }
3055
3056 static int
3057 compare_custom_attrs (const void *a, const void *b)
3058 {
3059         const guint32 *a_values = a;
3060         const guint32 *b_values = b;
3061
3062         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3063 }
3064
3065 static int
3066 compare_field_marshal (const void *a, const void *b)
3067 {
3068         const guint32 *a_values = a;
3069         const guint32 *b_values = b;
3070
3071         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3072 }
3073
3074 static int
3075 compare_nested (const void *a, const void *b)
3076 {
3077         const guint32 *a_values = a;
3078         const guint32 *b_values = b;
3079
3080         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3081 }
3082
3083 /*
3084  * build_compressed_metadata() fills in the blob of data that represents the 
3085  * raw metadata as it will be saved in the PE file. The five streams are output 
3086  * and the metadata tables are comnpressed from the guint32 array representation, 
3087  * to the compressed on-disk format.
3088  */
3089 static void
3090 build_compressed_metadata (MonoDynamicImage *assembly)
3091 {
3092         MonoDynamicTable *table;
3093         int i;
3094         guint64 valid_mask = 0;
3095         guint64 sorted_mask;
3096         guint32 heapt_size = 0;
3097         guint32 meta_size = 256; /* allow for header and other stuff */
3098         guint32 table_offset;
3099         guint32 ntables = 0;
3100         guint64 *int64val;
3101         guint32 *int32val;
3102         guint16 *int16val;
3103         MonoImage *meta;
3104         unsigned char *p;
3105
3106         struct StreamDesc {
3107                 const char *name;
3108                 MonoDynamicStream *stream;
3109         } stream_desc [5];
3110
3111         stream_desc[0].name  = "#~"; stream_desc[0].stream = &assembly->tstream;
3112         stream_desc[1].name  = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3113         stream_desc[2].name  = "#US"; stream_desc[2].stream = &assembly->us;
3114         stream_desc[3].name  = "#Blob"; stream_desc[3].stream = &assembly->blob;
3115         stream_desc[4].name  = "#GUID"; stream_desc[4].stream = &assembly->guid;
3116         
3117         /* tables that are sorted */
3118         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3119                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3120                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3121                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3122                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3123                 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3124         
3125         /* Compute table sizes */
3126         /* the MonoImage has already been created in mono_image_basic_init() */
3127         meta = &assembly->image;
3128         
3129         /* Setup the info used by compute_sizes () */
3130         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3131         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3132         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3133
3134         meta_size += assembly->blob.index;
3135         meta_size += assembly->guid.index;
3136         meta_size += assembly->sheap.index;
3137         meta_size += assembly->us.index;
3138
3139         for (i=0; i < 64; ++i)
3140                 meta->tables [i].rows = assembly->tables [i].rows;
3141         
3142         for (i = 0; i < 64; i++){
3143                 if (meta->tables [i].rows == 0)
3144                         continue;
3145                 valid_mask |= (guint64)1 << i;
3146                 ntables ++;
3147                 meta->tables [i].row_size = mono_metadata_compute_size (
3148                         meta, i, &meta->tables [i].size_bitfield);
3149                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3150         }
3151         heapt_size += 24; /* #~ header size */
3152         heapt_size += ntables * 4;
3153         meta_size += heapt_size;
3154         meta->raw_metadata = g_malloc0 (meta_size);
3155         p = meta->raw_metadata;
3156         /* the metadata signature */
3157         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3158         /* version numbers and 4 bytes reserved */
3159         int16val = (guint16*)p;
3160         *int16val++ = GUINT16_TO_LE (1);
3161         *int16val = GUINT16_TO_LE (1);
3162         p += 8;
3163         /* version string */
3164         int32val = (guint32*)p;
3165         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3166         p += 4;
3167         memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3168         p += GUINT32_FROM_LE (*int32val);
3169         align_pointer (meta->raw_metadata, p);
3170         int16val = (guint16*)p;
3171         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3172         *int16val = GUINT16_TO_LE (5); /* number of streams */
3173         p += 4;
3174
3175         /*
3176          * write the stream info.
3177          */
3178         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3179         table_offset += 3; table_offset &= ~3;
3180
3181         assembly->tstream.index = heapt_size;
3182         for (i = 0; i < 5; ++i) {
3183                 int32val = (guint32*)p;
3184                 stream_desc [i].stream->offset = table_offset;
3185                 *int32val++ = GUINT32_TO_LE (table_offset);
3186                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3187                 table_offset += GUINT32_FROM_LE (*int32val);
3188                 table_offset += 3; table_offset &= ~3;
3189                 p += 8;
3190                 strcpy (p, stream_desc [i].name);
3191                 p += strlen (stream_desc [i].name) + 1;
3192                 align_pointer (meta->raw_metadata, p);
3193         }
3194         /* 
3195          * now copy the data, the table stream header and contents goes first.
3196          */
3197         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3198         p = meta->raw_metadata + assembly->tstream.offset;
3199         int32val = (guint32*)p;
3200         *int32val = GUINT32_TO_LE (0); /* reserved */
3201         p += 4;
3202         *p++ = 1; /* version */
3203         *p++ = 0;
3204         if (meta->idx_string_wide)
3205                 *p |= 0x01;
3206         if (meta->idx_guid_wide)
3207                 *p |= 0x02;
3208         if (meta->idx_blob_wide)
3209                 *p |= 0x04;
3210         ++p;
3211         *p++ = 0; /* reserved */
3212         int64val = (guint64*)p;
3213         *int64val++ = GUINT64_TO_LE (valid_mask);
3214         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
3215         p += 16;
3216         int32val = (guint32*)p;
3217         for (i = 0; i < 64; i++){
3218                 if (meta->tables [i].rows == 0)
3219                         continue;
3220                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3221         }
3222         p = (unsigned char*)int32val;
3223
3224         /* sort the tables that still need sorting */
3225         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3226         if (table->rows)
3227                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3228         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3229         if (table->rows)
3230                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3231         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3232         if (table->rows)
3233                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3234         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3235         if (table->rows)
3236                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3237
3238         /* compress the tables */
3239         for (i = 0; i < 64; i++){
3240                 int row, col;
3241                 guint32 *values;
3242                 guint32 bitfield = meta->tables [i].size_bitfield;
3243                 if (!meta->tables [i].rows)
3244                         continue;
3245                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3246                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3247                 meta->tables [i].base = p;
3248                 for (row = 1; row <= meta->tables [i].rows; ++row) {
3249                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
3250                         for (col = 0; col < assembly->tables [i].columns; ++col) {
3251                                 switch (mono_metadata_table_size (bitfield, col)) {
3252                                 case 1:
3253                                         *p++ = values [col];
3254                                         break;
3255                                 case 2:
3256                                         *p++ = values [col] & 0xff;
3257                                         *p++ = (values [col] >> 8) & 0xff;
3258                                         break;
3259                                 case 4:
3260                                         *p++ = values [col] & 0xff;
3261                                         *p++ = (values [col] >> 8) & 0xff;
3262                                         *p++ = (values [col] >> 16) & 0xff;
3263                                         *p++ = (values [col] >> 24) & 0xff;
3264                                         break;
3265                                 default:
3266                                         g_assert_not_reached ();
3267                                 }
3268                         }
3269                 }
3270                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3271         }
3272         
3273         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3274         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3275         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3276         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3277         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3278
3279         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3280 }
3281
3282 /*
3283  * Some tables in metadata need to be sorted according to some criteria, but
3284  * when methods and fields are first created with reflection, they may be assigned a token
3285  * that doesn't correspond to the final token they will get assigned after the sorting.
3286  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3287  * with the reflection objects that represent them. Once all the tables are set up, the 
3288  * reflection objects will contains the correct table index. fixup_method() will fixup the
3289  * tokens for the method with ILGenerator @ilgen.
3290  */
3291 static void
3292 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3293         guint32 code_idx = GPOINTER_TO_UINT (value);
3294         MonoReflectionILTokenInfo *iltoken;
3295         MonoReflectionFieldBuilder *field;
3296         MonoReflectionCtorBuilder *ctor;
3297         MonoReflectionMethodBuilder *method;
3298         MonoReflectionTypeBuilder *tb;
3299         MonoReflectionArrayMethod *am;
3300         guint32 i, idx = 0;
3301         unsigned char *target;
3302
3303         for (i = 0; i < ilgen->num_token_fixups; ++i) {
3304                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3305                 target = assembly->code.data + code_idx + iltoken->code_pos;
3306                 switch (target [3]) {
3307                 case MONO_TABLE_FIELD:
3308                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3309                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
3310                                 idx = field->table_idx;
3311                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3312                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3313                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3314                         } else {
3315                                 g_assert_not_reached ();
3316                         }
3317                         break;
3318                 case MONO_TABLE_METHOD:
3319                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3320                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
3321                                 idx = method->table_idx;
3322                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3323                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3324                                 idx = ctor->table_idx;
3325                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
3326                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3327                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3328                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3329                         } else {
3330                                 g_assert_not_reached ();
3331                         }
3332                         break;
3333                 case MONO_TABLE_TYPEDEF:
3334                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3335                                 g_assert_not_reached ();
3336                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
3337                         idx = tb->table_idx;
3338                         break;
3339                 case MONO_TABLE_MEMBERREF:
3340                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3341                                 am = (MonoReflectionArrayMethod*)iltoken->member;
3342                                 idx = am->table_idx;
3343                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3344                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3345                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3346                                 g_assert (m->klass->generic_inst);
3347                                 continue;
3348                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3349                                 continue;
3350                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3351                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3352                                 g_assert (f->generic_type);
3353                                 continue;
3354                         } else {
3355                                 g_assert_not_reached ();
3356                         }
3357                         break;
3358                 case MONO_TABLE_METHODSPEC:
3359                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3360                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3361                                 g_assert (m->signature->generic_param_count);
3362                                 continue;
3363                         } else {
3364                                 g_assert_not_reached ();
3365                         }
3366                         break;
3367                 default:
3368                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
3369                 }
3370                 target [0] = idx & 0xff;
3371                 target [1] = (idx >> 8) & 0xff;
3372                 target [2] = (idx >> 16) & 0xff;
3373         }
3374 }
3375
3376 /*
3377  * fixup_cattrs:
3378  *
3379  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3380  * value is not known when the table is emitted.
3381  */
3382 static void
3383 fixup_cattrs (MonoDynamicImage *assembly)
3384 {
3385         MonoDynamicTable *table;
3386         guint32 *values;
3387         guint32 type, i, idx, token;
3388         MonoObject *ctor;
3389
3390         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3391
3392         for (i = 0; i < table->rows; ++i) {
3393                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3394
3395                 type = values [MONO_CUSTOM_ATTR_TYPE];
3396                 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3397                         idx = type >> CUSTOM_ATTR_TYPE_BITS;
3398                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3399                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3400                         g_assert (ctor);
3401
3402                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3403                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3404                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3405                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3406                         }
3407                 }
3408         }
3409 }
3410
3411 static void
3412 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3413 {
3414         MonoDynamicTable *table;
3415         guint32 *values;
3416         char *name;
3417
3418         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3419         table->rows++;
3420         alloc_table (table, table->rows);
3421         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3422         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3423         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3424         name = mono_string_to_utf8 (rsrc->name);
3425         values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3426         g_free (name);
3427         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3428         table->next_idx++;
3429 }
3430
3431 static void
3432 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3433 {
3434         MonoDynamicTable *table;
3435         guint32 *values;
3436         char blob_size [6];
3437         guchar hash [20];
3438         char *b = blob_size;
3439         char *name, *sname;
3440         guint32 idx, offset;
3441
3442         if (rsrc->filename) {
3443                 name = mono_string_to_utf8 (rsrc->filename);
3444                 sname = g_path_get_basename (name);
3445         
3446                 table = &assembly->tables [MONO_TABLE_FILE];
3447                 table->rows++;
3448                 alloc_table (table, table->rows);
3449                 values = table->values + table->next_idx * MONO_FILE_SIZE;
3450                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3451                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3452                 g_free (sname);
3453
3454                 mono_sha1_get_digest_from_file (name, hash);
3455                 mono_metadata_encode_value (20, b, &b);
3456                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3457                 mono_image_add_stream_data (&assembly->blob, hash, 20);
3458                 g_free (name);
3459                 idx = table->next_idx++;
3460                 rsrc->offset = 0;
3461                 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3462         } else {
3463                 char sizebuf [4];
3464                 offset = mono_array_length (rsrc->data);
3465                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3466                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3467                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3468                 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3469
3470                 if (!mb->is_main)
3471                         /* 
3472                          * The entry should be emitted into the MANIFESTRESOURCE table of 
3473                          * the main module, but that needs to reference the FILE table
3474                          * which isn't emitted yet.
3475                          */
3476                         return;
3477                 else
3478                         idx = 0;
3479         }
3480
3481         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3482 }
3483
3484 static void
3485 set_version_from_string (MonoString *version, guint32 *values)
3486 {
3487         gchar *ver, *p, *str;
3488         guint32 i;
3489         
3490         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3491         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3492         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3493         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3494         if (!version)
3495                 return;
3496         ver = str = mono_string_to_utf8 (version);
3497         for (i = 0; i < 4; ++i) {
3498                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3499                 switch (*p) {
3500                 case '.':
3501                         p++;
3502                         break;
3503                 case '*':
3504                         /* handle Revision and Build */
3505                         p++;
3506                         break;
3507                 }
3508                 ver = p;
3509         }
3510         g_free (str);
3511 }
3512
3513 static guint32
3514 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3515         gsize len;
3516         guint32 token = 0;
3517         char blob_size [6];
3518         char *b = blob_size;
3519
3520         if (!pkey)
3521                 return token;
3522
3523         len = mono_array_length (pkey);
3524         mono_metadata_encode_value (len, b, &b);
3525         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3526         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3527
3528         /* need to get the actual value from the key type... */
3529         assembly->strong_name_size = 128;
3530         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3531
3532         return token;
3533 }
3534
3535 static void
3536 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3537 {
3538         MonoDynamicTable *table;
3539         MonoDynamicImage *assembly;
3540         MonoReflectionAssemblyBuilder *assemblyb;
3541         MonoDomain *domain;
3542         guint32 *values;
3543         char *name;
3544         int i;
3545         guint32 module_index;
3546
3547         assemblyb = moduleb->assemblyb;
3548         assembly = moduleb->dynamic_image;
3549         domain = mono_object_domain (assemblyb);
3550
3551         /* Emit ASSEMBLY table */
3552         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3553         alloc_table (table, 1);
3554         values = table->values + MONO_ASSEMBLY_SIZE;
3555         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3556         name = mono_string_to_utf8 (assemblyb->name);
3557         values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3558         g_free (name);
3559         if (assemblyb->culture) {
3560                 name = mono_string_to_utf8 (assemblyb->culture);
3561                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3562                 g_free (name);
3563         } else {
3564                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3565         }
3566         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3567         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3568         set_version_from_string (assemblyb->version, values);
3569
3570         /* Emit FILE + EXPORTED_TYPE table */
3571         module_index = 0;
3572         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3573                 int j;
3574                 MonoReflectionModuleBuilder *file_module = 
3575                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3576                 if (file_module != moduleb) {
3577                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3578                         module_index ++;
3579                         if (file_module->types) {
3580                                 for (j = 0; j < file_module->num_types; ++j) {
3581                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3582                                         mono_image_fill_export_table (domain, tb, module_index, 0,
3583                                                                                                   assembly);
3584                                 }
3585                         }
3586                 }
3587         }
3588         if (assemblyb->loaded_modules) {
3589                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3590                         MonoReflectionModule *file_module = 
3591                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3592                         mono_image_fill_file_table (domain, file_module, assembly);
3593                         module_index ++;
3594                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3595                 }
3596         }
3597
3598         /* Emit MANIFESTRESOURCE table */
3599         module_index = 0;
3600         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3601                 int j;
3602                 MonoReflectionModuleBuilder *file_module = 
3603                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3604                 /* The table for the main module is emitted later */
3605                 if (file_module != moduleb) {
3606                         module_index ++;
3607                         if (file_module->resources) {
3608                                 int len = mono_array_length (file_module->resources);
3609                                 for (j = 0; j < len; ++j) {
3610                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3611                                         assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3612                                 }
3613                         }
3614                 }
3615         }               
3616 }
3617
3618 /*
3619  * mono_image_build_metadata() will fill the info in all the needed metadata tables
3620  * for the modulebuilder @moduleb.
3621  * At the end of the process, method and field tokens are fixed up and the 
3622  * on-disk compressed metadata representation is created.
3623  */
3624 void
3625 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3626 {
3627         MonoDynamicTable *table;
3628         MonoDynamicImage *assembly;
3629         MonoReflectionAssemblyBuilder *assemblyb;
3630         MonoDomain *domain;
3631         guint32 *values;
3632         int i;
3633
3634         assemblyb = moduleb->assemblyb;
3635         assembly = moduleb->dynamic_image;
3636         domain = mono_object_domain (assemblyb);
3637
3638         if (assembly->text_rva)
3639                 return;
3640
3641         assembly->text_rva = START_TEXT_RVA;
3642
3643         if (moduleb->is_main) {
3644                 mono_image_emit_manifest (moduleb);
3645         }
3646
3647         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3648         table->rows = 1; /* .<Module> */
3649         table->next_idx++;
3650         alloc_table (table, table->rows);
3651         /*
3652          * Set the first entry.
3653          */
3654         values = table->values + table->columns;
3655         values [MONO_TYPEDEF_FLAGS] = 0;
3656         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3657         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3658         values [MONO_TYPEDEF_EXTENDS] = 0;
3659         values [MONO_TYPEDEF_FIELD_LIST] = 1;
3660         values [MONO_TYPEDEF_METHOD_LIST] = 1;
3661
3662         /* 
3663          * handle global methods 
3664          * FIXME: test what to do when global methods are defined in multiple modules.
3665          */
3666         if (moduleb->global_methods) {
3667                 table = &assembly->tables [MONO_TABLE_METHOD];
3668                 table->rows += mono_array_length (moduleb->global_methods);
3669                 alloc_table (table, table->rows);
3670                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3671                         mono_image_get_method_info (
3672                                                                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3673         }
3674         if (moduleb->global_fields) {
3675                 table = &assembly->tables [MONO_TABLE_FIELD];
3676                 table->rows += mono_array_length (moduleb->global_fields);
3677                 alloc_table (table, table->rows);
3678                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3679                         mono_image_get_field_info (
3680                                                                            mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3681         }
3682
3683         table = &assembly->tables [MONO_TABLE_MODULE];
3684         alloc_table (table, 1);
3685         mono_image_fill_module_table (domain, moduleb, assembly);
3686
3687         /* Emit types */
3688         {
3689                 /* Collect all types into a list sorted by their table_idx */
3690                 GPtrArray *types = g_ptr_array_new ();
3691
3692                 if (moduleb->types)
3693                         for (i = 0; i < moduleb->num_types; ++i) {
3694                                 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3695                                 collect_types (types, type);
3696                         }
3697
3698                 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3699                 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3700                 table->rows += types->len;
3701                 alloc_table (table, table->rows);
3702
3703                 for (i = 0; i < types->len; ++i) {
3704                         MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3705                         mono_image_get_type_info (domain, type, assembly);
3706                 }
3707                 g_ptr_array_free (types, TRUE);
3708         }
3709
3710         /* 
3711          * table->rows is already set above and in mono_image_fill_module_table.
3712          */
3713         /* add all the custom attributes at the end, once all the indexes are stable */
3714         mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3715
3716         module_add_cattrs (assembly, moduleb);
3717
3718         /* fixup tokens */
3719         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3720         fixup_cattrs (assembly);
3721 }
3722
3723 /*
3724  * mono_image_insert_string:
3725  * @module: module builder object
3726  * @str: a string
3727  *
3728  * Insert @str into the user string stream of @module.
3729  */
3730 guint32
3731 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3732 {
3733         MonoDynamicImage *assembly;
3734         guint32 idx;
3735         char buf [16];
3736         char *b = buf;
3737         
3738         MONO_ARCH_SAVE_REGS;
3739
3740         if (!module->dynamic_image)
3741                 mono_image_module_basic_init (module);
3742
3743         assembly = module->dynamic_image;
3744         
3745         if (assembly->save) {
3746                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3747                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3748 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3749         {
3750                 char *swapped = g_malloc (2 * mono_string_length (str));
3751                 const char *p = (const char*)mono_string_chars (str);
3752
3753                 swap_with_size (swapped, p, 2, mono_string_length (str));
3754                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3755                 g_free (swapped);
3756         }
3757 #else
3758         mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3759 #endif
3760         mono_image_add_stream_data (&assembly->us, "", 1);
3761         }
3762         else
3763                 idx = assembly->us.index ++;
3764
3765         mono_g_hash_table_insert (assembly->tokens, 
3766                                                           GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3767
3768         return MONO_TOKEN_STRING | idx;
3769 }
3770
3771 /*
3772  * mono_image_create_token:
3773  * @assembly: a dynamic assembly
3774  * @obj:
3775  *
3776  * Get a token to insert in the IL code stream for the given MemberInfo.
3777  * @obj can be one of:
3778  *      ConstructorBuilder
3779  *      MethodBuilder
3780  *      FieldBuilder
3781  *      MonoCMethod
3782  *      MonoMethod
3783  *      MonoField
3784  *      MonoType
3785  *      TypeBuilder
3786  */
3787 guint32
3788 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3789 {
3790         MonoClass *klass;
3791         guint32 token = 0;
3792
3793         klass = obj->vtable->klass;
3794         if (strcmp (klass->name, "MethodBuilder") == 0) {
3795                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3796
3797                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3798                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3799                 else
3800                         token = mono_image_get_methodbuilder_token (assembly, mb);
3801                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3802         }
3803         else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3804                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3805
3806                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3807                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3808                 else
3809                         token = mono_image_get_ctorbuilder_token (assembly, mb);
3810                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3811         }
3812         else if (strcmp (klass->name, "FieldBuilder") == 0) {
3813                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3814                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3815                 if (tb->generic_params) {
3816                         token = mono_image_get_generic_field_token (assembly, fb);
3817                 } else {
3818                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3819                 }
3820         }
3821         else if (strcmp (klass->name, "TypeBuilder") == 0) {
3822                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3823                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3824         }
3825         else if (strcmp (klass->name, "MonoType") == 0 ||
3826                  strcmp (klass->name, "MonoGenericParam") == 0) {
3827                 MonoReflectionType *tb = (MonoReflectionType *)obj;
3828                 token = mono_metadata_token_from_dor (
3829                         mono_image_typedef_or_ref (assembly, tb->type));
3830         }
3831         else if (strcmp (klass->name, "MonoGenericInst") == 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, "MonoCMethod") == 0 ||
3837                         strcmp (klass->name, "MonoMethod") == 0) {
3838                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3839                 if (m->method->signature->is_inflated) {
3840                         token = mono_image_get_methodspec_token (assembly, m->method);
3841                 } else if (m->method->signature->generic_param_count) {
3842                         g_assert_not_reached ();
3843                 } else if ((m->method->klass->image == &assembly->image) &&
3844                          !m->method->klass->generic_inst) {
3845                         static guint32 method_table_idx = 0xffffff;
3846                         /*
3847                          * Each token should have a unique index, but the indexes are
3848                          * assigned by managed code, so we don't know about them. An
3849                          * easy solution is to count backwards...
3850                          */
3851                         method_table_idx --;
3852                         token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3853                 } else
3854                         token = mono_image_get_methodref_token (assembly, m->method);
3855                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3856         }
3857         else if (strcmp (klass->name, "MonoField") == 0) {
3858                 MonoReflectionField *f = (MonoReflectionField *)obj;
3859                 if ((f->klass->image == &assembly->image) && !f->field->generic_type) {
3860                         static guint32 field_table_idx = 0xffffff;
3861                         field_table_idx --;
3862                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3863                 } else
3864                         token = mono_image_get_fieldref_token (assembly, f);
3865                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3866         }
3867         else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3868                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3869                 token = mono_image_get_array_token (assembly, m);
3870         }
3871         else if (strcmp (klass->name, "SignatureHelper") == 0) {
3872                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3873                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3874         }
3875         else
3876                 g_error ("requested token for %s\n", klass->name);
3877
3878         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3879                                                           obj);
3880
3881         return token;
3882 }
3883
3884 typedef struct {
3885         guint32 import_lookup_table;
3886         guint32 timestamp;
3887         guint32 forwarder;
3888         guint32 name_rva;
3889         guint32 import_address_table_rva;
3890 } MonoIDT;
3891
3892 typedef struct {
3893         guint32 name_rva;
3894         guint32 flags;
3895 } MonoILT;
3896
3897 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3898
3899 static MonoDynamicImage*
3900 create_dynamic_mono_image (MonoDynamicAssembly *assembly, 
3901                                                    char *assembly_name, char *module_name)
3902 {
3903         static const guchar entrycode [16] = {0xff, 0x25, 0};
3904         MonoDynamicImage *image;
3905         int i;
3906
3907         /*
3908          * We need to use the current ms version or the ms runtime it won't find
3909          * the support dlls. D'oh!
3910          * const char *version = "mono-" VERSION;
3911          */
3912         const char *version = "v1.0.3705";
3913
3914 #if HAVE_BOEHM_GC
3915         image = GC_MALLOC (sizeof (MonoDynamicImage));
3916 #else
3917         image = g_new0 (MonoDynamicImage, 1);
3918 #endif
3919
3920         /* keep in sync with image.c */
3921         image->image.name = assembly_name;
3922         image->image.assembly_name = image->image.name; /* they may be different */
3923         image->image.module_name = module_name;
3924         image->image.version = g_strdup (version);
3925         image->image.dynamic = TRUE;
3926
3927         image->image.references = g_new0 (MonoAssembly*, 1);
3928         image->image.references [0] = NULL;
3929
3930         mono_image_init (&image->image);
3931
3932         image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3933         image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3934         image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3935         image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3936         image->handleref = g_hash_table_new (NULL, NULL);
3937         image->tokens = mono_g_hash_table_new (NULL, NULL);
3938         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3939         image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3940
3941         string_heap_init (&image->sheap);
3942         mono_image_add_stream_data (&image->us, "", 1);
3943         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3944         /* import tables... */
3945         mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
3946         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
3947         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
3948         mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
3949         image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
3950         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
3951         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
3952         stream_data_align (&image->code);
3953
3954         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
3955
3956         for (i=0; i < 64; ++i) {
3957                 image->tables [i].next_idx = 1;
3958                 image->tables [i].columns = table_sizes [i];
3959         }
3960
3961         image->image.assembly = (MonoAssembly*)assembly;
3962         image->run = assembly->run;
3963         image->save = assembly->save;
3964
3965         return image;
3966 }
3967
3968 /*
3969  * mono_image_basic_init:
3970  * @assembly: an assembly builder object
3971  *
3972  * Create the MonoImage that represents the assembly builder and setup some
3973  * of the helper hash table and the basic metadata streams.
3974  */
3975 void
3976 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
3977 {
3978         MonoDynamicAssembly *assembly;
3979         MonoDynamicImage *image;
3980         
3981         MONO_ARCH_SAVE_REGS;
3982
3983         if (assemblyb->dynamic_assembly)
3984                 return;
3985
3986 #if HAVE_BOEHM_GC
3987         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
3988 #else
3989         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
3990 #endif
3991
3992         assembly->assembly.dynamic = TRUE;
3993         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
3994         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
3995         if (assemblyb->culture)
3996                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
3997         else
3998                 assembly->assembly.aname.culture = g_strdup ("");
3999
4000         assembly->run = assemblyb->access != 2;
4001         assembly->save = assemblyb->access != 1;
4002
4003         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4004         assembly->assembly.aname.name = image->image.name;
4005         assembly->assembly.image = &image->image;
4006
4007         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4008         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4009 }
4010
4011 static int
4012 calc_section_size (MonoDynamicImage *assembly)
4013 {
4014         int nsections = 0;
4015
4016         /* alignment constraints */
4017         assembly->code.index += 3;
4018         assembly->code.index &= ~3;
4019         assembly->meta_size += 3;
4020         assembly->meta_size &= ~3;
4021         assembly->resources.index += 3;
4022         assembly->resources.index &= ~3;
4023
4024         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4025         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4026         nsections++;
4027
4028         if (assembly->win32_res) {
4029                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4030
4031                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4032                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4033                 nsections++;
4034         }
4035
4036         assembly->sections [MONO_SECTION_RELOC].size = 12;
4037         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4038         nsections++;
4039
4040         return nsections;
4041 }
4042
4043 typedef struct {
4044         guint32 id;
4045         guint32 offset;
4046         GSList *children;
4047         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4048 } ResTreeNode;
4049
4050 static int
4051 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4052 {
4053         ResTreeNode *t1 = (ResTreeNode*)a;
4054         ResTreeNode *t2 = (ResTreeNode*)b;
4055
4056         return t1->id - t2->id;
4057 }
4058
4059 /*
4060  * resource_tree_create:
4061  *
4062  *  Organize the resources into a resource tree.
4063  */
4064 static ResTreeNode *
4065 resource_tree_create (MonoArray *win32_resources)
4066 {
4067         ResTreeNode *tree, *res_node, *type_node, *lang_node;
4068         GSList *l;
4069         int i;
4070
4071         tree = g_new0 (ResTreeNode, 1);
4072         
4073         for (i = 0; i < mono_array_length (win32_resources); ++i) {
4074                 MonoReflectionWin32Resource *win32_res =
4075                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4076
4077                 /* Create node */
4078
4079                 lang_node = g_new0 (ResTreeNode, 1);
4080                 lang_node->id = win32_res->lang_id;
4081                 lang_node->win32_res = win32_res;
4082
4083                 /* Create type node if neccesary */
4084                 type_node = NULL;
4085                 for (l = tree->children; l; l = l->next)
4086                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4087                                 type_node = (ResTreeNode*)l->data;
4088                                 break;
4089                         }
4090
4091                 if (!type_node) {
4092                         type_node = g_new0 (ResTreeNode, 1);
4093                         type_node->id = win32_res->res_type;
4094
4095                         /* 
4096                          * The resource types have to be sorted otherwise
4097                          * Windows Explorer can't display the version information.
4098                          */
4099                         tree->children = g_slist_insert_sorted (tree->children, type_node, 
4100                                                                                                         resource_tree_compare_by_id);
4101                 }
4102
4103                 /* Create res node if neccesary */
4104                 res_node = NULL;
4105                 for (l = type_node->children; l; l = l->next)
4106                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4107                                 res_node = (ResTreeNode*)l->data;
4108                                 break;
4109                         }
4110
4111                 if (!res_node) {
4112                         res_node = g_new0 (ResTreeNode, 1);
4113                         res_node->id = win32_res->res_id;
4114                         type_node->children = g_slist_append (type_node->children, res_node);
4115                 }
4116
4117                 res_node->children = g_slist_append (res_node->children, lang_node);
4118         }
4119
4120         return tree;
4121 }
4122
4123 /*
4124  * resource_tree_encode:
4125  * 
4126  *   Encode the resource tree into the format used in the PE file.
4127  */
4128 static void
4129 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4130 {
4131         char *entries;
4132         MonoPEResourceDir dir;
4133         MonoPEResourceDirEntry dir_entry;
4134         MonoPEResourceDataEntry data_entry;
4135         GSList *l;
4136
4137         /*
4138          * For the format of the resource directory, see the article
4139          * "An In-Depth Look into the Win32 Portable Executable File Format" by
4140          * Matt Pietrek
4141          */
4142
4143         memset (&dir, 0, sizeof (dir));
4144         memset (&dir_entry, 0, sizeof (dir_entry));
4145         memset (&data_entry, 0, sizeof (data_entry));
4146
4147         g_assert (sizeof (dir) == 16);
4148         g_assert (sizeof (dir_entry) == 8);
4149         g_assert (sizeof (data_entry) == 16);
4150
4151         node->offset = p - begin;
4152
4153         /* IMAGE_RESOURCE_DIRECTORY */
4154         dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4155
4156         memcpy (p, &dir, sizeof (dir));
4157         p += sizeof (dir);
4158
4159         /* Reserve space for entries */
4160         entries = p;
4161         p += sizeof (dir_entry) * dir.res_id_entries;
4162
4163         /* Write children */
4164         for (l = node->children; l; l = l->next) {
4165                 ResTreeNode *child = (ResTreeNode*)l->data;
4166
4167                 if (child->win32_res) {
4168
4169                         child->offset = p - begin;
4170
4171                         /* IMAGE_RESOURCE_DATA_ENTRY */
4172                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4173                         data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4174
4175                         memcpy (p, &data_entry, sizeof (data_entry));
4176                         p += sizeof (data_entry);
4177
4178                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4179                         p += data_entry.rde_size;
4180                 }
4181                 else
4182                         resource_tree_encode (child, begin, p, &p);
4183         }
4184
4185         /* IMAGE_RESOURCE_ENTRY */
4186         for (l = node->children; l; l = l->next) {
4187                 ResTreeNode *child = (ResTreeNode*)l->data;
4188                 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4189
4190                 dir_entry.is_dir = child->win32_res ? 0 : 1;
4191                 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4192
4193                 memcpy (entries, &dir_entry, sizeof (dir_entry));
4194                 entries += sizeof (dir_entry);
4195         }
4196
4197         *endbuf = p;
4198 }
4199
4200 static void
4201 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4202 {
4203         char *buf;
4204         char *p;
4205         guint32 size, i;
4206         MonoReflectionWin32Resource *win32_res;
4207         ResTreeNode *tree;
4208
4209         if (!assemblyb->win32_resources)
4210                 return;
4211
4212         /*
4213          * Resources are stored in a three level tree inside the PE file.
4214          * - level one contains a node for each type of resource
4215          * - level two contains a node for each resource
4216          * - level three contains a node for each instance of a resource for a
4217          *   specific language.
4218          */
4219
4220         tree = resource_tree_create (assemblyb->win32_resources);
4221
4222         /* Estimate the size of the encoded tree */
4223         size = 0;
4224         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4225                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4226                 size += mono_array_length (win32_res->res_data);
4227         }
4228         /* Directory structure */
4229         size += mono_array_length (assemblyb->win32_resources) * 256;
4230         p = buf = g_malloc (size);
4231
4232         resource_tree_encode (tree, p, p, &p);
4233
4234         g_assert (p - buf < size);
4235
4236         assembly->win32_res = g_malloc (p - buf);
4237         assembly->win32_res_size = p - buf;
4238         memcpy (assembly->win32_res, buf, p - buf);
4239
4240         g_free (buf);
4241 }
4242
4243 static void
4244 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4245 {
4246         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4247         int i;
4248
4249         p += sizeof (MonoPEResourceDir);
4250         for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4251                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4252                 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4253                 if (dir_entry->is_dir)
4254                         fixup_resource_directory (res_section, child, rva);
4255                 else {
4256                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4257                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4258                 }
4259
4260                 p += sizeof (MonoPEResourceDirEntry);
4261         }
4262 }
4263
4264 /*
4265  * mono_image_create_pefile:
4266  * @mb: a module builder object
4267  * 
4268  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
4269  * assembly->pefile where it can be easily retrieved later in chunks.
4270  */
4271 void
4272 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4273         MonoMSDOSHeader *msdos;
4274         MonoDotNetHeader *header;
4275         MonoSectionTable *section;
4276         MonoCLIHeader *cli_header;
4277         guint32 size, image_size, virtual_base, text_offset;
4278         guint32 header_start, section_start, file_offset, virtual_offset;
4279         MonoDynamicImage *assembly;
4280         MonoReflectionAssemblyBuilder *assemblyb;
4281         MonoDynamicStream *pefile;
4282         int i, nsections;
4283         guint32 *rva, value;
4284         guint16 *data16;
4285         guchar *p;
4286         static const unsigned char msheader[] = {
4287                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4288                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4289                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4290                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4291                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4292                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4293                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4294                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4295         };
4296
4297         assemblyb = mb->assemblyb;
4298
4299         mono_image_basic_init (assemblyb);
4300         assembly = mb->dynamic_image;
4301
4302         /* already created */
4303         if (assembly->pefile.index)
4304                 return;
4305         
4306         mono_image_build_metadata (mb);
4307
4308         if (mb->is_main && assemblyb->resources) {
4309                 int len = mono_array_length (assemblyb->resources);
4310                 for (i = 0; i < len; ++i)
4311                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4312         }
4313
4314         if (mb->resources) {
4315                 int len = mono_array_length (mb->resources);
4316                 for (i = 0; i < len; ++i)
4317                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4318         }
4319
4320         build_compressed_metadata (assembly);
4321
4322         if (mb->is_main)
4323                 assembly_add_win32_resources (assembly, assemblyb);
4324
4325         nsections = calc_section_size (assembly);
4326
4327         pefile = &assembly->pefile;
4328
4329         /* The DOS header and stub */
4330         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4331         mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4332
4333         /* the dotnet header */
4334         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4335
4336         /* the section tables */
4337         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4338
4339         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4340         virtual_offset = VIRT_ALIGN;
4341         image_size = 0;
4342
4343         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4344                 if (!assembly->sections [i].size)
4345                         continue;
4346                 /* align offsets */
4347                 file_offset += FILE_ALIGN - 1;
4348                 file_offset &= ~(FILE_ALIGN - 1);
4349                 virtual_offset += VIRT_ALIGN - 1;
4350                 virtual_offset &= ~(VIRT_ALIGN - 1);
4351
4352                 assembly->sections [i].offset = file_offset;
4353                 assembly->sections [i].rva = virtual_offset;
4354
4355                 file_offset += assembly->sections [i].size;
4356                 virtual_offset += assembly->sections [i].size;
4357                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4358         }
4359
4360         file_offset += FILE_ALIGN - 1;
4361         file_offset &= ~(FILE_ALIGN - 1);
4362         mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4363
4364         image_size += section_start + sizeof (MonoSectionTable) * nsections;
4365
4366         /* back-patch info */
4367         msdos = (MonoMSDOSHeader*)pefile->data;
4368         msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4369         msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4370         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4371
4372         header = (MonoDotNetHeader*)(pefile->data + header_start);
4373         header->pesig [0] = 'P';
4374         header->pesig [1] = 'E';
4375         
4376         header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4377         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4378         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4379         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4380         if (assemblyb->pekind == 1) {
4381                 /* it's a dll */
4382                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4383         } else {
4384                 /* it's an exe */
4385                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4386         }
4387
4388         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4389
4390         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4391         header->pe.pe_major = 6;
4392         header->pe.pe_minor = 0;
4393         size = assembly->sections [MONO_SECTION_TEXT].size;
4394         size += FILE_ALIGN - 1;
4395         size &= ~(FILE_ALIGN - 1);
4396         header->pe.pe_code_size = GUINT32_FROM_LE(size);
4397         size = assembly->sections [MONO_SECTION_RSRC].size;
4398         size += FILE_ALIGN - 1;
4399         size &= ~(FILE_ALIGN - 1);
4400         header->pe.pe_data_size = GUINT32_FROM_LE(size);
4401         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4402         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4403         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4404         /* pe_rva_entry_point always at the beginning of the text section */
4405         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4406
4407         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4408         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4409         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4410         header->nt.pe_os_major = GUINT16_FROM_LE (4);
4411         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4412         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4413         size = section_start;
4414         size += FILE_ALIGN - 1;
4415         size &= ~(FILE_ALIGN - 1);
4416         header->nt.pe_header_size = GUINT32_FROM_LE (size);
4417         size = image_size;
4418         size += VIRT_ALIGN - 1;
4419         size &= ~(VIRT_ALIGN - 1);
4420         header->nt.pe_image_size = GUINT32_FROM_LE (size);
4421
4422         //
4423         // Translate the PEFileKind value to the value expected by the Windows loader
4424         //
4425         {
4426                 short kind = assemblyb->pekind;
4427
4428                 //
4429                 // PEFileKinds.ConsoleApplication == 2
4430                 // PEFileKinds.WindowApplication == 3
4431                 //
4432                 // need to get:
4433                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4434                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4435                 if (kind == 2)
4436                         kind = 3;
4437                 else if (kind == 3)
4438                         kind = 2;
4439                 
4440                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4441         }    
4442         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4443         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4444         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4445         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4446         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4447         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4448
4449         /* fill data directory entries */
4450
4451         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4452         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4453
4454         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4455         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4456
4457         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4458         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4459         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4460         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4461         /* patch imported function RVA name */
4462         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4463         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4464
4465         /* the import table */
4466         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4467         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4468         /* patch imported dll RVA name and other entries in the dir */
4469         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4470         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4471         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4472         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4473         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4474         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4475
4476         p = (assembly->code.data + assembly->ilt_offset);
4477         value = (assembly->text_rva + assembly->imp_names_offset - 2);
4478         *p++ = (value) & 0xff;
4479         *p++ = (value >> 8) & (0xff);
4480         *p++ = (value >> 16) & (0xff);
4481         *p++ = (value >> 24) & (0xff);
4482
4483         /* the CLI header info */
4484         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4485         cli_header->ch_size = GUINT32_FROM_LE (72);
4486         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4487         cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4488         if (assemblyb->entry_point) {
4489                 guint32 table_idx = 0;
4490                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4491                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4492                         table_idx = methodb->table_idx;
4493                 }
4494                 else
4495                         table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4496                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4497         }                       
4498         else
4499                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4500         /* The embedded managed resources */
4501         text_offset = assembly->text_rva + assembly->code.index;
4502         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4503         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4504         text_offset += assembly->resources.index;
4505         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4506         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4507         text_offset += assembly->meta_size;
4508         if (assembly->strong_name_size) {
4509                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4510                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4511                 text_offset += assembly->strong_name_size;
4512         }
4513
4514         /* write the section tables and section content */
4515         section = (MonoSectionTable*)(pefile->data + section_start);
4516         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4517                 static const char *section_names [] = {
4518                         ".text", ".rsrc", ".reloc"
4519                 };
4520                 if (!assembly->sections [i].size)
4521                         continue;
4522                 strcpy (section->st_name, section_names [i]);
4523                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4524                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4525                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4526                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4527                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4528                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4529                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4530                 switch (i) {
4531                 case MONO_SECTION_TEXT:
4532                         /* patch entry point */
4533                         p = (assembly->code.data + 2);
4534                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4535                         *p++ = (value) & 0xff;
4536                         *p++ = (value >> 8) & 0xff;
4537                         *p++ = (value >> 16) & 0xff;
4538                         *p++ = (value >> 24) & 0xff;
4539
4540                         text_offset = assembly->sections [i].offset;
4541                         memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4542                         text_offset += assembly->code.index;
4543                         memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4544                         text_offset += assembly->resources.index;
4545                         memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4546                         text_offset += assembly->meta_size;
4547                         memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4548
4549                         g_free (assembly->image.raw_metadata);
4550                         break;
4551                 case MONO_SECTION_RELOC:
4552                         rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4553                         *rva = GUINT32_FROM_LE (assembly->text_rva);
4554                         ++rva;
4555                         *rva = GUINT32_FROM_LE (12);
4556                         ++rva;
4557                         data16 = (guint16*)rva;
4558                         /* 
4559                          * the entrypoint is always at the start of the text section 
4560                          * 3 is IMAGE_REL_BASED_HIGHLOW
4561                          * 2 is patch_size_rva - text_rva
4562                          */
4563                         *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4564                         data16++;
4565                         *data16 = 0; /* terminate */
4566                         break;
4567                 case MONO_SECTION_RSRC:
4568                         if (assembly->win32_res) {
4569                                 text_offset = assembly->sections [i].offset;
4570
4571                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4572                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4573
4574                                 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4575                         }
4576                         break;
4577                 default:
4578                         g_assert_not_reached ();
4579                 }
4580                 section++;
4581         }
4582         
4583         /* check that the file is properly padded */
4584 #if 0
4585         {
4586                 FILE *f = fopen ("mypetest.exe", "w");
4587                 fwrite (pefile->data, pefile->index, 1, f);
4588                 fclose (f);
4589         }
4590 #endif
4591 }
4592
4593 MonoReflectionModule *
4594 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4595 {
4596         char *name;
4597         MonoImage *image;
4598         MonoImageOpenStatus status;
4599         MonoDynamicAssembly *assembly;
4600         
4601         name = mono_string_to_utf8 (fileName);
4602
4603         image = mono_image_open (name, &status);
4604         if (status) {
4605                 MonoException *exc;
4606                 if (status == MONO_IMAGE_ERROR_ERRNO)
4607                         exc = mono_get_exception_file_not_found (fileName);
4608                 else
4609                         exc = mono_get_exception_bad_image_format (name);
4610                 g_free (name);
4611                 mono_raise_exception (exc);
4612         }
4613
4614         g_free (name);
4615
4616         assembly = ab->dynamic_assembly;
4617         image->assembly = (MonoAssembly*)assembly;
4618
4619         mono_assembly_load_references (image, &status);
4620         if (status) {
4621                 mono_image_close (image);
4622                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4623         }
4624
4625         return mono_module_get_object (mono_domain_get (), image);
4626 }
4627
4628 /*
4629  * We need to return always the same object for MethodInfo, FieldInfo etc..
4630  * but we need to consider the reflected type.
4631  * type uses a different hash, since it uses custom hash/equal functions.
4632  */
4633
4634 typedef struct {
4635         gpointer item;
4636         MonoClass *refclass;
4637 } ReflectedEntry;
4638
4639 static gboolean
4640 reflected_equal (gconstpointer a, gconstpointer b) {
4641         const ReflectedEntry *ea = a;
4642         const ReflectedEntry *eb = b;
4643
4644         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4645 }
4646
4647 static guint
4648 reflected_hash (gconstpointer a) {
4649         const ReflectedEntry *ea = a;
4650         return GPOINTER_TO_UINT (ea->item);
4651 }
4652
4653 #define CHECK_OBJECT(t,p,k)     \
4654         do {    \
4655                 t _obj; \
4656                 ReflectedEntry e;       \
4657                 e.item = (p);   \
4658                 e.refclass = (k);       \
4659                 mono_domain_lock (domain);      \
4660                 if (!domain->refobject_hash)    \
4661                         domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);       \
4662                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
4663                         mono_domain_unlock (domain);    \
4664                         return _obj;    \
4665                 }       \
4666         } while (0)
4667
4668 #if HAVE_BOEHM_GC
4669 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4670 #else
4671 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4672 #endif
4673
4674 #define CACHE_OBJECT(p,o,k)     \
4675         do {    \
4676                 ReflectedEntry *e = ALLOC_REFENTRY;     \
4677                 e->item = (p);  \
4678                 e->refclass = (k);      \
4679                 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4680                 mono_domain_unlock (domain);    \
4681         } while (0)
4682
4683 static void 
4684 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4685 {
4686         /* this is done only once */
4687         mono_domain_lock (domain);
4688         CACHE_OBJECT (assembly, res, NULL);
4689 }
4690
4691 static void
4692 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4693 {
4694         /* this is done only once */
4695         mono_domain_lock (domain);
4696         CACHE_OBJECT (module, res, NULL);
4697 }
4698
4699 void
4700 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4701 {
4702         MonoDynamicImage *image = moduleb->dynamic_image;
4703         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4704         if (!image) {
4705                 /*
4706                  * FIXME: we already created an image in mono_image_basic_init (), but
4707                  * we don't know which module it belongs to, since that is only 
4708                  * determined at assembly save time.
4709                  */
4710                 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4711                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4712
4713                 moduleb->module.image = &image->image;
4714                 moduleb->dynamic_image = image;
4715                 register_module (mono_object_domain (moduleb), moduleb, image);
4716         }
4717 }
4718
4719 /*
4720  * mono_assembly_get_object:
4721  * @domain: an app domain
4722  * @assembly: an assembly
4723  *
4724  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4725  */
4726 MonoReflectionAssembly*
4727 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4728 {
4729         static MonoClass *System_Reflection_Assembly;
4730         MonoReflectionAssembly *res;
4731         
4732         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4733         if (!System_Reflection_Assembly)
4734                 System_Reflection_Assembly = mono_class_from_name (
4735                         mono_defaults.corlib, "System.Reflection", "Assembly");
4736         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4737         res->assembly = assembly;
4738         CACHE_OBJECT (assembly, res, NULL);
4739         return res;
4740 }
4741
4742
4743
4744 MonoReflectionModule*   
4745 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
4746 {
4747         static MonoClass *System_Reflection_Module;
4748         MonoReflectionModule *res;
4749         
4750         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4751         if (!System_Reflection_Module)
4752                 System_Reflection_Module = mono_class_from_name (
4753                         mono_defaults.corlib, "System.Reflection", "Module");
4754         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4755
4756         res->image = image;
4757         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4758
4759         res->fqname    = mono_string_new (domain, image->name);
4760         res->name      = mono_string_new (domain, g_path_get_basename (image->name));
4761         res->scopename = mono_string_new (domain, image->module_name);
4762
4763         mono_image_addref (image);
4764
4765         CACHE_OBJECT (image, res, NULL);
4766         return res;
4767 }
4768
4769 MonoReflectionModule*   
4770 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4771 {
4772         static MonoClass *System_Reflection_Module;
4773         MonoReflectionModule *res;
4774         MonoTableInfo *table;
4775         guint32 cols [MONO_FILE_SIZE];
4776         const char *name;
4777         guint32 i, name_idx;
4778         const char *val;
4779         
4780         if (!System_Reflection_Module)
4781                 System_Reflection_Module = mono_class_from_name (
4782                         mono_defaults.corlib, "System.Reflection", "Module");
4783         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4784
4785         table = &image->tables [MONO_TABLE_FILE];
4786         g_assert (table_index < table->rows);
4787         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4788
4789         res->image = 0;
4790         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4791         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4792
4793         // Check whenever the row has a corresponding row in the moduleref table
4794         table = &image->tables [MONO_TABLE_MODULEREF];
4795         for (i = 0; i < table->rows; ++i) {
4796                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4797                 val = mono_metadata_string_heap (image, name_idx);
4798                 if (strcmp (val, name) == 0)
4799                         res->image = image->modules [i];
4800         }
4801
4802         res->fqname    = mono_string_new (domain, name);
4803         res->name      = mono_string_new (domain, name);
4804         res->scopename = mono_string_new (domain, name);
4805         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4806
4807         return res;
4808 }
4809
4810 static gboolean
4811 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4812 {
4813         if ((t1->type != t2->type) ||
4814             (t1->byref != t2->byref))
4815                 return FALSE;
4816
4817         switch (t1->type) {
4818         case MONO_TYPE_VOID:
4819         case MONO_TYPE_BOOLEAN:
4820         case MONO_TYPE_CHAR:
4821         case MONO_TYPE_I1:
4822         case MONO_TYPE_U1:
4823         case MONO_TYPE_I2:
4824         case MONO_TYPE_U2:
4825         case MONO_TYPE_I4:
4826         case MONO_TYPE_U4:
4827         case MONO_TYPE_I8:
4828         case MONO_TYPE_U8:
4829         case MONO_TYPE_R4:
4830         case MONO_TYPE_R8:
4831         case MONO_TYPE_STRING:
4832         case MONO_TYPE_I:
4833         case MONO_TYPE_U:
4834         case MONO_TYPE_OBJECT:
4835         case MONO_TYPE_TYPEDBYREF:
4836                 return TRUE;
4837         case MONO_TYPE_VALUETYPE:
4838         case MONO_TYPE_CLASS:
4839         case MONO_TYPE_SZARRAY:
4840                 return t1->data.klass == t2->data.klass;
4841         case MONO_TYPE_PTR:
4842                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4843         case MONO_TYPE_ARRAY:
4844                 if (t1->data.array->rank != t2->data.array->rank)
4845                         return FALSE;
4846                 return t1->data.array->eklass == t2->data.array->eklass;
4847         case MONO_TYPE_GENERICINST: {
4848                 int i;
4849                 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4850                         return FALSE;
4851                 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4852                         return FALSE;
4853                 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4854                         if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4855                                 return FALSE;
4856                 }
4857                 return TRUE;
4858         }
4859         case MONO_TYPE_VAR:
4860         case MONO_TYPE_MVAR:
4861                 return t1->data.generic_param == t2->data.generic_param;
4862         default:
4863                 g_error ("implement type compare for %0x!", t1->type);
4864                 return FALSE;
4865         }
4866
4867         return FALSE;
4868 }
4869
4870 static guint
4871 mymono_metadata_type_hash (MonoType *t1)
4872 {
4873         guint hash;
4874
4875         hash = t1->type;
4876
4877         hash |= t1->byref << 6; /* do not collide with t1->type values */
4878         switch (t1->type) {
4879         case MONO_TYPE_VALUETYPE:
4880         case MONO_TYPE_CLASS:
4881         case MONO_TYPE_SZARRAY:
4882                 /* check if the distribution is good enough */
4883                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4884         case MONO_TYPE_PTR:
4885                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4886         }
4887         return hash;
4888 }
4889
4890 static MonoReflectionGenericInst*
4891 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
4892 {
4893         static MonoClass *System_Reflection_MonoGenericInst;
4894         MonoReflectionGenericInst *res;
4895         MonoGenericInst *ginst;
4896         MonoClass *gklass;
4897
4898         if (!System_Reflection_MonoGenericInst) {
4899                 System_Reflection_MonoGenericInst = mono_class_from_name (
4900                         mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
4901                 g_assert (System_Reflection_MonoGenericInst);
4902         }
4903
4904         ginst = geninst->data.generic_inst;
4905         gklass = mono_class_from_mono_type (ginst->generic_type);
4906
4907         mono_class_init (ginst->klass);
4908
4909         res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
4910
4911         res->type.type = geninst;
4912         if (gklass->wastypebuilder && gklass->reflection_info)
4913                 res->generic_type = gklass->reflection_info;
4914         else
4915                 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
4916
4917         return res;
4918 }
4919
4920 /*
4921  * mono_type_get_object:
4922  * @domain: an app domain
4923  * @type: a type
4924  *
4925  * Return an System.MonoType object representing the type @type.
4926  */
4927 MonoReflectionType*
4928 mono_type_get_object (MonoDomain *domain, MonoType *type)
4929 {
4930         MonoReflectionType *res;
4931         MonoClass *klass = mono_class_from_mono_type (type);
4932
4933         mono_domain_lock (domain);
4934         if (!domain->type_hash)
4935                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
4936                                 (GCompareFunc)mymono_metadata_type_equal);
4937         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4938                 mono_domain_unlock (domain);
4939                 return res;
4940         }
4941         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
4942                 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
4943                 mono_g_hash_table_insert (domain->type_hash, type, res);
4944                 mono_domain_unlock (domain);
4945                 return res;
4946         }
4947         if (klass->reflection_info && !klass->wastypebuilder) {
4948                 //g_assert_not_reached ();
4949                 /* should this be considered an error condition? */
4950                 if (!type->byref) {
4951                         mono_domain_unlock (domain);
4952                         return klass->reflection_info;
4953                 }
4954         }
4955         mono_class_init (klass);
4956         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
4957         res->type = type;
4958         mono_g_hash_table_insert (domain->type_hash, type, res);
4959         mono_domain_unlock (domain);
4960         return res;
4961 }
4962
4963 /*
4964  * mono_method_get_object:
4965  * @domain: an app domain
4966  * @method: a method
4967  * @refclass: the reflected type (can be NULL)
4968  *
4969  * Return an System.Reflection.MonoMethod object representing the method @method.
4970  */
4971 MonoReflectionMethod*
4972 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
4973 {
4974         /*
4975          * We use the same C representation for methods and constructors, but the type 
4976          * name in C# is different.
4977          */
4978         const char *cname;
4979         MonoClass *klass;
4980         MonoReflectionMethod *ret;
4981
4982         if (!refclass)
4983                 refclass = method->klass;
4984
4985         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
4986         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
4987                 cname = "MonoCMethod";
4988         else
4989                 cname = "MonoMethod";
4990         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
4991
4992         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
4993         ret->method = method;
4994         ret->name = mono_string_new (domain, method->name);
4995         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
4996         CACHE_OBJECT (method, ret, refclass);
4997         return ret;
4998 }
4999
5000 /*
5001  * mono_field_get_object:
5002  * @domain: an app domain
5003  * @klass: a type
5004  * @field: a field
5005  *
5006  * Return an System.Reflection.MonoField object representing the field @field
5007  * in class @klass.
5008  */
5009 MonoReflectionField*
5010 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5011 {
5012         MonoReflectionField *res;
5013         MonoClass *oklass;
5014
5015         CHECK_OBJECT (MonoReflectionField *, field, klass);
5016         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5017         res = (MonoReflectionField *)mono_object_new (domain, oklass);
5018         res->klass = klass;
5019         res->field = field;
5020         res->name = mono_string_new (domain, field->name);
5021         res->attrs = field->type->attrs;
5022         res->type = mono_type_get_object (domain, field->type);
5023         CACHE_OBJECT (field, res, klass);
5024         return res;
5025 }
5026
5027 /*
5028  * mono_property_get_object:
5029  * @domain: an app domain
5030  * @klass: a type
5031  * @property: a property
5032  *
5033  * Return an System.Reflection.MonoProperty object representing the property @property
5034  * in class @klass.
5035  */
5036 MonoReflectionProperty*
5037 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5038 {
5039         MonoReflectionProperty *res;
5040         MonoClass *oklass;
5041
5042         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5043         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5044         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5045         res->klass = klass;
5046         res->property = property;
5047         CACHE_OBJECT (property, res, klass);
5048         return res;
5049 }
5050
5051 /*
5052  * mono_event_get_object:
5053  * @domain: an app domain
5054  * @klass: a type
5055  * @event: a event
5056  *
5057  * Return an System.Reflection.MonoEvent object representing the event @event
5058  * in class @klass.
5059  */
5060 MonoReflectionEvent*
5061 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5062 {
5063         MonoReflectionEvent *res;
5064         MonoClass *oklass;
5065
5066         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5067         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5068         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5069         res->klass = klass;
5070         res->event = event;
5071         CACHE_OBJECT (event, res, klass);
5072         return res;
5073 }
5074
5075 /*
5076  * mono_param_get_objects:
5077  * @domain: an app domain
5078  * @method: a method
5079  *
5080  * Return an System.Reflection.ParameterInfo array object representing the parameters
5081  * in the method @method.
5082  */
5083 MonoArray*
5084 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5085 {
5086         static MonoClass *System_Reflection_ParameterInfo;
5087         MonoArray *res = NULL;
5088         MonoReflectionMethod *member = NULL;
5089         MonoReflectionParameter *param = NULL;
5090         char **names;
5091         int i;
5092
5093         if (!System_Reflection_ParameterInfo)
5094                 System_Reflection_ParameterInfo = mono_class_from_name (
5095                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5096         
5097         if (!method->signature->param_count)
5098                 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5099
5100         /* Note: the cache is based on the address of the signature into the method
5101          * since we already cache MethodInfos with the method as keys.
5102          */
5103         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5104
5105         member = mono_method_get_object (domain, method, NULL);
5106         names = g_new (char *, method->signature->param_count);
5107         mono_method_get_param_names (method, (const char **) names);
5108
5109         res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5110         for (i = 0; i < method->signature->param_count; ++i) {
5111                 param = (MonoReflectionParameter *)mono_object_new (domain, 
5112                                                                                                                         System_Reflection_ParameterInfo);
5113                 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5114                 param->DefaultValueImpl = NULL; /* FIXME */
5115                 param->MemberImpl = (MonoObject*)member;
5116                 param->NameImpl = mono_string_new (domain, names [i]);
5117                 param->PositionImpl = i;
5118                 param->AttrsImpl = method->signature->params [i]->attrs;
5119                 mono_array_set (res, gpointer, i, param);
5120         }
5121         g_free (names);
5122         CACHE_OBJECT (&(method->signature), res, NULL);
5123         return res;
5124 }
5125
5126 static int
5127 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5128         int found_sep;
5129         char *s;
5130
5131         memset (assembly, 0, sizeof (MonoAssemblyName));
5132         assembly->name = p;
5133         assembly->culture = "";
5134         
5135         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5136                 p++;
5137         found_sep = 0;
5138         while (*p == ' ' || *p == ',') {
5139                 *p++ = 0;
5140                 found_sep = 1;
5141                 continue;
5142         }
5143         /* failed */
5144         if (!found_sep)
5145                 return 1;
5146         while (*p) {
5147                 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
5148                         p += 8;
5149                         assembly->major = strtoul (p, &s, 10);
5150                         if (s == p || *s != '.')
5151                                 return 1;
5152                         p = ++s;
5153                         assembly->minor = strtoul (p, &s, 10);
5154                         if (s == p || *s != '.')
5155                                 return 1;
5156                         p = ++s;
5157                         assembly->build = strtoul (p, &s, 10);
5158                         if (s == p || *s != '.')
5159                                 return 1;
5160                         p = ++s;
5161                         assembly->revision = strtoul (p, &s, 10);
5162                         if (s == p)
5163                                 return 1;
5164                 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
5165                         p += 8;
5166                         if (strncmp (p, "neutral", 7) == 0) {
5167                                 assembly->culture = "";
5168                                 p += 7;
5169                         } else {
5170                                 assembly->culture = p;
5171                                 while (*p && *p != ',') {
5172                                         p++;
5173                                 }
5174                         }
5175                 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
5176                         p += 15;
5177                         s = p;
5178                         while (*s && isxdigit (*s)) {
5179                                 *s = tolower (*s);
5180                                 s++;
5181                         }
5182                         assembly->hash_len = s - p;
5183                         if (!(s-p) || ((s-p) & 1))
5184                                 return 1;
5185                         assembly->hash_value = s = p;
5186                         while (*s && isxdigit (*s)) {
5187                                 int val;
5188                                 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5189                                 s++;
5190                                 *p = val << 4;
5191                                 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5192                                 p++;
5193                         }
5194                         p = s;
5195                 } else {
5196                         while (*p && *p != ',')
5197                                 p++;
5198                 }
5199                 found_sep = 0;
5200                 while (*p == ' ' || *p == ',') {
5201                         *p++ = 0;
5202                         found_sep = 1;
5203                         continue;
5204                 }
5205                 /* failed */
5206                 if (!found_sep)
5207                         return 1;
5208         }
5209
5210         return 0;
5211 }
5212
5213 /*
5214  * mono_reflection_parse_type:
5215  * @name: type name
5216  *
5217  * Parse a type name as accepted by the GetType () method and output the info
5218  * extracted in the info structure.
5219  * the name param will be mangled, so, make a copy before passing it to this function.
5220  * The fields in info will be valid until the memory pointed to by name is valid.
5221  * Returns 0 on parse error.
5222  * See also mono_type_get_name () below.
5223  */
5224 int
5225 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5226
5227         char *start, *p, *w, *last_point, *startn;
5228         int in_modifiers = 0;
5229         int isbyref = 0, rank;
5230
5231         start = p = w = name;
5232
5233         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5234         info->name = info->name_space = NULL;
5235         info->nested = NULL;
5236         info->modifiers = NULL;
5237
5238         /* last_point separates the namespace from the name */
5239         last_point = NULL;
5240
5241         while (*p) {
5242                 switch (*p) {
5243                 case '+':
5244                         *p = 0; /* NULL terminate the name */
5245                         startn = p + 1;
5246                         info->nested = g_list_append (info->nested, startn);
5247                         /* we have parsed the nesting namespace + name */
5248                         if (info->name)
5249                                 break;
5250                         if (last_point) {
5251                                 info->name_space = start;
5252                                 *last_point = 0;
5253                                 info->name = last_point + 1;
5254                         } else {
5255                                 info->name_space = (char *)"";
5256                                 info->name = start;
5257                         }
5258                         break;
5259                 case '.':
5260                         last_point = w;
5261                         break;
5262                 case '\\':
5263                         ++p;
5264                         break;
5265                 case '&':
5266                 case '*':
5267                 case '[':
5268                 case ',':
5269                         in_modifiers = 1;
5270                         break;
5271                 default:
5272                         break;
5273                 }
5274                 if (in_modifiers)
5275                         break;
5276                 *w++ = *p++;
5277         }
5278         
5279         if (!info->name) {
5280                 if (last_point) {
5281                         info->name_space = start;
5282                         *last_point = 0;
5283                         info->name = last_point + 1;
5284                 } else {
5285                         info->name_space = (char *)"";
5286                         info->name = start;
5287                 }
5288         }
5289         while (*p) {
5290                 switch (*p) {
5291                 case '&':
5292                         if (isbyref) /* only one level allowed by the spec */
5293                                 return 0;
5294                         isbyref = 1;
5295                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5296                         *p++ = 0;
5297                         break;
5298                 case '*':
5299                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5300                         *p++ = 0;
5301                         break;
5302                 case '[':
5303                         rank = 1;
5304                         *p++ = 0;
5305                         while (*p) {
5306                                 if (*p == ']')
5307                                         break;
5308                                 if (*p == ',')
5309                                         rank++;
5310                                 else if (*p != '*') /* '*' means unknown lower bound */
5311                                         return 0;
5312                                 ++p;
5313                         }
5314                         if (*p++ != ']')
5315                                 return 0;
5316                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5317                         break;
5318                 case ',':
5319                         *p++ = 0;
5320                         while (*p) {
5321                                 if (*p == ' ') {
5322                                         ++p;
5323                                         continue;
5324                                 }
5325                                 break;
5326                         }
5327                         if (!*p)
5328                                 return 0; /* missing assembly name */
5329                         if (!assembly_name_to_aname (&info->assembly, p))
5330                                 return 0;
5331                         break;
5332                 default:
5333                         return 0;
5334                         break;
5335                 }
5336                 if (info->assembly.name)
5337                         break;
5338         }
5339         *w = 0; /* terminate class name */
5340         if (!info->name || !*info->name)
5341                 return 0;
5342         /* add other consistency checks */
5343         return 1;
5344 }
5345
5346 static MonoType*
5347 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5348 {
5349         MonoClass *klass;
5350         GList *mod;
5351         int modval;
5352         
5353         if (!image)
5354                 image = mono_defaults.corlib;
5355
5356         if (ignorecase)
5357                 klass = mono_class_from_name_case (image, info->name_space, info->name);
5358         else
5359                 klass = mono_class_from_name (image, info->name_space, info->name);
5360         if (!klass)
5361                 return NULL;
5362         for (mod = info->nested; mod; mod = mod->next) {
5363                 GList *nested;
5364
5365                 mono_class_init (klass);
5366                 nested = klass->nested_classes;
5367                 klass = NULL;
5368                 while (nested) {
5369                         klass = nested->data;
5370                         if (ignorecase) {
5371                                 if (g_strcasecmp (klass->name, mod->data) == 0)
5372                                         break;
5373                         } else {
5374                                 if (strcmp (klass->name, mod->data) == 0)
5375                                         break;
5376                         }
5377                         klass = NULL;
5378                         nested = nested->next;
5379                 }
5380                 if (!klass)
5381                         break;
5382         }
5383         if (!klass)
5384                 return NULL;
5385         mono_class_init (klass);
5386         for (mod = info->modifiers; mod; mod = mod->next) {
5387                 modval = GPOINTER_TO_UINT (mod->data);
5388                 if (!modval) { /* byref: must be last modifier */
5389                         return &klass->this_arg;
5390                 } else if (modval == -1) {
5391                         klass = mono_ptr_class_get (&klass->byval_arg);
5392                 } else { /* array rank */
5393                         klass = mono_array_class_get (klass, modval);
5394                 }
5395                 mono_class_init (klass);
5396         }
5397
5398         return &klass->byval_arg;
5399 }
5400
5401 /*
5402  * mono_reflection_get_type:
5403  * @image: a metadata context
5404  * @info: type description structure
5405  * @ignorecase: flag for case-insensitive string compares
5406  *
5407  * Build a MonoType from the type description in @info.
5408  * 
5409  */
5410
5411 MonoType*
5412 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5413 {
5414         MonoType *type;
5415         MonoReflectionAssembly *assembly;
5416         GString *fullName;
5417         GList *mod;
5418
5419         type = mono_reflection_get_type_internal (image, info, ignorecase);
5420         if (type)
5421                 return type;
5422         if (!mono_domain_has_type_resolve (mono_domain_get ()))
5423                 return NULL;
5424         
5425         // Reconstruct the type name
5426         fullName = g_string_new ("");
5427         if (info->name_space && (info->name_space [0] != '\0'))
5428                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5429         else
5430                 g_string_printf (fullName, info->name);
5431         for (mod = info->nested; mod; mod = mod->next)
5432                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5433
5434         assembly = 
5435                 mono_domain_try_type_resolve (
5436                         mono_domain_get (), fullName->str, NULL);
5437         if (assembly && (!image || (assembly->assembly->image == image)))
5438                 type = mono_reflection_get_type_internal (assembly->assembly->image, 
5439                                                                                  info, ignorecase);
5440         g_string_free (fullName, TRUE);
5441         return type;
5442 }
5443
5444 /*
5445  * mono_reflection_type_from_name:
5446  * @name: type name.
5447  * @image: a metadata context (can be NULL).
5448  *
5449  * Retrieves a MonoType from its @name. If the name is not fully qualified,
5450  * it defaults to get the type from @image or, if @image is NULL or loading
5451  * from it fails, uses corlib.
5452  * 
5453  */
5454 MonoType*
5455 mono_reflection_type_from_name (char *name, MonoImage *image)
5456 {
5457         MonoType *type;
5458         MonoTypeNameParse info;
5459         MonoAssembly *assembly;
5460         
5461         /*g_print ("requested type %s\n", str);*/
5462         if (!mono_reflection_parse_type (name, &info)) {
5463                 g_list_free (info.modifiers);
5464                 g_list_free (info.nested);
5465                 return NULL;
5466         }
5467
5468         if (info.assembly.name) {
5469                 assembly = mono_assembly_loaded (&info.assembly);
5470                 /* do we need to load if it's not already loaded? */
5471                 if (!assembly) {
5472                         g_list_free (info.modifiers);
5473                         g_list_free (info.nested);
5474                         return NULL;
5475                 }
5476                 else
5477                         image = assembly->image;
5478         } else if (image == NULL) {
5479                 image = mono_defaults.corlib;
5480         }
5481
5482         type = mono_reflection_get_type (image, &info, FALSE);
5483         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5484                 image = mono_defaults.corlib;
5485                 type = mono_reflection_get_type (image, &info, FALSE);
5486         }
5487         
5488         g_list_free (info.modifiers);
5489         g_list_free (info.nested);
5490         return type;
5491 }
5492
5493 static void*
5494 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5495 {
5496         int slen, type = t->type;
5497 handle_enum:
5498         switch (type) {
5499         case MONO_TYPE_U1:
5500         case MONO_TYPE_I1:
5501         case MONO_TYPE_BOOLEAN: {
5502                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5503                 *bval = *p;
5504                 *end = p + 1;
5505                 return bval;
5506         }
5507         case MONO_TYPE_CHAR:
5508         case MONO_TYPE_U2:
5509         case MONO_TYPE_I2: {
5510                 guint16 *val = g_malloc (sizeof (guint16));
5511                 *val = read16 (p);
5512                 *end = p + 2;
5513                 return val;
5514         }
5515 #if SIZEOF_VOID_P == 4
5516         case MONO_TYPE_U:
5517         case MONO_TYPE_I:
5518 #endif
5519         case MONO_TYPE_R4:
5520         case MONO_TYPE_U4:
5521         case MONO_TYPE_I4: {
5522                 guint32 *val = g_malloc (sizeof (guint32));
5523                 *val = read32 (p);
5524                 *end = p + 4;
5525                 return val;
5526         }
5527 #if SIZEOF_VOID_P == 8
5528         case MONO_TYPE_U: /* error out instead? this should probably not happen */
5529         case MONO_TYPE_I:
5530 #endif
5531         case MONO_TYPE_R8:
5532         case MONO_TYPE_U8:
5533         case MONO_TYPE_I8: {
5534                 guint64 *val = g_malloc (sizeof (guint64));
5535                 *val = read64 (p);
5536                 *end = p + 8;
5537                 return val;
5538         }
5539         case MONO_TYPE_VALUETYPE:
5540                 if (t->data.klass->enumtype) {
5541                         type = t->data.klass->enum_basetype->type;
5542                         goto handle_enum;
5543                 } else {
5544                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5545                 }
5546                 break;
5547         case MONO_TYPE_STRING:
5548                 if (*p == (char)0xFF) {
5549                         *end = p + 1;
5550                         return NULL;
5551                 }
5552                 slen = mono_metadata_decode_value (p, &p);
5553                 *end = p + slen;
5554                 return mono_string_new_len (mono_domain_get (), p, slen);
5555         case MONO_TYPE_CLASS: {
5556                 char *n;
5557                 MonoType *t;
5558                 if (*p == (char)0xFF) {
5559                         *end = p + 1;
5560                         return NULL;
5561                 }
5562 handle_type:
5563                 slen = mono_metadata_decode_value (p, &p);
5564                 n = g_memdup (p, slen + 1);
5565                 n [slen] = 0;
5566                 t = mono_reflection_type_from_name (n, image);
5567                 if (!t)
5568                         g_warning ("Cannot load type '%s'", n);
5569                 g_free (n);
5570                 *end = p + slen;
5571                 if (t)
5572                         return mono_type_get_object (mono_domain_get (), t);
5573                 else
5574                         return NULL;
5575         }
5576         case MONO_TYPE_OBJECT: {
5577                 char subt = *p++;
5578                 MonoObject *obj;
5579                 MonoClass *subc = NULL;
5580                 void *val;
5581
5582                 if (subt == 0x50) {
5583                         goto handle_type;
5584                 } else if (subt == 0x0E) {
5585                         type = MONO_TYPE_STRING;
5586                         goto handle_enum;
5587                 } else if (subt == 0x55) {
5588                         char *n;
5589                         MonoType *t;
5590                         slen = mono_metadata_decode_value (p, &p);
5591                         n = g_memdup (p, slen + 1);
5592                         n [slen] = 0;
5593                         t = mono_reflection_type_from_name (n, image);
5594                         if (!t)
5595                                 g_warning ("Cannot load type '%s'", n);
5596                         g_free (n);
5597                         p += slen;
5598                         subc = mono_class_from_mono_type (t);
5599                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5600                         MonoType simple_type = {{0}};
5601                         simple_type.type = subt;
5602                         subc = mono_class_from_mono_type (&simple_type);
5603                 } else {
5604                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5605                 }
5606                 val = load_cattr_value (image, &subc->byval_arg, p, end);
5607                 obj = mono_object_new (mono_domain_get (), subc);
5608                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5609                 g_free (val);
5610                 return obj;
5611         }
5612         case MONO_TYPE_SZARRAY:
5613         {
5614                 MonoArray *arr;
5615                 guint32 i, alen, basetype;
5616                 alen = read32 (p);
5617                 p += 4;
5618                 if (alen == 0xffffffff) {
5619                         *end = p;
5620                         return NULL;
5621                 }
5622                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5623                 basetype = t->data.klass->byval_arg.type;
5624                 switch (basetype)
5625                 {
5626                         case MONO_TYPE_U1:
5627                         case MONO_TYPE_I1:
5628                         case MONO_TYPE_BOOLEAN:
5629                                 for (i=0;i<alen;i++)
5630                                 {
5631                                         MonoBoolean val=*p++;
5632                                         mono_array_set(arr,MonoBoolean,i,val);
5633                                 }
5634                                 break;
5635                         case MONO_TYPE_CHAR:
5636                         case MONO_TYPE_U2:
5637                         case MONO_TYPE_I2:
5638                                 for (i=0;i<alen;i++)
5639                                 {
5640                                         guint16 val=read16(p);
5641                                         mono_array_set(arr,guint16,i,val);
5642                                         p+=2;
5643                                 }
5644                                 break;
5645                         case MONO_TYPE_R4:
5646                         case MONO_TYPE_U4:
5647                         case MONO_TYPE_I4:
5648                                 for (i=0;i<alen;i++)
5649                                 {
5650                                         guint32 val=read32(p);
5651                                         mono_array_set(arr,guint32,i,val);
5652                                         p+=4;
5653                                 }
5654                                 break;
5655                         case MONO_TYPE_R8:
5656                         case MONO_TYPE_U8:
5657                         case MONO_TYPE_I8:
5658                                 for (i=0;i<alen;i++)
5659                                 {
5660                                         guint64 val=read64(p);
5661                                         mono_array_set(arr,guint64,i,val);
5662                                         p+=8;
5663                                 }
5664                                 break;
5665                         case MONO_TYPE_CLASS:
5666                         case MONO_TYPE_STRING:
5667                                 for (i = 0; i < alen; i++) {
5668                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5669                                         mono_array_set (arr, gpointer, i, item);
5670                                 }
5671                                 break;
5672                         default:
5673                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5674                 }
5675                 *end=p;
5676                 return arr;
5677         }
5678         default:
5679                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5680         }
5681         return NULL;
5682 }
5683
5684 static gboolean
5685 type_is_reference (MonoType *type)
5686 {
5687         switch (type->type) {
5688         case MONO_TYPE_BOOLEAN:
5689         case MONO_TYPE_CHAR:
5690         case MONO_TYPE_U:
5691         case MONO_TYPE_I:
5692         case MONO_TYPE_U1:
5693         case MONO_TYPE_I1:
5694         case MONO_TYPE_U2:
5695         case MONO_TYPE_I2:
5696         case MONO_TYPE_U4:
5697         case MONO_TYPE_I4:
5698         case MONO_TYPE_U8:
5699         case MONO_TYPE_I8:
5700         case MONO_TYPE_R8:
5701         case MONO_TYPE_R4:
5702         case MONO_TYPE_VALUETYPE:
5703                 return FALSE;
5704         default:
5705                 return TRUE;
5706         }
5707 }
5708
5709 static void
5710 free_param_data (MonoMethodSignature *sig, void **params) {
5711         int i;
5712         for (i = 0; i < sig->param_count; ++i) {
5713                 if (!type_is_reference (sig->params [i]))
5714                         g_free (params [i]);
5715         }
5716 }
5717
5718 /*
5719  * Find the method index in the metadata methodDef table.
5720  * Later put these three helper methods in metadata and export them.
5721  */
5722 static guint32
5723 find_method_index (MonoMethod *method) {
5724         MonoClass *klass = method->klass;
5725         int i;
5726
5727         for (i = 0; i < klass->method.count; ++i) {
5728                 if (method == klass->methods [i])
5729                         return klass->method.first + 1 + i;
5730         }
5731         return 0;
5732 }
5733
5734 /*
5735  * Find the field index in the metadata FieldDef table.
5736  */
5737 static guint32
5738 find_field_index (MonoClass *klass, MonoClassField *field) {
5739         int i;
5740
5741         for (i = 0; i < klass->field.count; ++i) {
5742                 if (field == &klass->fields [i])
5743                         return klass->field.first + 1 + i;
5744         }
5745         return 0;
5746 }
5747
5748 /*
5749  * Find the property index in the metadata Property table.
5750  */
5751 static guint32
5752 find_property_index (MonoClass *klass, MonoProperty *property) {
5753         int i;
5754
5755         for (i = 0; i < klass->property.count; ++i) {
5756                 if (property == &klass->properties [i])
5757                         return klass->property.first + 1 + i;
5758         }
5759         return 0;
5760 }
5761
5762 /*
5763  * Find the event index in the metadata Event table.
5764  */
5765 static guint32
5766 find_event_index (MonoClass *klass, MonoEvent *event) {
5767         int i;
5768
5769         for (i = 0; i < klass->event.count; ++i) {
5770                 if (event == &klass->events [i])
5771                         return klass->event.first + 1 + i;
5772         }
5773         return 0;
5774 }
5775
5776 static MonoObject*
5777 create_custom_attr (MonoImage *image, MonoMethod *method, 
5778                                         const char *data, guint32 len)
5779 {
5780         const char *p = data;
5781         const char *named;
5782         guint32 i, j, num_named;
5783         MonoObject *attr;
5784         void **params;
5785
5786         mono_class_init (method->klass);
5787
5788         if (len == 0) {
5789                 attr = mono_object_new (mono_domain_get (), method->klass);
5790                 mono_runtime_invoke (method, attr, NULL, NULL);
5791                 return attr;
5792         }
5793
5794         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5795                 return NULL;
5796
5797         /*g_print ("got attr %s\n", method->klass->name);*/
5798         
5799         params = g_new (void*, method->signature->param_count);
5800
5801         /* skip prolog */
5802         p += 2;
5803         for (i = 0; i < method->signature->param_count; ++i) {
5804                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5805         }
5806
5807         named = p;
5808         attr = mono_object_new (mono_domain_get (), method->klass);
5809         mono_runtime_invoke (method, attr, params, NULL);
5810         free_param_data (method->signature, params);
5811         g_free (params);
5812         num_named = read16 (named);
5813         named += 2;
5814         for (j = 0; j < num_named; j++) {
5815                 gint name_len;
5816                 char *name, named_type, data_type;
5817                 named_type = *named++;
5818                 data_type = *named++; /* type of data */
5819                 if (data_type == 0x55) {
5820                         gint type_len;
5821                         char *type_name;
5822                         type_len = mono_metadata_decode_blob_size (named, &named);
5823                         type_name = g_malloc (type_len + 1);
5824                         memcpy (type_name, named, type_len);
5825                         type_name [type_len] = 0;
5826                         named += type_len;
5827                         /* FIXME: lookup the type and check type consistency */
5828                 }
5829                 else
5830                         if (data_type == MONO_TYPE_SZARRAY)
5831                                 /* The spec does not mention this */
5832                                 named ++;
5833                 name_len = mono_metadata_decode_blob_size (named, &named);
5834                 name = g_malloc (name_len + 1);
5835                 memcpy (name, named, name_len);
5836                 name [name_len] = 0;
5837                 named += name_len;
5838                 if (named_type == 0x53) {
5839                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5840                         void *val = load_cattr_value (image, field->type, named, &named);
5841                                 mono_field_set_value (attr, field, val);
5842                                 if (!type_is_reference (field->type))
5843                                         g_free (val);
5844                 } else if (named_type == 0x54) {
5845                         MonoProperty *prop;
5846                         void *pparams [1];
5847                         MonoType *prop_type;
5848
5849                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5850                         /* can we have more that 1 arg in a custom attr named property? */
5851                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5852                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
5853                         mono_property_set_value (prop, attr, pparams, NULL);
5854                         if (!type_is_reference (prop_type))
5855                                 g_free (pparams [0]);
5856                 }
5857                 g_free (name);
5858         }
5859
5860         return attr;
5861 }
5862
5863 MonoArray*
5864 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5865 {
5866         MonoArray *result;
5867         MonoClass *klass;
5868         MonoObject *attr;
5869         int i;
5870
5871         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5872         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5873         for (i = 0; i < cinfo->num_attrs; ++i) {
5874                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5875                 mono_array_set (result, gpointer, i, attr);
5876         }
5877         return result;
5878 }
5879
5880 MonoCustomAttrInfo*
5881 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5882 {
5883         guint32 mtoken, i, len;
5884         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5885         MonoTableInfo *ca;
5886         MonoCustomAttrInfo *ainfo;
5887         GList *tmp, *list = NULL;
5888         const char *data;
5889
5890         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5891
5892         i = mono_metadata_custom_attrs_from_index (image, idx);
5893         if (!i)
5894                 return NULL;
5895         i --;
5896         while (i < ca->rows) {
5897                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5898                         break;
5899                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5900                 ++i;
5901         }
5902         len = g_list_length (list);
5903         if (!len)
5904                 return NULL;
5905         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5906         ainfo->num_attrs = len;
5907         ainfo->image = image;
5908         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5909                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5910                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5911                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5912                 case CUSTOM_ATTR_TYPE_METHODDEF:
5913                         mtoken |= MONO_TOKEN_METHOD_DEF;
5914                         break;
5915                 case CUSTOM_ATTR_TYPE_MEMBERREF:
5916                         mtoken |= MONO_TOKEN_MEMBER_REF;
5917                         break;
5918                 default:
5919                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5920                         break;
5921                 }
5922                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5923                 if (!ainfo->attrs [i].ctor)
5924                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5925                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5926                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5927                 ainfo->attrs [i].data = data;
5928         }
5929         g_list_free (list);
5930
5931         return ainfo;
5932 }
5933
5934 MonoCustomAttrInfo*
5935 mono_custom_attrs_from_method (MonoMethod *method)
5936 {
5937         MonoCustomAttrInfo *cinfo;
5938         guint32 idx;
5939         
5940         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5941                 return cinfo;
5942         idx = find_method_index (method);
5943         idx <<= CUSTOM_ATTR_BITS;
5944         idx |= CUSTOM_ATTR_METHODDEF;
5945         return mono_custom_attrs_from_index (method->klass->image, idx);
5946 }
5947
5948 MonoCustomAttrInfo*
5949 mono_custom_attrs_from_class (MonoClass *klass)
5950 {
5951         MonoCustomAttrInfo *cinfo;
5952         guint32 idx;
5953         
5954         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
5955                 return cinfo;
5956         idx = mono_metadata_token_index (klass->type_token);
5957         idx <<= CUSTOM_ATTR_BITS;
5958         idx |= CUSTOM_ATTR_TYPEDEF;
5959         return mono_custom_attrs_from_index (klass->image, idx);
5960 }
5961
5962 MonoCustomAttrInfo*
5963 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
5964 {
5965         MonoCustomAttrInfo *cinfo;
5966         guint32 idx;
5967         
5968         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
5969                 return cinfo;
5970         idx = 1; /* there is only one assembly */
5971         idx <<= CUSTOM_ATTR_BITS;
5972         idx |= CUSTOM_ATTR_ASSEMBLY;
5973         return mono_custom_attrs_from_index (assembly->image, idx);
5974 }
5975
5976 static MonoCustomAttrInfo*
5977 mono_custom_attrs_from_module (MonoImage *image)
5978 {
5979         MonoCustomAttrInfo *cinfo;
5980         guint32 idx;
5981         
5982         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
5983                 return cinfo;
5984         idx = 1; /* there is only one module */
5985         idx <<= CUSTOM_ATTR_BITS;
5986         idx |= CUSTOM_ATTR_MODULE;
5987         return mono_custom_attrs_from_index (image, idx);
5988 }
5989
5990 MonoCustomAttrInfo*
5991 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
5992 {
5993         MonoCustomAttrInfo *cinfo;
5994         guint32 idx;
5995         
5996         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
5997                 return cinfo;
5998         idx = find_property_index (klass, property);
5999         idx <<= CUSTOM_ATTR_BITS;
6000         idx |= CUSTOM_ATTR_PROPERTY;
6001         return mono_custom_attrs_from_index (klass->image, idx);
6002 }
6003
6004 MonoCustomAttrInfo*
6005 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6006 {
6007         MonoCustomAttrInfo *cinfo;
6008         guint32 idx;
6009         
6010         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6011                 return cinfo;
6012         idx = find_event_index (klass, event);
6013         idx <<= CUSTOM_ATTR_BITS;
6014         idx |= CUSTOM_ATTR_EVENT;
6015         return mono_custom_attrs_from_index (klass->image, idx);
6016 }
6017
6018 MonoCustomAttrInfo*
6019 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6020 {
6021         MonoCustomAttrInfo *cinfo;
6022         guint32 idx;
6023         
6024         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6025                 return cinfo;
6026         idx = find_field_index (klass, field);
6027         idx <<= CUSTOM_ATTR_BITS;
6028         idx |= CUSTOM_ATTR_FIELDDEF;
6029         return mono_custom_attrs_from_index (klass->image, idx);
6030 }
6031
6032 MonoCustomAttrInfo*
6033 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6034 {
6035         MonoTableInfo *ca;
6036         guint32 i, idx, method_index;
6037         guint32 param_list, param_last, param_pos, found;
6038         MonoImage *image;
6039         MonoReflectionMethodAux *aux;
6040
6041         if (method->klass->image->dynamic) {
6042                 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6043                 if (!aux || !aux->param_cattr)
6044                         return NULL;
6045                 return aux->param_cattr [param];
6046         }
6047
6048         image = method->klass->image;
6049         method_index = find_method_index (method);
6050         ca = &image->tables [MONO_TABLE_METHOD];
6051
6052         if (method->klass->generic_inst || method->klass->gen_params ||
6053             method->signature->generic_param_count) {
6054                 // FIXME FIXME FIXME
6055                 return NULL;
6056         }
6057
6058         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6059         if (method_index == ca->rows) {
6060                 ca = &image->tables [MONO_TABLE_PARAM];
6061                 param_last = ca->rows + 1;
6062         } else {
6063                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6064                 ca = &image->tables [MONO_TABLE_PARAM];
6065         }
6066         found = FALSE;
6067         for (i = param_list; i < param_last; ++i) {
6068                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6069                 if (param_pos == param) {
6070                         found = TRUE;
6071                         break;
6072                 }
6073         }
6074         if (!found)
6075                 return NULL;
6076         idx = i;
6077         idx <<= CUSTOM_ATTR_BITS;
6078         idx |= CUSTOM_ATTR_PARAMDEF;
6079         return mono_custom_attrs_from_index (image, idx);
6080 }
6081
6082 /*
6083  * mono_reflection_get_custom_attrs:
6084  * @obj: a reflection object handle
6085  *
6086  * Return an array with all the custom attributes defined of the
6087  * reflection handle @obj. The objects are fully build.
6088  */
6089 MonoArray*
6090 mono_reflection_get_custom_attrs (MonoObject *obj)
6091 {
6092         MonoClass *klass;
6093         MonoArray *result;
6094         MonoCustomAttrInfo *cinfo = NULL;
6095         
6096         MONO_ARCH_SAVE_REGS;
6097
6098         klass = obj->vtable->klass;
6099         /* FIXME: need to handle: Module */
6100         if (klass == mono_defaults.monotype_class) {
6101                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6102                 klass = mono_class_from_mono_type (rtype->type);
6103                 cinfo = mono_custom_attrs_from_class (klass);
6104         } else if (strcmp ("Assembly", klass->name) == 0) {
6105                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6106                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6107         } else if (strcmp ("Module", klass->name) == 0) {
6108                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6109                 cinfo = mono_custom_attrs_from_module (module->image);
6110         } else if (strcmp ("MonoProperty", klass->name) == 0) {
6111                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6112                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6113         } else if (strcmp ("MonoEvent", klass->name) == 0) {
6114                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6115                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6116         } else if (strcmp ("MonoField", klass->name) == 0) {
6117                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6118                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6119         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6120                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6121                 cinfo = mono_custom_attrs_from_method (rmethod->method);
6122         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6123                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6124                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6125                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6126         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6127                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6128                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6129         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6130                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6131                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6132         } else { /* handle other types here... */
6133                 g_error ("get custom attrs not yet supported for %s", klass->name);
6134         }
6135
6136         if (cinfo) {
6137                 result = mono_custom_attrs_construct (cinfo);
6138         } else {
6139                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6140                 result = mono_array_new (mono_domain_get (), klass, 0);
6141         }
6142
6143         return result;
6144 }
6145
6146 static MonoMethodSignature*
6147 parameters_to_signature (MonoArray *parameters) {
6148         MonoMethodSignature *sig;
6149         int count, i;
6150
6151         count = parameters? mono_array_length (parameters): 0;
6152
6153         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6154         sig->param_count = count;
6155         sig->sentinelpos = -1; /* FIXME */
6156         for (i = 0; i < count; ++i) {
6157                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6158                 sig->params [i] = pt->type;
6159         }
6160         return sig;
6161 }
6162
6163 static MonoMethodSignature*
6164 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6165         MonoMethodSignature *sig;
6166
6167         sig = parameters_to_signature (ctor->parameters);
6168         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6169         sig->ret = &mono_defaults.void_class->byval_arg;
6170         return sig;
6171 }
6172
6173 static MonoMethodSignature*
6174 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6175         MonoMethodSignature *sig;
6176
6177         sig = parameters_to_signature (method->parameters);
6178         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6179         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6180         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6181         return sig;
6182 }
6183
6184 static MonoMethodSignature*
6185 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6186         MonoMethodSignature *sig;
6187
6188         sig = parameters_to_signature (method->parameters);
6189         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6190         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6191         sig->generic_param_count = 0;
6192         return sig;
6193 }
6194
6195 static void
6196 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6197 {
6198         MonoClass *klass = mono_object_class (prop);
6199         if (strcmp (klass->name, "PropertyBuilder") == 0) {
6200                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6201                 *name = mono_string_to_utf8 (pb->name);
6202                 *type = pb->type->type;
6203         } else {
6204                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6205                 *name = g_strdup (p->property->name);
6206                 if (p->property->get)
6207                         *type = p->property->get->signature->ret;
6208                 else
6209                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6210         }
6211 }
6212
6213 static void
6214 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6215 {
6216         MonoClass *klass = mono_object_class (field);
6217         if (strcmp (klass->name, "FieldBuilder") == 0) {
6218                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6219                 *name = mono_string_to_utf8 (fb->name);
6220                 *type = fb->type->type;
6221         } else {
6222                 MonoReflectionField *f = (MonoReflectionField *)field;
6223                 *name = g_strdup (f->field->name);
6224                 *type = f->field->type;
6225         }
6226 }
6227
6228 static void
6229 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6230 {
6231         char *argval;
6232         MonoTypeEnum simple_type;
6233         
6234         if ((p-buffer) + 10 >= *buflen) {
6235                 char *newbuf;
6236                 *buflen *= 2;
6237                 newbuf = g_realloc (buffer, *buflen);
6238                 p = newbuf + (p-buffer);
6239                 buffer = newbuf;
6240         }
6241         argval = ((char*)arg + sizeof (MonoObject));
6242         simple_type = type->type;
6243 handle_enum:
6244         switch (simple_type) {
6245         case MONO_TYPE_BOOLEAN:
6246         case MONO_TYPE_U1:
6247         case MONO_TYPE_I1:
6248                 *p++ = *argval;
6249                 break;
6250         case MONO_TYPE_CHAR:
6251         case MONO_TYPE_U2:
6252         case MONO_TYPE_I2:
6253                 swap_with_size (p, argval, 2, 1);
6254                 p += 2;
6255                 break;
6256         case MONO_TYPE_U4:
6257         case MONO_TYPE_I4:
6258         case MONO_TYPE_R4:
6259                 swap_with_size (p, argval, 4, 1);
6260                 p += 4;
6261                 break;
6262         case MONO_TYPE_U8:
6263         case MONO_TYPE_I8:
6264         case MONO_TYPE_R8:
6265                 swap_with_size (p, argval, 8, 1);
6266                 p += 8;
6267                 break;
6268         case MONO_TYPE_VALUETYPE:
6269                 if (type->data.klass->enumtype) {
6270                         simple_type = type->data.klass->enum_basetype->type;
6271                         goto handle_enum;
6272                 } else {
6273                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6274                 }
6275                 break;
6276         case MONO_TYPE_STRING: {
6277                 char *str;
6278                 guint32 slen;
6279                 if (!arg) {
6280                         *p++ = 0xFF;
6281                         break;
6282                 }
6283                 str = mono_string_to_utf8 ((MonoString*)arg);
6284                 slen = strlen (str);
6285                 if ((p-buffer) + 10 + slen >= *buflen) {
6286                         char *newbuf;
6287                         *buflen *= 2;
6288                         *buflen += slen;
6289                         newbuf = g_realloc (buffer, *buflen);
6290                         p = newbuf + (p-buffer);
6291                         buffer = newbuf;
6292                 }
6293                 mono_metadata_encode_value (slen, p, &p);
6294                 memcpy (p, str, slen);
6295                 p += slen;
6296                 g_free (str);
6297                 break;
6298         }
6299         case MONO_TYPE_CLASS: {
6300                 char *str;
6301                 guint32 slen;
6302                 MonoClass *k;
6303                 if (!arg) {
6304                         *p++ = 0xFF;
6305                         break;
6306                 }
6307                 k = mono_object_class (arg);
6308                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6309                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6310                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6311 handle_type:
6312                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6313                 slen = strlen (str);
6314                 if ((p-buffer) + 10 + slen >= *buflen) {
6315                         char *newbuf;
6316                         *buflen *= 2;
6317                         *buflen += slen;
6318                         newbuf = g_realloc (buffer, *buflen);
6319                         p = newbuf + (p-buffer);
6320                         buffer = newbuf;
6321                 }
6322                 mono_metadata_encode_value (slen, p, &p);
6323                 memcpy (p, str, slen);
6324                 p += slen;
6325                 g_free (str);
6326                 break;
6327         }
6328         case MONO_TYPE_SZARRAY: {
6329                 int len, i;
6330                 MonoClass *eclass;
6331
6332                 if (!arg) {
6333                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6334                         break;
6335                 }
6336                 len = mono_array_length ((MonoArray*)arg);
6337                 *p++ = len & 0xff;
6338                 *p++ = (len >> 8) & 0xff;
6339                 *p++ = (len >> 16) & 0xff;
6340                 *p++ = (len >> 24) & 0xff;
6341                 *retp = p;
6342                 *retbuffer = buffer;
6343                 eclass = type->data.klass;
6344                 for (i = 0; i < len; ++i) {
6345                         encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6346                 }
6347                 break;
6348         }
6349         /* it may be a boxed value or a Type */
6350         case MONO_TYPE_OBJECT: {
6351                 MonoClass *klass = mono_object_class (arg);
6352                 char *str;
6353                 guint32 slen;
6354                 
6355                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6356                         *p++ = 0x50;
6357                         goto handle_type;
6358                 } else if (klass->enumtype) {
6359                         *p++ = 0x55;
6360                 } else if (klass == mono_defaults.string_class) {
6361                         simple_type = MONO_TYPE_STRING;
6362                         *p++ = 0x0E;
6363                         goto handle_enum;
6364                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6365                         *p++ = simple_type = klass->byval_arg.type;
6366                         goto handle_enum;
6367                 } else {
6368                         g_error ("unhandled type in custom attr");
6369                 }
6370                 str = type_get_qualified_name (klass->enum_basetype, NULL);
6371                 slen = strlen (str);
6372                 if ((p-buffer) + 10 + slen >= *buflen) {
6373                         char *newbuf;
6374                         *buflen *= 2;
6375                         *buflen += slen;
6376                         newbuf = g_realloc (buffer, *buflen);
6377                         p = newbuf + (p-buffer);
6378                         buffer = newbuf;
6379                 }
6380                 mono_metadata_encode_value (slen, p, &p);
6381                 memcpy (p, str, slen);
6382                 p += slen;
6383                 g_free (str);
6384                 simple_type = klass->enum_basetype->type;
6385                 goto handle_enum;
6386         }
6387         default:
6388                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6389         }
6390         *retp = p;
6391         *retbuffer = buffer;
6392 }
6393
6394 /*
6395  * mono_reflection_get_custom_attrs_blob:
6396  * @ctor: custom attribute constructor
6397  * @ctorArgs: arguments o the constructor
6398  * @properties:
6399  * @propValues:
6400  * @fields:
6401  * @fieldValues:
6402  * 
6403  * Creates the blob of data that needs to be saved in the metadata and that represents
6404  * the custom attributed described by @ctor, @ctorArgs etc.
6405  * Returns: a Byte array representing the blob of data.
6406  */
6407 MonoArray*
6408 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
6409 {
6410         MonoArray *result;
6411         MonoMethodSignature *sig;
6412         MonoObject *arg;
6413         char *buffer, *p;
6414         guint32 buflen, i;
6415
6416         MONO_ARCH_SAVE_REGS;
6417
6418         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6419                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6420         } else {
6421                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6422         }
6423         g_assert (mono_array_length (ctorArgs) == sig->param_count);
6424         buflen = 256;
6425         p = buffer = g_malloc (buflen);
6426         /* write the prolog */
6427         *p++ = 1;
6428         *p++ = 0;
6429         for (i = 0; i < sig->param_count; ++i) {
6430                 arg = mono_array_get (ctorArgs, MonoObject*, i);
6431                 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6432         }
6433         i = 0;
6434         if (properties)
6435                 i += mono_array_length (properties);
6436         if (fields)
6437                 i += mono_array_length (fields);
6438         *p++ = i & 0xff;
6439         *p++ = (i >> 8) & 0xff;
6440         if (properties) {
6441                 MonoObject *prop;
6442                 for (i = 0; i < mono_array_length (properties); ++i) {
6443                         MonoType *ptype;
6444                         char *pname;
6445                         int len;
6446                         
6447                         prop = mono_array_get (properties, gpointer, i);
6448                         get_prop_name_and_type (prop, &pname, &ptype);
6449                         *p++ = 0x54; /* PROPERTY signature */
6450
6451                         /* Preallocate a large enough buffer */
6452                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6453                                 char *str = type_get_qualified_name (ptype, NULL);
6454                                 len = strlen (str);
6455                                 g_free (str);
6456                         }
6457                         else
6458                                 len = 0;
6459                         len += strlen (pname);
6460
6461                         if ((p-buffer) + 20 + len >= buflen) {
6462                                 char *newbuf;
6463                                 buflen *= 2;
6464                                 buflen += len;
6465                                 newbuf = g_realloc (buffer, buflen);
6466                                 p = newbuf + (p-buffer);
6467                                 buffer = newbuf;
6468                         }
6469
6470                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6471                                 char *str = type_get_qualified_name (ptype, NULL);
6472                                 int slen = strlen (str);
6473
6474                                 *p++ = 0x55;
6475                                 /*
6476                                  * This seems to be optional...
6477                                  * *p++ = 0x80;
6478                                  */
6479                                 mono_metadata_encode_value (slen, p, &p);
6480                                 memcpy (p, str, slen);
6481                                 p += slen;
6482                                 g_free (str);
6483                         } else {
6484                                 mono_metadata_encode_value (ptype->type, p, &p);
6485                                 if (ptype->type == MONO_TYPE_SZARRAY)
6486                                         mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6487                         }
6488                         len = strlen (pname);
6489                         mono_metadata_encode_value (len, p, &p);
6490                         memcpy (p, pname, len);
6491                         p += len;
6492                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6493                         g_free (pname);
6494                 }
6495         }
6496
6497         if (fields) {
6498                 MonoObject *field;
6499                 for (i = 0; i < mono_array_length (fields); ++i) {
6500                         MonoType *ftype;
6501                         char *fname;
6502                         int len;
6503                         
6504                         field = mono_array_get (fields, gpointer, i);
6505                         get_field_name_and_type (field, &fname, &ftype);
6506                         *p++ = 0x53; /* FIELD signature */
6507                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6508                                 char *str = type_get_qualified_name (ftype, NULL);
6509                                 int slen = strlen (str);
6510                                 if ((p-buffer) + 10 + slen >= buflen) {
6511                                         char *newbuf;
6512                                         buflen *= 2;
6513                                         buflen += slen;
6514                                         newbuf = g_realloc (buffer, buflen);
6515                                         p = newbuf + (p-buffer);
6516                                         buffer = newbuf;
6517                                 }
6518                                 *p++ = 0x55;
6519                                 /*
6520                                  * This seems to be optional...
6521                                  * *p++ = 0x80;
6522                                  */
6523                                 mono_metadata_encode_value (slen, p, &p);
6524                                 memcpy (p, str, slen);
6525                                 p += slen;
6526                                 g_free (str);
6527                         } else {
6528                                 mono_metadata_encode_value (ftype->type, p, &p);
6529                         }
6530                         len = strlen (fname);
6531                         mono_metadata_encode_value (len, p, &p);
6532                         memcpy (p, fname, len);
6533                         p += len;
6534                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6535                         g_free (fname);
6536                 }
6537         }
6538
6539         g_assert (p - buffer <= buflen);
6540         buflen = p - buffer;
6541         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6542         p = mono_array_addr (result, char, 0);
6543         memcpy (p, buffer, buflen);
6544         g_free (buffer);
6545         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6546                 g_free (sig);
6547         return result;
6548 }
6549
6550 /*
6551  * mono_reflection_setup_internal_class:
6552  * @tb: a TypeBuilder object
6553  *
6554  * Creates a MonoClass that represents the TypeBuilder.
6555  * This is a trick that lets us simplify a lot of reflection code
6556  * (and will allow us to support Build and Run assemblies easier).
6557  */
6558 void
6559 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6560 {
6561         MonoClass *klass, *parent;
6562
6563         MONO_ARCH_SAVE_REGS;
6564
6565         klass = g_new0 (MonoClass, 1);
6566
6567         klass->image = &tb->module->dynamic_image->image;
6568
6569         if (tb->parent) {
6570                 /* check so we can compile corlib correctly */
6571                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6572                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6573                         parent = tb->parent->type->data.klass;
6574                 } else 
6575                         parent = my_mono_class_from_mono_type (tb->parent->type);
6576         } else
6577                 parent = NULL;
6578         
6579         klass->inited = 1; /* we lie to the runtime */
6580         klass->name = mono_string_to_utf8 (tb->name);
6581         klass->name_space = mono_string_to_utf8 (tb->nspace);
6582         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6583         klass->flags = tb->attrs;
6584
6585         klass->element_class = klass;
6586         klass->reflection_info = tb; /* need to pin. */
6587
6588         /* Put into cache so mono_class_get () will find it */
6589         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6590                                                                   tb->table_idx);
6591
6592         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6593                                                           GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6594                                                           tb);
6595
6596         if (parent != NULL)
6597                 mono_class_setup_parent (klass, parent);
6598         else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6599                 const char *old_n = klass->name;
6600                 /* trick to get relative numbering right when compiling corlib */
6601                 klass->name = "BuildingObject";
6602                 mono_class_setup_parent (klass, mono_defaults.object_class);
6603                 klass->name = old_n;
6604         }
6605         mono_class_setup_mono_type (klass);
6606
6607         mono_class_setup_supertypes (klass);
6608
6609         /*
6610          * FIXME: handle interfaces.
6611          */
6612
6613         tb->type.type = &klass->byval_arg;
6614
6615         if (tb->nesting_type) {
6616                 g_assert (tb->nesting_type->type);
6617                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6618         }
6619
6620         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6621 }
6622
6623 /*
6624  * mono_reflection_setup_generic_class:
6625  * @tb: a TypeBuilder object
6626  *
6627  * Setup the generic class after all generic parameters have been added.
6628  */
6629 void
6630 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6631 {
6632         MonoClass *klass;
6633         int count, i;
6634
6635         MONO_ARCH_SAVE_REGS;
6636
6637         klass = my_mono_class_from_mono_type (tb->type.type);
6638
6639         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6640
6641         if (klass->gen_params || (count == 0))
6642                 return;
6643
6644         klass->num_gen_params = count;
6645         klass->gen_params = g_new0 (MonoGenericParam, count);
6646
6647         for (i = 0; i < count; i++) {
6648                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6649                 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6650         }
6651 }
6652
6653 /*
6654  * mono_reflection_create_internal_class:
6655  * @tb: a TypeBuilder object
6656  *
6657  * Actually create the MonoClass that is associated with the TypeBuilder.
6658  */
6659 void
6660 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6661 {
6662         MonoClass *klass;
6663
6664         MONO_ARCH_SAVE_REGS;
6665
6666         klass = my_mono_class_from_mono_type (tb->type.type);
6667
6668         if (klass->enumtype && klass->enum_basetype == NULL) {
6669                 MonoReflectionFieldBuilder *fb;
6670
6671                 g_assert (tb->fields != NULL);
6672                 g_assert (mono_array_length (tb->fields) >= 1);
6673
6674                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6675
6676                 klass->enum_basetype = fb->type->type;
6677                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6678                 if (!klass->element_class)
6679                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6680                 klass->instance_size = klass->element_class->instance_size;
6681                 klass->size_inited = 1;
6682                 /* 
6683                  * this is almost safe to do with enums and it's needed to be able
6684                  * to create objects of the enum type (for use in SetConstant).
6685                  */
6686                 /* FIXME: Does this mean enums can't have method overrides ? */
6687                 mono_class_setup_vtable (klass, NULL, 0);
6688         }
6689 }
6690
6691 static MonoMarshalSpec*
6692 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6693                                                                 MonoReflectionMarshal *minfo)
6694 {
6695         MonoMarshalSpec *res;
6696
6697         res = g_new0 (MonoMarshalSpec, 1);
6698         res->native = minfo->type;
6699
6700         switch (minfo->type) {
6701         case MONO_NATIVE_LPARRAY:
6702                 res->data.array_data.elem_type = minfo->eltype;
6703                 res->data.array_data.param_num = 0; /* Not yet */
6704                 res->data.array_data.num_elem = minfo->count;
6705                 break;
6706
6707         case MONO_NATIVE_BYVALTSTR:
6708         case MONO_NATIVE_BYVALARRAY:
6709                 res->data.array_data.num_elem = minfo->count;
6710                 break;
6711
6712         case MONO_NATIVE_CUSTOM:
6713                 if (minfo->marshaltyperef)
6714                         res->data.custom_data.custom_name =
6715                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6716                 if (minfo->mcookie)
6717                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6718                 break;
6719
6720         default:
6721                 break;
6722         }
6723
6724         return res;
6725 }
6726
6727 static MonoMethod*
6728 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6729                                          ReflectionMethodBuilder *rmb,
6730                                          MonoMethodSignature *sig)
6731 {
6732         MonoMethod *m;
6733         MonoMethodNormal *pm;
6734         MonoMarshalSpec **specs;
6735         MonoReflectionMethodAux *method_aux;
6736         int i;
6737
6738         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6739             (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6740                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6741         else 
6742                 if (rmb->refs)
6743                         m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6744         else
6745                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6746
6747         pm = (MonoMethodNormal*)m;
6748
6749         m->slot = -1;
6750         m->flags = rmb->attrs;
6751         m->iflags = rmb->iattrs;
6752         m->name = mono_string_to_utf8 (rmb->name);
6753         m->klass = klass;
6754         m->signature = sig;
6755         if (rmb->table_idx)
6756                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6757
6758         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6759                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6760                         m->string_ctor = 1;
6761
6762                 m->signature->pinvoke = 1;
6763         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6764                 /* TODO */
6765                 m->signature->pinvoke = 1;
6766                 return m;
6767         } else if (!m->klass->dummy && 
6768                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6769                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6770                 MonoMethodHeader *header;
6771                 guint32 code_size;
6772                 gint32 max_stack, i;
6773                 gint32 num_locals = 0;
6774                 gint32 num_clauses = 0;
6775                 guint8 *code;
6776
6777                 if (rmb->ilgen) {
6778                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6779                         code_size = rmb->ilgen->code_len;
6780                         max_stack = rmb->ilgen->max_stack;
6781                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6782                         if (rmb->ilgen->ex_handlers)
6783                                 num_clauses = method_count_clauses (rmb->ilgen);
6784                 } else {
6785                         if (rmb->code) {
6786                                 code = mono_array_addr (rmb->code, guint8, 0);
6787                                 code_size = mono_array_length (rmb->code);
6788                                 /* we probably need to run a verifier on the code... */
6789                                 max_stack = 8; 
6790                         }
6791                         else {
6792                                 code = NULL;
6793                                 code_size = 0;
6794                                 max_stack = 8;
6795                         }
6796                 }
6797
6798                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
6799                                                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6800                 header->code_size = code_size;
6801                 header->code = g_malloc (code_size);
6802                 memcpy ((char*)header->code, code, code_size);
6803                 header->max_stack = max_stack;
6804                 header->init_locals = rmb->init_locals;
6805                 header->num_locals = num_locals;
6806
6807                 for (i = 0; i < num_locals; ++i) {
6808                         MonoReflectionLocalBuilder *lb = 
6809                                 mono_array_get (rmb->ilgen->locals, 
6810                                                                 MonoReflectionLocalBuilder*, i);
6811
6812                         header->locals [i] = g_new0 (MonoType, 1);
6813                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6814                 }
6815
6816                 header->num_clauses = num_clauses;
6817                 if (num_clauses) {
6818                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6819                                                                  rmb->ilgen,
6820                                                                  num_clauses);
6821                 }
6822
6823                 if (rmb->generic_params) {
6824                         int count = mono_array_length (rmb->generic_params);
6825                         header->gen_params = g_new0 (MonoGenericParam, count);
6826                         for (i = 0; i < count; i++) {
6827                                 MonoReflectionGenericParam *gp =
6828                                         mono_array_get (rmb->generic_params,
6829                                                         MonoReflectionGenericParam*, i);
6830
6831                                 header->gen_params [i] = *gp->type.type->data.generic_param;
6832                         }
6833                 }
6834
6835                 pm->header = header;
6836         }
6837
6838         if (rmb->refs) {
6839                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6840                 int i;
6841
6842                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6843
6844                 for (i = 0; i < rmb->nrefs; ++i)
6845                         mw->data = g_list_append (mw->data, rmb->refs [i]);
6846         }
6847
6848         method_aux = NULL;
6849
6850         /* Parameter names */
6851         if (rmb->pinfo) {
6852                 if (!method_aux)
6853                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
6854                 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
6855                 for (i = 0; i <= m->signature->param_count; ++i) {
6856                         MonoReflectionParamBuilder *pb;
6857                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6858                                 if (pb->name)
6859                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6860                                 if (pb->cattrs) {
6861                                         if (!method_aux->param_cattr)
6862                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
6863                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
6864                                 }
6865                         }
6866                 }
6867         }
6868
6869         /* Parameter marshalling */
6870         specs = NULL;
6871         if (rmb->pinfo)         
6872                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6873                         MonoReflectionParamBuilder *pb;
6874                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6875                                 if (pb->marshal_info) {
6876                                         if (specs == NULL)
6877                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6878                                         specs [pb->position] = 
6879                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6880                                 }
6881                         }
6882                 }
6883         if (specs != NULL) {
6884                 if (!method_aux)
6885                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
6886                 method_aux->param_marshall = specs;
6887         }
6888
6889         if (klass->image->dynamic && method_aux)
6890                 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6891
6892         return m;
6893 }       
6894
6895 static MonoMethod*
6896 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6897 {
6898         ReflectionMethodBuilder rmb;
6899         MonoMethodSignature *sig;
6900
6901         sig = ctor_builder_to_signature (mb);
6902
6903         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6904
6905         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6906         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6907
6908         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6909                 /* ilgen is no longer needed */
6910                 mb->ilgen = NULL;
6911         }
6912
6913         return mb->mhandle;
6914 }
6915
6916 static MonoMethod*
6917 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6918 {
6919         ReflectionMethodBuilder rmb;
6920         MonoMethodSignature *sig;
6921
6922         sig = method_builder_to_signature (mb);
6923
6924         reflection_methodbuilder_from_method_builder (&rmb, mb);
6925
6926         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6927         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6928
6929         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6930                 /* ilgen is no longer needed */
6931                 mb->ilgen = NULL;
6932         }
6933         return mb->mhandle;
6934 }
6935
6936 static MonoClassField*
6937 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6938 {
6939         MonoClassField *field;
6940         const char *p, *p2;
6941         guint32 len, idx;
6942
6943         if (fb->handle)
6944                 return fb->handle;
6945
6946         field = g_new0 (MonoClassField, 1);
6947
6948         field->name = mono_string_to_utf8 (fb->name);
6949         if (fb->attrs) {
6950                 /* FIXME: handle type modifiers */
6951                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
6952                 field->type->attrs = fb->attrs;
6953         } else {
6954                 field->type = fb->type->type;
6955         }
6956         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
6957                 field->data = mono_array_addr (fb->rva_data, char, 0);
6958         if (fb->offset != -1)
6959                 field->offset = fb->offset;
6960         field->parent = klass;
6961         fb->handle = field;
6962         mono_save_custom_attrs (klass->image, field, fb->cattrs);
6963
6964         if (fb->def_value) {
6965                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
6966                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
6967                 field->def_value = g_new0 (MonoConstant, 1);
6968                 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
6969                 /* Copy the data from the blob since it might get realloc-ed */
6970                 p = assembly->blob.data + idx;
6971                 len = mono_metadata_decode_blob_size (p, &p2);
6972                 len += p2 - p;
6973                 field->def_value->value = g_malloc (len);
6974                 memcpy (field->def_value->value, p, len);
6975         }
6976
6977         return field;
6978 }
6979
6980 static MonoType*
6981 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
6982                                             MonoType **types, MonoType *nested_in)
6983 {
6984         MonoClass *klass;
6985         MonoReflectionTypeBuilder *tb = NULL;
6986         MonoGenericInst *ginst;
6987         MonoDomain *domain;
6988         MonoType *geninst;
6989         int icount, i;
6990
6991         klass = mono_class_from_mono_type (type->type);
6992         if (!klass->gen_params && !klass->generic_inst &&
6993             !(klass->nested_in && klass->nested_in->gen_params))
6994                 return NULL;
6995
6996         mono_loader_lock ();
6997
6998         domain = mono_object_domain (type);
6999
7000         ginst = g_new0 (MonoGenericInst, 1);
7001
7002         if (!klass->generic_inst) {
7003                 ginst->type_argc = type_argc;
7004                 ginst->type_argv = types;
7005
7006                 for (i = 0; i < ginst->type_argc; ++i) {
7007                         if (!ginst->is_open)
7008                                 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7009                 }
7010
7011                 ginst->generic_type = &klass->byval_arg;
7012         } else {
7013                 MonoGenericInst *kginst = klass->generic_inst;
7014
7015                 ginst->type_argc = kginst->type_argc;
7016                 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7017
7018                 for (i = 0; i < ginst->type_argc; i++) {
7019                         MonoType *t = kginst->type_argv [i];
7020
7021                         if (t->type == MONO_TYPE_VAR)
7022                                 t = types [t->data.generic_param->num];
7023
7024                         if (!ginst->is_open)
7025                                 ginst->is_open = mono_class_is_open_constructed_type (t);
7026
7027                         ginst->type_argv [i] = t;
7028                 }
7029
7030                 ginst->generic_type = kginst->generic_type;
7031         }
7032
7033         geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7034         if (geninst) {
7035                 g_free (ginst);
7036                 mono_loader_unlock ();
7037                 return geninst;
7038         }
7039
7040         ginst->context = g_new0 (MonoGenericContext, 1);
7041         ginst->context->ginst = ginst;
7042
7043         geninst = g_new0 (MonoType, 1);
7044         geninst->type = MONO_TYPE_GENERICINST;
7045         geninst->data.generic_inst = ginst;
7046
7047         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7048                 tb = (MonoReflectionTypeBuilder *) type;
7049
7050                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7051                 ginst->is_dynamic = TRUE;
7052         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7053                 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7054                 MonoReflectionType *rgt = rgi->generic_type;
7055
7056                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7057                 tb = (MonoReflectionTypeBuilder *) rgt;
7058
7059                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7060                 ginst->is_dynamic = TRUE;
7061         } else
7062                 icount = klass->interface_count;
7063
7064         ginst->ifaces = g_new0 (MonoType *, icount);
7065         ginst->count_ifaces = icount;
7066
7067         for (i = 0; i < icount; i++) {
7068                 MonoReflectionType *itype;
7069
7070                 if (tb)
7071                         itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7072                 else
7073                         itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7074                 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7075                 if (!ginst->ifaces [i])
7076                         ginst->ifaces [i] = itype->type;
7077         }
7078
7079         ginst->nested_in = nested_in;
7080
7081         mono_class_create_generic (ginst);
7082
7083         g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7084
7085         mono_loader_unlock ();
7086
7087         return geninst;
7088 }
7089
7090 MonoType*
7091 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7092 {
7093         MonoClass *klass, *pklass = NULL, *oklass = NULL;
7094         MonoReflectionType *parent = NULL, *outer = NULL;
7095         MonoType *geninst, *nested_in = NULL;
7096         MonoReflectionTypeBuilder *tb = NULL;
7097         MonoGenericInst *ginst;
7098         MonoDomain *domain;
7099
7100         domain = mono_object_domain (type);
7101         klass = mono_class_from_mono_type (type->type);
7102
7103         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7104                 tb = (MonoReflectionTypeBuilder *) type;
7105
7106                 if (tb->parent) {
7107                         parent = tb->parent;
7108                         pklass = mono_class_from_mono_type (parent->type);
7109                 }
7110                 if (tb->nesting_type) {
7111                         outer = tb->nesting_type;
7112                         oklass = mono_class_from_mono_type (outer->type);
7113                 }
7114         } else {
7115                 pklass = klass->parent;
7116                 if (pklass)
7117                         parent = mono_type_get_object (domain, &pklass->byval_arg);
7118                 oklass = klass->nested_in;
7119                 if (oklass)
7120                         outer = mono_type_get_object (domain, &oklass->byval_arg);
7121         }
7122
7123         if (oklass)
7124                 nested_in = mono_reflection_bind_generic_parameters (outer, oklass->num_gen_params, types);
7125
7126         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types, nested_in);
7127         if (!geninst)
7128                 return NULL;
7129
7130         ginst = geninst->data.generic_inst;
7131
7132         if (pklass && pklass->generic_inst)
7133                 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7134
7135         return geninst;
7136 }
7137
7138 void
7139 mono_reflection_generic_inst_get_nested_types (MonoReflectionGenericInst *type)
7140 {
7141         MonoReflectionTypeBuilder *tb;
7142         MonoGenericInst *ginst;
7143         int i;
7144
7145         ginst = type->type.type->data.generic_inst;
7146         if (ginst->nested)
7147                 return;
7148
7149         if (strcmp (((MonoObject *) type->generic_type)->vtable->klass->name, "TypeBuilder"))
7150                 return;
7151
7152         tb = (MonoReflectionTypeBuilder *) type->generic_type;
7153
7154         ginst->count_nested = tb->subtypes ? mono_array_length (tb->subtypes) : 0;
7155         ginst->nested = g_new0 (MonoType *, ginst->count_nested);
7156
7157         for (i = 0; i < ginst->count_nested; i++) {
7158                 MonoReflectionTypeBuilder *ntype;
7159                 MonoType **ntypes;
7160                 int ntype_argc, j;
7161
7162                 ntype = mono_array_get (tb->subtypes, gpointer, i);
7163                 ntype_argc = ntype->generic_params ? mono_array_length (ntype->generic_params) : 0;
7164
7165                 if (ntype_argc > ginst->type_argc) {
7166                         ntypes = g_new0 (MonoType *, ntype_argc);
7167
7168                         for (j = 0; j < ginst->type_argc; j++)
7169                                 ntypes [j] = ginst->type_argv [j];
7170
7171                         for (j = ginst->type_argc; j < ntype_argc; j++) {
7172                                 MonoReflectionGenericParam *ngparam;
7173                                 MonoType *pt = g_new0 (MonoType, 1);
7174
7175                                 ngparam = mono_array_get (ntype->generic_params, gpointer, j);
7176
7177                                 pt->type = MONO_TYPE_VAR;
7178                                 pt->data.generic_param = ngparam->type.type->data.generic_param;
7179
7180                                 ntypes [j] = pt;
7181                         }
7182                 } else
7183                         ntypes = ginst->type_argv;
7184
7185                 ginst->nested [i] = mono_reflection_bind_generic_parameters ((MonoReflectionType *) ntype, ntype_argc, ntypes);
7186         }
7187 }
7188
7189 MonoReflectionMethod*
7190 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7191 {
7192         MonoMethod *method, *inflated;
7193         MonoReflectionMethodBuilder *mb = NULL;
7194         MonoGenericMethod *gmethod;
7195         MonoGenericContext *context;
7196         int count, i;
7197
7198         MONO_ARCH_SAVE_REGS;
7199         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7200                 MonoReflectionTypeBuilder *tb;
7201                 MonoClass *klass;
7202
7203                 mb = (MonoReflectionMethodBuilder *) rmethod;
7204                 tb = (MonoReflectionTypeBuilder *) mb->type;
7205                 klass = mono_class_from_mono_type (tb->type.type);
7206
7207                 method = methodbuilder_to_mono_method (klass, mb);
7208         } else
7209                 method = rmethod->method;
7210
7211         count = method->signature->generic_param_count;
7212         if (count != mono_array_length (types))
7213                 return NULL;
7214
7215         gmethod = g_new0 (MonoGenericMethod, 1);
7216         gmethod->mtype_argc = count;
7217         gmethod->mtype_argv = g_new0 (MonoType *, count);
7218         for (i = 0; i < count; i++) {
7219                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7220                 gmethod->mtype_argv [i] = garg->type;
7221         }
7222
7223         context = g_new0 (MonoGenericContext, 1);
7224         context->ginst = method->klass->generic_inst;
7225         context->gmethod = gmethod;
7226
7227         inflated = mono_class_inflate_generic_method (method, context, NULL);
7228
7229         return mono_method_get_object (
7230                 mono_object_domain (rmethod), inflated, NULL);
7231 }
7232
7233 static MonoMethod *
7234 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7235 {
7236         MonoGenericMethod *gmethod;
7237         MonoGenericInst *ginst;
7238         MonoGenericContext *context;
7239
7240         ginst = type->type.type->data.generic_inst;
7241
7242         gmethod = g_new0 (MonoGenericMethod, 1);
7243         gmethod->reflection_info = obj;
7244
7245         context = g_new0 (MonoGenericContext, 1);
7246         context->ginst = ginst;
7247         context->gmethod = gmethod;
7248
7249         return mono_class_inflate_generic_method (method, context, ginst->klass);
7250 }
7251
7252 static MonoMethod *
7253 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7254 {
7255         MonoMethod *method;
7256         MonoClass *klass;
7257
7258         klass = mono_class_from_mono_type (type->type.type);
7259
7260         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7261                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7262         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7263                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7264         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7265                  !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7266                 method = ((MonoReflectionMethod *) obj)->method;
7267         else {
7268                 method = NULL; /* prevent compiler warning */
7269                 g_assert_not_reached ();
7270         }
7271
7272         return inflate_mono_method (type, method, obj);
7273 }
7274
7275 void
7276 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7277                                          MonoArray *methods, MonoArray *ctors,
7278                                          MonoArray *fields, MonoArray *properties,
7279                                          MonoArray *events)
7280 {
7281         MonoGenericInst *ginst;
7282         MonoDynamicGenericInst *dginst;
7283         MonoClass *klass, *gklass, *pklass;
7284         int i;
7285
7286         MONO_ARCH_SAVE_REGS;
7287
7288         klass = mono_class_from_mono_type (type->type.type);
7289         ginst = type->type.type->data.generic_inst;
7290
7291         if (ginst->initialized)
7292                 return;
7293
7294         dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7295
7296         gklass = mono_class_from_mono_type (ginst->generic_type);
7297         mono_class_init (gklass);
7298
7299         if (ginst->parent)
7300                 pklass = mono_class_from_mono_type (ginst->parent);
7301         else
7302                 pklass = gklass->parent;
7303
7304         mono_class_setup_parent (klass, pklass);
7305
7306         dginst->count_methods = methods ? mono_array_length (methods) : 0;
7307         dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7308         dginst->count_fields = fields ? mono_array_length (fields) : 0;
7309         dginst->count_properties = properties ? mono_array_length (properties) : 0;
7310         dginst->count_events = events ? mono_array_length (events) : 0;
7311
7312         dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7313         dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7314         dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7315         dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7316         dginst->events = g_new0 (MonoEvent, dginst->count_events);
7317
7318         for (i = 0; i < dginst->count_methods; i++) {
7319                 MonoObject *obj = mono_array_get (methods, gpointer, i);
7320
7321                 dginst->methods [i] = inflate_method (type, obj);
7322         }
7323
7324         for (i = 0; i < dginst->count_ctors; i++) {
7325                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7326
7327                 dginst->ctors [i] = inflate_method (type, obj);
7328         }
7329
7330         for (i = 0; i < dginst->count_fields; i++) {
7331                 MonoObject *obj = mono_array_get (fields, gpointer, i);
7332                 MonoClassField *field;
7333
7334                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7335                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7336                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7337                         field = ((MonoReflectionField *) obj)->field;
7338                 else {
7339                         field = NULL; /* prevent compiler warning */
7340                         g_assert_not_reached ();
7341                 }
7342
7343                 dginst->fields [i] = *field;
7344                 dginst->fields [i].generic_type = field->type;
7345                 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7346         }
7347
7348         for (i = 0; i < dginst->count_properties; i++) {
7349                 MonoObject *obj = mono_array_get (properties, gpointer, i);
7350                 MonoProperty *property = &dginst->properties [i];
7351
7352                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7353                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7354
7355                         property->parent = klass;
7356                         property->attrs = pb->attrs;
7357                         property->name = mono_string_to_utf8 (pb->name);
7358                         if (pb->get_method)
7359                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7360                         if (pb->set_method)
7361                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7362                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7363                         *property = *((MonoReflectionProperty *) obj)->property;
7364
7365                         if (property->get)
7366                                 property->get = inflate_mono_method (type, property->get, NULL);
7367                         if (property->set)
7368                                 property->set = inflate_mono_method (type, property->set, NULL);
7369                 } else
7370                         g_assert_not_reached ();
7371         }
7372
7373         for (i = 0; i < dginst->count_events; i++) {
7374                 MonoObject *obj = mono_array_get (events, gpointer, i);
7375                 MonoEvent *event = &dginst->events [i];
7376
7377                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7378                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7379
7380                         event->parent = klass;
7381                         event->attrs = eb->attrs;
7382                         event->name = mono_string_to_utf8 (eb->name);
7383                         if (eb->add_method)
7384                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7385                         if (eb->remove_method)
7386                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7387                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7388                         *event = *((MonoReflectionEvent *) obj)->event;
7389
7390                         if (event->add)
7391                                 event->add = inflate_mono_method (type, event->add, NULL);
7392                         if (event->remove)
7393                                 event->remove = inflate_mono_method (type, event->remove, NULL);
7394                 } else
7395                         g_assert_not_reached ();
7396         }
7397
7398         ginst->initialized = TRUE;
7399 }
7400
7401 static void
7402 ensure_runtime_vtable (MonoClass *klass)
7403 {
7404         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7405         int i, num, j, onum;
7406         MonoMethod **overrides;
7407
7408         if (!tb || klass->wastypebuilder)
7409                 return;
7410         if (klass->parent)
7411                 ensure_runtime_vtable (klass->parent);
7412
7413         num = tb->ctors? mono_array_length (tb->ctors): 0;
7414         num += tb->num_methods;
7415         klass->method.count = num;
7416         klass->methods = g_new (MonoMethod*, num);
7417         num = tb->ctors? mono_array_length (tb->ctors): 0;
7418         for (i = 0; i < num; ++i)
7419                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7420         num = tb->num_methods;
7421         j = i;
7422         for (i = 0; i < num; ++i)
7423                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7424
7425         klass->wastypebuilder = TRUE;
7426         if (tb->interfaces) {
7427                 klass->interface_count = mono_array_length (tb->interfaces);
7428                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7429                 for (i = 0; i < klass->interface_count; ++i) {
7430                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7431                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7432                 }
7433         }
7434
7435         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7436                 for (i = 0; i < klass->method.count; ++i)
7437                         klass->methods [i]->slot = i;
7438
7439         /* Overrides */
7440         onum = 0;
7441         if (tb->methods) {
7442                 for (i = 0; i < tb->num_methods; ++i) {
7443                         MonoReflectionMethodBuilder *mb = 
7444                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7445                         if (mb->override_method)
7446                                 onum ++;
7447                 }
7448         }
7449
7450         overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7451
7452         if (tb->methods) {
7453                 onum = 0;
7454                 for (i = 0; i < tb->num_methods; ++i) {
7455                         MonoReflectionMethodBuilder *mb = 
7456                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7457                         if (mb->override_method) {
7458                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7459                                 overrides [onum * 2] = 
7460                                         mb->override_method->method;
7461                                 overrides [onum * 2 + 1] =
7462                                         mb->mhandle;
7463
7464                                 g_assert (mb->mhandle);
7465
7466                                 onum ++;
7467                         }
7468                 }
7469         }
7470
7471         mono_class_setup_vtable (klass, overrides, onum);
7472 }
7473
7474 static void
7475 typebuilder_setup_fields (MonoClass *klass)
7476 {
7477         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7478         MonoReflectionFieldBuilder *fb;
7479         MonoClassField *field;
7480         const char *p, *p2;
7481         int i;
7482         guint32 len, idx;
7483
7484         klass->field.count = tb->num_fields;
7485         klass->field.first = 0;
7486         klass->field.last = klass->field.count;
7487
7488         if (!klass->field.count)
7489                 return;
7490         
7491         klass->fields = g_new0 (MonoClassField, klass->field.count);
7492
7493         for (i = 0; i < klass->field.count; ++i) {
7494                 fb = mono_array_get (tb->fields, gpointer, i);
7495                 field = &klass->fields [i];
7496                 field->name = mono_string_to_utf8 (fb->name);
7497                 if (fb->attrs) {
7498                         /* FIXME: handle type modifiers */
7499                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
7500                         field->type->attrs = fb->attrs;
7501                 } else {
7502                         field->type = fb->type->type;
7503                 }
7504                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7505                         field->data = mono_array_addr (fb->rva_data, char, 0);
7506                 if (fb->offset != -1)
7507                         field->offset = fb->offset;
7508                 field->parent = klass;
7509                 fb->handle = field;
7510                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7511
7512                 if (fb->def_value) {
7513                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7514                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7515                         field->def_value = g_new0 (MonoConstant, 1);
7516                         idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7517                         /* Copy the data from the blob since it might get realloc-ed */
7518                         p = assembly->blob.data + idx;
7519                         len = mono_metadata_decode_blob_size (p, &p2);
7520                         len += p2 - p;
7521                         field->def_value->value = g_malloc (len);
7522                         memcpy (field->def_value->value, p, len);
7523                 }
7524         }
7525         mono_class_layout_fields (klass);
7526 }
7527
7528 static void
7529 typebuilder_setup_properties (MonoClass *klass)
7530 {
7531         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7532         MonoReflectionPropertyBuilder *pb;
7533         int i;
7534
7535         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7536         klass->property.first = 0;
7537         klass->property.last = klass->property.count;
7538
7539         klass->properties = g_new0 (MonoProperty, klass->property.count);
7540         for (i = 0; i < klass->property.count; ++i) {
7541                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7542                 klass->properties [i].parent = klass;
7543                 klass->properties [i].attrs = pb->attrs;
7544                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7545                 if (pb->get_method)
7546                         klass->properties [i].get = pb->get_method->mhandle;
7547                 if (pb->set_method)
7548                         klass->properties [i].set = pb->set_method->mhandle;
7549         }
7550 }
7551
7552 MonoReflectionEvent *
7553 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7554 {
7555         MonoEvent *event = g_new0 (MonoEvent, 1);
7556         MonoClass *klass;
7557         int j;
7558
7559         klass = my_mono_class_from_mono_type (tb->type.type);
7560
7561         event->parent = klass;
7562         event->attrs = eb->attrs;
7563         event->name = mono_string_to_utf8 (eb->name);
7564         if (eb->add_method)
7565                 event->add = eb->add_method->mhandle;
7566         if (eb->remove_method)
7567                 event->remove = eb->remove_method->mhandle;
7568         if (eb->raise_method)
7569                 event->raise = eb->raise_method->mhandle;
7570
7571         if (eb->other_methods) {
7572                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7573                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7574                         MonoReflectionMethodBuilder *mb = 
7575                                 mono_array_get (eb->other_methods,
7576                                                 MonoReflectionMethodBuilder*, j);
7577                         event->other [j] = mb->mhandle;
7578                 }
7579         }
7580
7581         return mono_event_get_object (mono_object_domain (tb), klass, event);
7582 }
7583
7584 static void
7585 typebuilder_setup_events (MonoClass *klass)
7586 {
7587         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7588         MonoReflectionEventBuilder *eb;
7589         int i, j;
7590
7591         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7592         klass->event.first = 0;
7593         klass->event.last = klass->event.count;
7594
7595         klass->events = g_new0 (MonoEvent, klass->event.count);
7596         for (i = 0; i < klass->event.count; ++i) {
7597                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7598                 klass->events [i].parent = klass;
7599                 klass->events [i].attrs = eb->attrs;
7600                 klass->events [i].name = mono_string_to_utf8 (eb->name);
7601                 if (eb->add_method)
7602                         klass->events [i].add = eb->add_method->mhandle;
7603                 if (eb->remove_method)
7604                         klass->events [i].remove = eb->remove_method->mhandle;
7605                 if (eb->raise_method)
7606                         klass->events [i].raise = eb->raise_method->mhandle;
7607
7608                 if (eb->other_methods) {
7609                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7610                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7611                                 MonoReflectionMethodBuilder *mb = 
7612                                         mono_array_get (eb->other_methods,
7613                                                                         MonoReflectionMethodBuilder*, j);
7614                                 klass->events [i].other [j] = mb->mhandle;
7615                         }
7616                 }
7617         }
7618 }
7619
7620 MonoReflectionType*
7621 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7622 {
7623         MonoClass *klass;
7624         MonoReflectionType* res;
7625
7626         MONO_ARCH_SAVE_REGS;
7627
7628         klass = my_mono_class_from_mono_type (tb->type.type);
7629
7630         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7631
7632         /*
7633          * Fields to set in klass:
7634          * the various flags: delegate/unicode/contextbound etc.
7635          * nested_classes
7636          */
7637         klass->flags = tb->attrs;
7638
7639         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7640                 /* No need to fully construct the type */
7641                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7642
7643         /* enums are done right away */
7644         if (!klass->enumtype)
7645                 ensure_runtime_vtable (klass);
7646
7647         /* fields and object layout */
7648         if (klass->parent) {
7649                 if (!klass->parent->size_inited)
7650                         mono_class_init (klass->parent);
7651                 klass->instance_size += klass->parent->instance_size;
7652                 klass->class_size += klass->parent->class_size;
7653                 klass->min_align = klass->parent->min_align;
7654         } else {
7655                 klass->instance_size = sizeof (MonoObject);
7656                 klass->min_align = 1;
7657         }
7658
7659         /* FIXME: handle packing_size and instance_size */
7660         typebuilder_setup_fields (klass);
7661
7662         typebuilder_setup_properties (klass);
7663
7664         typebuilder_setup_events (klass);
7665
7666         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7667         /* with enums res == tb: need to fix that. */
7668         if (!klass->enumtype)
7669                 g_assert (res != (MonoReflectionType*)tb);
7670         return res;
7671 }
7672
7673 MonoReflectionGenericParam *
7674 mono_reflection_define_generic_parameter (MonoReflectionTypeBuilder *tb, MonoReflectionMethodBuilder *mb, MonoString *name, guint32 index)
7675 {
7676         static MonoClass *System_Reflection_MonoGenericParam;
7677         MonoImage *image;
7678         MonoGenericParam *param;
7679         MonoReflectionGenericParam *res;
7680         MonoDomain *domain;
7681
7682         if (!System_Reflection_MonoGenericParam) {
7683                 System_Reflection_MonoGenericParam = mono_class_from_name (
7684                         mono_defaults.corlib, "System.Reflection", "MonoGenericParam");
7685                 g_assert (System_Reflection_MonoGenericParam);
7686         }
7687
7688         param = g_new0 (MonoGenericParam, 1);
7689
7690         if (mb)
7691                 tb = (MonoReflectionTypeBuilder *) mb->type;
7692
7693         domain = mono_object_domain (tb);
7694         image = (MonoImage*)tb->module->dynamic_image;
7695
7696         param->method = NULL;
7697         param->name = mono_string_to_utf8 (name);
7698         param->num = index;
7699
7700         res = (MonoReflectionGenericParam *)mono_object_new (domain, System_Reflection_MonoGenericParam);
7701         res->type.type = g_new0 (MonoType, 1);
7702         res->type.type->type = mb ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7703         res->type.type->data.generic_param = param;
7704
7705         res->refobj = mb ? (MonoObject *) mb : (MonoObject *) tb;
7706         res->index = index;
7707         res->name = name;
7708
7709         return res;
7710 }
7711
7712 void
7713 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7714 {
7715         MonoGenericParam *param;
7716         MonoReflectionMethodBuilder *mb = NULL;
7717         MonoReflectionTypeBuilder *tb;
7718         MonoImage *image;
7719         int count, i;
7720
7721         param = gparam->type.type->data.generic_param;
7722         count = gparam->constraints ? mono_array_length (gparam->constraints) : 0;
7723         param->constraints = g_new0 (MonoClass *, count + 1);
7724         for (i = 0; i < count; i++) {
7725                 MonoReflectionType *constraint = mono_array_get (gparam->constraints, MonoReflectionType *, i);
7726
7727                 param->constraints [i] = mono_class_from_mono_type (constraint->type);
7728         }
7729
7730         if (!strcmp (gparam->refobj->vtable->klass->name, "MethodBuilder")) {
7731                 mb = (MonoReflectionMethodBuilder *) gparam->refobj;
7732                 tb = (MonoReflectionTypeBuilder *) mb->type;
7733         } else
7734                 tb = (MonoReflectionTypeBuilder *) gparam->refobj;
7735
7736         image = (MonoImage*)tb->module->dynamic_image;
7737
7738         param->pklass = mono_class_from_generic_parameter (param, image, mb != NULL);
7739         param->pklass->reflection_info = gparam;
7740
7741         gparam->initialized = TRUE;
7742 }
7743
7744 MonoArray *
7745 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7746 {
7747         MonoDynamicImage *assembly = sig->module->dynamic_image;
7748         guint32 na = mono_array_length (sig->arguments);
7749         guint32 buflen, i;
7750         MonoArray *result;
7751         char *buf, *p;
7752
7753         MONO_ARCH_SAVE_REGS;
7754
7755         p = buf = g_malloc (10 + na * 10);
7756
7757         mono_metadata_encode_value (0x07, p, &p);
7758         mono_metadata_encode_value (na, p, &p);
7759         for (i = 0; i < na; ++i) {
7760                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7761                 encode_reflection_type (assembly, type, p, &p);
7762         }
7763
7764         buflen = p - buf;
7765         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7766         p = mono_array_addr (result, char, 0);
7767         memcpy (p, buf, buflen);
7768         g_free (buf);
7769
7770         return result;
7771 }
7772
7773 MonoArray *
7774 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7775 {
7776         MonoDynamicImage *assembly = sig->module->dynamic_image;
7777         guint32 na = mono_array_length (sig->arguments);
7778         guint32 buflen, i;
7779         MonoArray *result;
7780         char *buf, *p;
7781
7782         MONO_ARCH_SAVE_REGS;
7783
7784         p = buf = g_malloc (10 + na * 10);
7785
7786         mono_metadata_encode_value (0x06, p, &p);
7787         for (i = 0; i < na; ++i) {
7788                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7789                 encode_reflection_type (assembly, type, p, &p);
7790         }
7791
7792         buflen = p - buf;
7793         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7794         p = mono_array_addr (result, char, 0);
7795         memcpy (p, buf, buflen);
7796         g_free (buf);
7797
7798         return result;
7799 }
7800
7801 void 
7802 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7803 {
7804         ReflectionMethodBuilder rmb;
7805         MonoMethodSignature *sig;
7806         int i;
7807
7808         sig = dynamic_method_to_signature (mb);
7809
7810         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7811
7812         /*
7813          * Resolve references.
7814          */
7815         rmb.nrefs = mb->nrefs;
7816         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7817         for (i = 0; i < mb->nrefs; ++i) {
7818                 gpointer ref = resolve_object (mb->module->image, 
7819                                                mono_array_get (mb->refs, MonoObject*, i));
7820                 if (!ref) {
7821                         g_free (rmb.refs);
7822                         mono_raise_exception (mono_get_exception_type_load (NULL));
7823                         return;
7824                 }
7825                 rmb.refs [i] = ref;
7826         }               
7827
7828         /* FIXME: class */
7829         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7830
7831         g_free (rmb.refs);
7832
7833         /* ilgen is no longer needed */
7834         mb->ilgen = NULL;
7835 }
7836
7837 /**
7838  * mono_reflection_lookup_dynamic_token:
7839  *
7840  *  Finish the Builder object pointed to by TOKEN and return the corresponding
7841  * runtime structure.
7842  */
7843 gpointer
7844 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7845 {
7846         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7847         MonoObject *obj;
7848
7849         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7850         g_assert (obj);
7851
7852         return resolve_object (image, obj);
7853 }
7854
7855 static gpointer
7856 resolve_object (MonoImage *image, MonoObject *obj)
7857 {
7858         gpointer result = NULL;
7859
7860         if (strcmp (obj->vtable->klass->name, "String") == 0) {
7861                 result = mono_string_intern ((MonoString*)obj);
7862                 g_assert (result);
7863         }
7864         else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7865                 MonoReflectionType *tb = (MonoReflectionType*)obj;
7866                 result = mono_class_from_mono_type (tb->type);
7867                 g_assert (result);
7868         }
7869         else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7870                 result = ((MonoReflectionMethod*)obj)->method;
7871                 g_assert (result);
7872         }
7873         else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7874                 result = ((MonoReflectionMethod*)obj)->method;
7875                 g_assert (result);
7876         }
7877         else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7878                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7879                 result = mb->mhandle;
7880                 if (!result) {
7881                         /* Type is not yet created */
7882                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7883
7884                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7885
7886                         /*
7887                          * Hopefully this has been filled in by calling CreateType() on the
7888                          * TypeBuilder.
7889                          */
7890                         /**
7891                          * TODO: This won't work if the application finishes another 
7892                          * TypeBuilder instance instead of this one.
7893                          */
7894                         result = mb->mhandle;
7895                 }
7896         }
7897         else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7898                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7899
7900                 result = cb->mhandle;
7901                 if (!result) {
7902                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7903
7904                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7905                         result = cb->mhandle;
7906                 }
7907         }
7908         else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7909                 result = ((MonoReflectionField*)obj)->field;
7910                 g_assert (result);
7911         }
7912         else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7913                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7914                 result = fb->handle;
7915
7916                 if (!result) {
7917                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7918
7919                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7920                         result = fb->handle;
7921                 }
7922         }
7923         else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7924                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7925                 MonoClass *klass;
7926
7927                 klass = tb->type.type->data.klass;
7928                 if (klass->wastypebuilder) {
7929                         /* Already created */
7930                         result = klass;
7931                 }
7932                 else {
7933                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7934                         result = tb->type.type->data.klass;
7935                         g_assert (result);
7936                 }
7937         }
7938         else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7939                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7940                 MonoMethodSignature *sig;
7941                 int nargs, i;
7942
7943                 if (helper->arguments)
7944                         nargs = mono_array_length (helper->arguments);
7945                 else
7946                         nargs = 0;
7947
7948                 sig = mono_metadata_signature_alloc (image, nargs);
7949                 sig->explicit_this = helper->call_conv & 64;
7950                 sig->hasthis = helper->call_conv & 32;
7951
7952                 if (helper->call_conv == 0) /* unmanaged */
7953                         sig->call_convention = helper->unmanaged_call_conv - 1;
7954                 else
7955                         if (helper->call_conv & 0x02)
7956                                 sig->call_convention = MONO_CALL_VARARG;
7957                 else
7958                         sig->call_convention = MONO_CALL_DEFAULT;
7959
7960                 sig->param_count = nargs;
7961                 /* TODO: Copy type ? */
7962                 sig->ret = helper->return_type->type;
7963                 for (i = 0; i < nargs; ++i) {
7964                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7965                         sig->params [i] = rt->type;
7966                 }
7967
7968                 result = sig;
7969         }
7970         else {
7971                 g_print (obj->vtable->klass->name);
7972                 g_assert_not_reached ();
7973         }
7974         return result;
7975 }