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