2004-05-03 Gonzalo Paniagua Javier <gonzalo@ximian.com>
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
8  *
9  */
10 #include <config.h>
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/tokentype.h"
15 #include "mono/metadata/appdomain.h"
16 #include "mono/metadata/opcodes.h"
17 #include "mono/metadata/assembly.h"
18 #include <mono/metadata/exception.h>
19 #include <stdio.h>
20 #include <glib.h>
21 #include <errno.h>
22 #include <time.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include "image.h"
26 #include "cil-coff.h"
27 #include "rawbuffer.h"
28 #include "mono-endian.h"
29 #include "private.h"
30 #include <mono/os/gc_wrapper.h>
31
32 #define TEXT_OFFSET 512
33 #define CLI_H_SIZE 136
34 #define FILE_ALIGN 512
35 #define VIRT_ALIGN 8192
36 #define START_TEXT_RVA  0x00002000
37
38 typedef struct {
39         MonoReflectionILGen *ilgen;
40         MonoReflectionType *rtype;
41         MonoArray *parameters;
42         MonoArray *generic_params;
43         MonoArray *pinfo;
44         guint32 attrs;
45         guint32 iattrs;
46         guint32 call_conv;
47         guint32 *table_idx; /* note: it's a pointer */
48         MonoArray *code;
49         MonoObject *type;
50         MonoString *name;
51         MonoBoolean init_locals;
52         MonoArray *return_modreq;
53         MonoArray *return_modopt;
54         MonoArray *param_modreq;
55         MonoArray *param_modopt;
56         MonoArray *permissions;
57         MonoMethod *mhandle;
58         guint32 nrefs;
59         gpointer *refs;
60 } ReflectionMethodBuilder;
61
62 const unsigned char table_sizes [64] = {
63         MONO_MODULE_SIZE,
64         MONO_TYPEREF_SIZE,
65         MONO_TYPEDEF_SIZE,
66         0,
67         MONO_FIELD_SIZE,
68         0,
69         MONO_METHOD_SIZE,
70         0,
71         MONO_PARAM_SIZE,
72         MONO_INTERFACEIMPL_SIZE,
73         MONO_MEMBERREF_SIZE,    /* 0x0A */
74         MONO_CONSTANT_SIZE,
75         MONO_CUSTOM_ATTR_SIZE,
76         MONO_FIELD_MARSHAL_SIZE,
77         MONO_DECL_SECURITY_SIZE,
78         MONO_CLASS_LAYOUT_SIZE,
79         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
80         MONO_STAND_ALONE_SIGNATURE_SIZE,
81         MONO_EVENT_MAP_SIZE,
82         0,
83         MONO_EVENT_SIZE,
84         MONO_PROPERTY_MAP_SIZE,
85         0,
86         MONO_PROPERTY_SIZE,
87         MONO_METHOD_SEMA_SIZE,
88         MONO_METHODIMPL_SIZE,
89         MONO_MODULEREF_SIZE,    /* 0x1A */
90         MONO_TYPESPEC_SIZE,
91         MONO_IMPLMAP_SIZE,      
92         MONO_FIELD_RVA_SIZE,
93         0,
94         0,
95         MONO_ASSEMBLY_SIZE,     /* 0x20 */
96         MONO_ASSEMBLY_PROCESSOR_SIZE,
97         MONO_ASSEMBLYOS_SIZE,
98         MONO_ASSEMBLYREF_SIZE,
99         MONO_ASSEMBLYREFPROC_SIZE,
100         MONO_ASSEMBLYREFOS_SIZE,
101         MONO_FILE_SIZE,
102         MONO_EXP_TYPE_SIZE,
103         MONO_MANIFEST_SIZE,
104         MONO_NESTED_CLASS_SIZE,
105
106         MONO_GENERICPARAM_SIZE, /* 0x2A */
107         MONO_METHODSPEC_SIZE,
108         MONO_GENPARCONSTRAINT_SIZE,
109
110         0       /* 0x2D */
111 };
112
113 /**
114  * These macros can be used to allocate long living atomic data so it won't be
115  * tracked by the garbage collector. We use libgc because it's apparently faster
116  * than g_malloc.
117  */
118 #ifdef HAVE_BOEHM_GC
119 #define ALLOC_ATOMIC(size) GC_MALLOC_ATOMIC (size)
120 #define FREE_ATOMIC(ptr)
121 #define REALLOC_ATOMIC(ptr, size) GC_REALLOC ((ptr), (size))
122 #else
123 #define ALLOC_ATOMIC(size) g_malloc (size)
124 #define FREE_ATOMIC(ptr) g_free (ptr)
125 #define REALLOC_ATOMIC(ptr, size) g_realloc ((ptr), (size))
126 #endif
127
128 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
129 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
130 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
131 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method);
132 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb);
133 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
134 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
135 static void    mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
136 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
137 static char*   type_get_qualified_name (MonoType *type, MonoAssembly *ass);
138 static void    ensure_runtime_vtable (MonoClass *klass);
139 static gpointer resolve_object (MonoImage *image, MonoObject *obj);
140 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf);
141 static guint32 type_get_signature_size (MonoType *type);
142
143
144 static void
145 alloc_table (MonoDynamicTable *table, guint nrows)
146 {
147         table->rows = nrows;
148         g_assert (table->columns);
149         if (nrows + 1 >= table->alloc_rows) {
150                 while (nrows + 1 >= table->alloc_rows)
151                         if (table->alloc_rows == 0)
152                                 table->alloc_rows = 16;
153                         else
154                                 table->alloc_rows *= 2;
155
156                 if (table->values)
157                         table->values = REALLOC_ATOMIC (table->values, (table->alloc_rows) * table->columns * sizeof (guint32));
158                 else
159                         table->values = ALLOC_ATOMIC ((table->alloc_rows) * table->columns * sizeof (guint32));
160         }
161 }
162
163 static void
164 make_room_in_stream (MonoDynamicStream *stream, int size)
165 {
166         while (stream->alloc_size <= size) {
167                 if (stream->alloc_size < 4096)
168                         stream->alloc_size = 4096;
169                 else
170                         stream->alloc_size *= 2;
171         }
172         if (stream->data)
173                 stream->data = REALLOC_ATOMIC (stream->data, stream->alloc_size);
174         else
175                 stream->data = ALLOC_ATOMIC (stream->alloc_size);
176 }       
177
178 static guint32
179 string_heap_insert (MonoDynamicStream *sh, const char *str)
180 {
181         guint32 idx;
182         guint32 len;
183         gpointer oldkey, oldval;
184
185         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
186                 return GPOINTER_TO_UINT (oldval);
187
188         len = strlen (str) + 1;
189         idx = sh->index;
190         if (idx + len > sh->alloc_size)
191                 make_room_in_stream (sh, idx + len);
192
193         /*
194          * We strdup the string even if we already copy them in sh->data
195          * so that the string pointers in the hash remain valid even if
196          * we need to realloc sh->data. We may want to avoid that later.
197          */
198         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
199         memcpy (sh->data + idx, str, len);
200         sh->index += len;
201         return idx;
202 }
203
204 static void
205 string_heap_init (MonoDynamicStream *sh)
206 {
207         sh->index = 0;
208         sh->alloc_size = 4096;
209         sh->data = ALLOC_ATOMIC (4096);
210         sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
211         string_heap_insert (sh, "");
212 }
213
214 #if 0 /* never used */
215 static void
216 string_heap_free (MonoDynamicStream *sh)
217 {
218         FREE_ATOMIC (sh->data);
219         g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
220         g_hash_table_destroy (sh->hash);
221 }
222 #endif
223
224 static guint32
225 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
226 {
227         guint32 idx;
228         if (stream->alloc_size < stream->index + len)
229                 make_room_in_stream (stream, stream->index + len);
230         memcpy (stream->data + stream->index, data, len);
231         idx = stream->index;
232         stream->index += len;
233         /* 
234          * align index? Not without adding an additional param that controls it since
235          * we may store a blob value in pieces.
236          */
237         return idx;
238 }
239
240 static guint32
241 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
242 {
243         guint32 idx;
244         if (stream->alloc_size < stream->index + len)
245                 make_room_in_stream (stream, stream->index + len);
246         memset (stream->data + stream->index, 0, len);
247         idx = stream->index;
248         stream->index += len;
249         return idx;
250 }
251
252 static void
253 stream_data_align (MonoDynamicStream *stream)
254 {
255         char buf [4] = {0};
256         guint32 count = stream->index % 4;
257
258         /* we assume the stream data will be aligned */
259         if (count)
260                 mono_image_add_stream_data (stream, buf, 4 - count);
261 }
262
263 static int
264 mono_blob_entry_hash (const char* str)
265 {
266         guint len, h;
267         const char *end;
268         len = mono_metadata_decode_blob_size (str, &str);
269         if (len > 0) {
270                 end = str + len;
271                 h = *str;
272                 for (str += 1; str < end; str++)
273                         h = (h << 5) - h + *str;
274                 return h;
275         }
276         else
277                 return 0;
278 }
279
280 static gboolean
281 mono_blob_entry_equal (const char *str1, const char *str2) {
282         int len, len2;
283         const char *end1;
284         const char *end2;
285         len = mono_metadata_decode_blob_size (str1, &end1);
286         len2 = mono_metadata_decode_blob_size (str2, &end2);
287         if (len != len2)
288                 return 0;
289         return memcmp (end1, end2, len) == 0;
290 }
291
292 static guint32
293 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
294 {
295         guint32 idx;
296         char *copy;
297         gpointer oldkey, oldval;
298         
299         copy = ALLOC_ATOMIC (s1+s2);
300         memcpy (copy, b1, s1);
301         memcpy (copy + s1, b2, s2);
302         if (mono_g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
303                 FREE_ATOMIC (copy);
304                 idx = GPOINTER_TO_UINT (oldval);
305         } else {
306                 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
307                 mono_image_add_stream_data (&assembly->blob, b2, s2);
308                 mono_g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
309         }
310         return idx;
311 }
312
313 /*
314  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
315  * dest may be misaligned.
316  */
317 static void
318 swap_with_size (char *dest, const char* val, int len, int nelem) {
319 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
320         int elem;
321
322         for (elem = 0; elem < nelem; ++elem) {
323                 switch (len) {
324                 case 1:
325                         *dest = *val;
326                         break;
327                 case 2:
328                         dest [0] = val [1];
329                         dest [1] = val [0];
330                         break;
331                 case 4:
332                         dest [0] = val [3];
333                         dest [1] = val [2];
334                         dest [2] = val [1];
335                         dest [3] = val [0];
336                         break;
337                 case 8:
338                         dest [0] = val [7];
339                         dest [1] = val [6];
340                         dest [2] = val [5];
341                         dest [3] = val [4];
342                         dest [4] = val [3];
343                         dest [5] = val [2];
344                         dest [6] = val [1];
345                         dest [7] = val [0];
346                         break;
347                 default:
348                         g_assert_not_reached ();
349                 }
350                 dest += len;
351                 val += len;
352         }
353 #else
354         memcpy (dest, val, len * nelem);
355 #endif
356 }
357
358 static guint32
359 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
360 {
361         char blob_size [64];
362         char *b = blob_size;
363         guint32 idx = 0, len;
364
365         len = str->length * 2;
366         mono_metadata_encode_value (len, b, &b);
367 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
368         {
369                 char *swapped = g_malloc (2 * mono_string_length (str));
370                 const char *p = (const char*)mono_string_chars (str);
371
372                 swap_with_size (swapped, p, 2, mono_string_length (str));
373                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
374                 g_free (swapped);
375         }
376 #else
377         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
378 #endif
379         return idx;
380 }
381
382 /* modified version needed to handle building corlib */
383 static MonoClass*
384 my_mono_class_from_mono_type (MonoType *type) {
385         switch (type->type) {
386         case MONO_TYPE_ARRAY:
387         case MONO_TYPE_PTR:
388         case MONO_TYPE_SZARRAY:
389         case MONO_TYPE_GENERICINST:
390                 return mono_class_from_mono_type (type);
391         case MONO_TYPE_VAR:
392         case MONO_TYPE_MVAR:
393                 g_assert (type->data.generic_param->pklass);
394                 return type->data.generic_param->pklass;
395         default:
396                 /* should be always valid when we reach this case... */
397                 return type->data.klass;
398         }
399 }
400
401 static void
402 encode_generic_inst (MonoDynamicImage *assembly, MonoGenericInst *ginst, char *p, char **endbuf)
403 {
404         int i;
405
406         if (!ginst) {
407                 g_assert_not_reached ();
408                 return;
409         }
410
411         mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
412         encode_type (assembly, ginst->generic_type, p, &p);
413         mono_metadata_encode_value (ginst->type_argc, p, &p);
414         for (i = 0; i < ginst->type_argc; ++i)
415                 encode_type (assembly, ginst->type_argv [i], p, &p);
416
417         *endbuf = p;
418 }
419
420 static void
421 encode_type (MonoDynamicImage *assembly, MonoType *type, char *p, char **endbuf)
422 {
423         if (!type) {
424                 g_assert_not_reached ();
425                 return;
426         }
427                 
428         if (type->byref)
429                 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
430
431         switch (type->type){
432         case MONO_TYPE_VOID:
433         case MONO_TYPE_BOOLEAN:
434         case MONO_TYPE_CHAR:
435         case MONO_TYPE_I1:
436         case MONO_TYPE_U1:
437         case MONO_TYPE_I2:
438         case MONO_TYPE_U2:
439         case MONO_TYPE_I4:
440         case MONO_TYPE_U4:
441         case MONO_TYPE_I8:
442         case MONO_TYPE_U8:
443         case MONO_TYPE_R4:
444         case MONO_TYPE_R8:
445         case MONO_TYPE_I:
446         case MONO_TYPE_U:
447         case MONO_TYPE_STRING:
448         case MONO_TYPE_OBJECT:
449         case MONO_TYPE_TYPEDBYREF:
450                 mono_metadata_encode_value (type->type, p, &p);
451                 break;
452         case MONO_TYPE_PTR:
453                 mono_metadata_encode_value (type->type, p, &p);
454                 encode_type (assembly, type->data.type, p, &p);
455                 break;
456         case MONO_TYPE_SZARRAY:
457                 mono_metadata_encode_value (type->type, p, &p);
458                 encode_type (assembly, &type->data.klass->byval_arg, p, &p);
459                 break;
460
461         case MONO_TYPE_VALUETYPE:
462         case MONO_TYPE_CLASS: {
463                 MonoClass *k = mono_class_from_mono_type (type);
464                 mono_metadata_encode_value (type->type, p, &p);
465                 /*
466                  * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
467                  * otherwise two typerefs could point to the same type, leading to
468                  * verification errors.
469                  */
470                 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, &k->byval_arg), p, &p);
471                 break;
472         }
473
474         case MONO_TYPE_ARRAY:
475                 mono_metadata_encode_value (type->type, p, &p);
476                 encode_type (assembly, &type->data.array->eklass->byval_arg, p, &p);
477                 mono_metadata_encode_value (type->data.array->rank, p, &p);
478                 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
479                 mono_metadata_encode_value (0, p, &p);
480                 break;
481         case MONO_TYPE_GENERICINST:
482                 encode_generic_inst (assembly, type->data.generic_inst, p, &p);
483                 break;
484         case MONO_TYPE_VAR:
485         case MONO_TYPE_MVAR:
486                 mono_metadata_encode_value (type->type, p, &p);
487                 mono_metadata_encode_value (type->data.generic_param->num, p, &p);
488                 break;
489
490         default:
491                 g_error ("need to encode type %x", type->type);
492         }
493         *endbuf = p;
494 }
495
496 static void
497 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, char *p, char **endbuf)
498 {
499         if (!type) {
500                 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
501                 return;
502         }
503         if (type->type) {
504                 encode_type (assembly, type->type, p, endbuf);
505                 return;
506         }
507
508         g_assert_not_reached ();
509
510 }
511
512 static void
513 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, char *p, char **endbuf)
514 {
515         int i;
516
517         if (modreq) {
518                 for (i = 0; i < mono_array_length (modreq); ++i) {
519                         MonoReflectionType *mod = mono_array_get (modreq, MonoReflectionType*, i);
520                         *p = MONO_TYPE_CMOD_REQD;
521                         p++;
522                         mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
523                 }
524         }
525         if (modopt) {
526                 for (i = 0; i < mono_array_length (modopt); ++i) {
527                         MonoReflectionType *mod = mono_array_get (modopt, MonoReflectionType*, i);
528                         *p = MONO_TYPE_CMOD_OPT;
529                         p++;
530                         mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, mod->type), p, &p);
531                 }
532         }
533         *endbuf = p;
534 }
535
536 static guint32
537 generic_inst_get_signature_size (MonoGenericInst *ginst)
538 {
539         guint32 size = 0;
540         int i;
541
542         if (!ginst) {
543                 g_assert_not_reached ();
544         }
545
546         size += 1 + type_get_signature_size (ginst->generic_type);
547         size += 4;
548         for (i = 0; i < ginst->type_argc; ++i)
549                 size += type_get_signature_size (ginst->type_argv [i]);
550
551         return size;
552 }
553
554 static guint32
555 type_get_signature_size (MonoType *type)
556 {
557         guint32 size = 0;
558
559         if (!type) {
560                 g_assert_not_reached ();
561         }
562                 
563         if (type->byref)
564                 size++;
565
566         switch (type->type){
567         case MONO_TYPE_VOID:
568         case MONO_TYPE_BOOLEAN:
569         case MONO_TYPE_CHAR:
570         case MONO_TYPE_I1:
571         case MONO_TYPE_U1:
572         case MONO_TYPE_I2:
573         case MONO_TYPE_U2:
574         case MONO_TYPE_I4:
575         case MONO_TYPE_U4:
576         case MONO_TYPE_I8:
577         case MONO_TYPE_U8:
578         case MONO_TYPE_R4:
579         case MONO_TYPE_R8:
580         case MONO_TYPE_I:
581         case MONO_TYPE_U:
582         case MONO_TYPE_STRING:
583         case MONO_TYPE_OBJECT:
584         case MONO_TYPE_TYPEDBYREF:
585                 return size + 1;
586         case MONO_TYPE_PTR:
587                 return size + 1 + type_get_signature_size (type->data.type);
588         case MONO_TYPE_SZARRAY:
589                 return size + 1 + type_get_signature_size (&type->data.klass->byval_arg);
590
591         case MONO_TYPE_VALUETYPE:
592         case MONO_TYPE_CLASS:
593                 return size + 5;
594
595         case MONO_TYPE_ARRAY:
596                 return size + 7 + type_get_signature_size (&type->data.array->eklass->byval_arg);
597         case MONO_TYPE_GENERICINST:
598                 return size + generic_inst_get_signature_size (type->data.generic_inst);
599         case MONO_TYPE_VAR:
600         case MONO_TYPE_MVAR:
601                 return size + 5;
602
603         default:
604                 g_error ("need to encode type %x", type->type);
605                 return size;
606         }
607 }
608
609 static guint32
610 method_get_signature_size (MonoMethodSignature *sig)
611 {
612         guint32 size;
613         int i;
614
615         size = type_get_signature_size (sig->ret);
616         for (i = 0; i < sig->param_count; i++)
617                 size += type_get_signature_size (sig->params [i]);
618
619         if (sig->generic_param_count)
620                 size += 4;
621
622         return size;    
623 }
624
625 static guint32
626 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
627 {
628         char *buf;
629         char *p;
630         int i;
631         guint32 nparams =  sig->param_count;
632         guint32 size = 11 + method_get_signature_size (sig);
633         guint32 idx;
634         char blob_size [6];
635         char *b = blob_size;
636
637         if (!assembly->save)
638                 return 0;
639
640         p = buf = g_malloc (size);
641         /*
642          * FIXME: vararg, explicit_this, differenc call_conv values...
643          */
644         *p = sig->call_convention;
645         if (sig->hasthis)
646                 *p |= 0x20; /* hasthis */
647         if (sig->generic_param_count)
648                 *p |= 0x10; /* generic */
649         p++;
650         if (sig->generic_param_count)
651                 mono_metadata_encode_value (sig->generic_param_count, p, &p);
652         mono_metadata_encode_value (nparams, p, &p);
653         encode_type (assembly, sig->ret, p, &p);
654         for (i = 0; i < nparams; ++i)
655                 encode_type (assembly, sig->params [i], p, &p);
656         /* store length */
657         g_assert (p - buf < size);
658         mono_metadata_encode_value (p-buf, b, &b);
659         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
660         g_free (buf);
661         return idx;
662 }
663
664 static guint32
665 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
666 {
667         /*
668          * FIXME: reuse code from method_encode_signature().
669          */
670         char *buf;
671         char *p;
672         int i;
673         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
674         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
675         guint32 size = 21 + nparams * 20;
676         guint32 idx;
677         char blob_size [6];
678         char *b = blob_size;
679
680         p = buf = g_malloc (size);
681         /* LAMESPEC: all the call conv spec is foobared */
682         *p = mb->call_conv & 0x60; /* has-this, explicit-this */
683         if (mb->call_conv & 2)
684                 *p |= 0x5; /* vararg */
685         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
686                 *p |= 0x20; /* hasthis */
687         if (ngparams)
688                 *p |= 0x10; /* generic */
689         p++;
690         if (ngparams)
691                 mono_metadata_encode_value (ngparams, p, &p);
692         mono_metadata_encode_value (nparams, p, &p);
693         encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, p, &p);
694         encode_reflection_type (assembly, mb->rtype, p, &p);
695         for (i = 0; i < nparams; ++i) {
696                 MonoArray *modreq = NULL;
697                 MonoArray *modopt = NULL;
698                 MonoReflectionType *pt;
699
700                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
701                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
702                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
703                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
704                 encode_custom_modifiers (assembly, modreq, modopt, p, &p);
705                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
706                 encode_reflection_type (assembly, pt, p, &p);
707         }
708         /* store length */
709         g_assert (p - buf < size);
710         mono_metadata_encode_value (p-buf, b, &b);
711         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
712         g_free (buf);
713         return idx;
714 }
715
716 static guint32
717 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
718 {
719         MonoDynamicTable *table;
720         guint32 *values;
721         char *p;
722         guint32 idx, sig_idx, size;
723         guint nl = mono_array_length (ilgen->locals);
724         char *buf;
725         char blob_size [6];
726         char *b = blob_size;
727         int i;
728
729         size = 10 + nl * 10;
730         p = buf = g_malloc (size);
731         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
732         idx = table->next_idx ++;
733         table->rows ++;
734         alloc_table (table, table->rows);
735         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
736
737         mono_metadata_encode_value (0x07, p, &p);
738         mono_metadata_encode_value (nl, p, &p);
739         for (i = 0; i < nl; ++i) {
740                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
741                 
742                 if (lb->is_pinned)
743                         mono_metadata_encode_value (MONO_TYPE_PINNED, p, &p);
744                 
745                 encode_reflection_type (assembly, lb->type, p, &p);
746         }
747         g_assert (p - buf < size);
748         mono_metadata_encode_value (p-buf, b, &b);
749         sig_idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
750         g_free (buf);
751
752         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
753
754         return idx;
755 }
756
757 static guint32
758 method_count_clauses (MonoReflectionILGen *ilgen)
759 {
760         guint32 num_clauses = 0;
761         int i;
762
763         MonoILExceptionInfo *ex_info;
764         for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
765                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
766                 if (ex_info->handlers)
767                         num_clauses += mono_array_length (ex_info->handlers);
768                 else
769                         num_clauses++;
770         }
771
772         return num_clauses;
773 }
774
775 static MonoExceptionClause*
776 method_encode_clauses (MonoDynamicImage *assembly,
777                                            MonoReflectionILGen *ilgen, guint32 num_clauses)
778 {
779         MonoExceptionClause *clauses;
780         MonoExceptionClause *clause;
781         MonoILExceptionInfo *ex_info;
782         MonoILExceptionBlock *ex_block;
783         guint32 finally_start;
784         int i, j, clause_index;;
785
786         clauses = g_new0 (MonoExceptionClause, num_clauses);
787
788         clause_index = 0;
789         for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
790                 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
791                 finally_start = ex_info->start + ex_info->len;
792                 g_assert (ex_info->handlers);
793                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
794                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
795                         clause = &(clauses [clause_index]);
796
797                         clause->flags = ex_block->type;
798                         clause->try_offset = ex_info->start;
799
800                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
801                                 clause->try_len = finally_start - ex_info->start;
802                         else
803                                 clause->try_len = ex_info->len;
804                         clause->handler_offset = ex_block->start;
805                         clause->handler_len = ex_block->len;
806                         clause->token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
807                                 mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
808                         if (ex_block->extype) {
809                                 mono_g_hash_table_insert (assembly->tokens,
810                                                                                   GUINT_TO_POINTER (clause->token_or_filter),
811                                                                                   ex_block->extype);
812                         }
813                         finally_start = ex_block->start + ex_block->len;
814
815                         clause_index ++;
816                 }
817         }
818
819         return clauses;
820 }
821
822 static guint32
823 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
824 {
825         char flags = 0;
826         guint32 idx;
827         guint32 code_size;
828         gint32 max_stack, i;
829         gint32 num_locals = 0;
830         gint32 num_exception = 0;
831         gint maybe_small;
832         guint32 fat_flags;
833         char fat_header [12];
834         guint32 *intp;
835         guint16 *shortp;
836         guint32 local_sig = 0;
837         guint32 header_size = 12;
838         MonoArray *code;
839
840         if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
841                         (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
842                         (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
843                         (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
844                 return 0;
845
846         /*if (mb->name)
847                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
848         if (mb->ilgen) {
849                 code = mb->ilgen->code;
850                 code_size = mb->ilgen->code_len;
851                 max_stack = mb->ilgen->max_stack;
852                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
853                 if (mb->ilgen->ex_handlers)
854                         num_exception = method_count_clauses (mb->ilgen);
855         } else {
856                 code = mb->code;
857                 if (code == NULL){
858                         char *name = mono_string_to_utf8 (mb->name);
859                         char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
860                         MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
861                         g_free (str);
862                         g_free (name);
863                         mono_raise_exception (exception);
864                 }
865
866                 code_size = mono_array_length (code);
867                 max_stack = 8; /* we probably need to run a verifier on the code... */
868         }
869
870         /* check for exceptions, maxstack, locals */
871         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
872         if (maybe_small) {
873                 if (code_size < 64 && !(code_size & 1)) {
874                         flags = (code_size << 2) | 0x2;
875                 } else if (code_size < 32 && (code_size & 1)) {
876                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
877                 } else {
878                         goto fat_header;
879                 }
880                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
881                 /* add to the fixup todo list */
882                 if (mb->ilgen && mb->ilgen->num_token_fixups)
883                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
884                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
885                 return assembly->text_rva + idx;
886         } 
887 fat_header:
888         if (num_locals)
889                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
890         /* 
891          * FIXME: need to set also the header size in fat_flags.
892          * (and more sects and init locals flags)
893          */
894         fat_flags =  0x03;
895         if (num_exception)
896                 fat_flags |= METHOD_HEADER_MORE_SECTS;
897         if (mb->init_locals)
898                 fat_flags |= METHOD_HEADER_INIT_LOCALS;
899         fat_header [0] = fat_flags;
900         fat_header [1] = (header_size / 4 ) << 4;
901         shortp = (guint16*)(fat_header + 2);
902         *shortp = GUINT16_TO_LE (max_stack);
903         intp = (guint32*)(fat_header + 4);
904         *intp = GUINT32_TO_LE (code_size);
905         intp = (guint32*)(fat_header + 8);
906         *intp = GUINT32_TO_LE (local_sig);
907         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
908         /* add to the fixup todo list */
909         if (mb->ilgen && mb->ilgen->num_token_fixups)
910                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
911         
912         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
913         if (num_exception) {
914                 unsigned char sheader [4];
915                 MonoExceptionClause clause;
916                 MonoILExceptionInfo * ex_info;
917                 MonoILExceptionBlock * ex_block;
918                 int j;
919
920                 stream_data_align (&assembly->code);
921                 /* always use fat format for now */
922                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
923                 num_exception *= sizeof (MonoExceptionClause);
924                 num_exception += 4; /* include the size of the header */
925                 sheader [1] = num_exception & 0xff;
926                 sheader [2] = (num_exception >> 8) & 0xff;
927                 sheader [3] = (num_exception >> 16) & 0xff;
928                 mono_image_add_stream_data (&assembly->code, sheader, 4);
929                 /* fat header, so we are already aligned */
930                 /* reverse order */
931                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
932                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
933                         if (ex_info->handlers) {
934                                 int finally_start = ex_info->start + ex_info->len;
935                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
936                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
937                                         clause.flags = GUINT32_TO_LE (ex_block->type);
938                                         clause.try_offset = GUINT32_TO_LE (ex_info->start);
939                                         /* need fault, too, probably */
940                                         if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
941                                                 clause.try_len = GUINT32_TO_LE (finally_start - ex_info->start);
942                                         else
943                                                 clause.try_len = GUINT32_TO_LE (ex_info->len);
944                                         clause.handler_offset = GUINT32_TO_LE (ex_block->start);
945                                         clause.handler_len = GUINT32_TO_LE (ex_block->len);
946                                         finally_start = ex_block->start + ex_block->len;
947                                         clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
948                                                         mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
949                                         clause.token_or_filter = GUINT32_TO_LE (clause.token_or_filter);
950                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n", 
951                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
952                                         mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
953                                 }
954                         } else {
955                                 g_error ("No clauses for ex info block %d", i);
956                         }
957                 }
958         }
959         return assembly->text_rva + idx;
960 }
961
962 static guint32
963 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
964 {
965         int i;
966         MonoDynamicTable *table;
967         guint32 *values;
968         
969         table = &assembly->tables [table_idx];
970
971         g_assert (col < table->columns);
972
973         values = table->values + table->columns;
974         for (i = 1; i <= table->rows; ++i) {
975                 if (values [col] == token)
976                         return i;
977                 values += table->columns;
978         }
979         return 0;
980 }
981
982 static GHashTable *dynamic_custom_attrs = NULL;
983
984 static MonoCustomAttrInfo*
985 mono_custom_attrs_from_builders (MonoImage *image, MonoArray *cattrs)
986 {
987         int i, count;
988         MonoCustomAttrInfo *ainfo;
989         MonoReflectionCustomAttr *cattr;
990
991         if (!cattrs)
992                 return NULL;
993         /* FIXME: check in assembly the Run flag is set */
994
995         count = mono_array_length (cattrs);
996
997         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (count - MONO_ZERO_LEN_ARRAY));
998
999         ainfo->image = image;
1000         ainfo->num_attrs = count;
1001         for (i = 0; i < count; ++i) {
1002                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1003                 ainfo->attrs [i].ctor = cattr->ctor->method;
1004                 /* FIXME: might want to memdup the data here */
1005                 ainfo->attrs [i].data = mono_array_addr (cattr->data, char, 0);
1006                 ainfo->attrs [i].data_size = mono_array_length (cattr->data);
1007         }
1008
1009         return ainfo;
1010 }
1011
1012 static void
1013 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1014 {
1015         MonoCustomAttrInfo *ainfo = mono_custom_attrs_from_builders (image, cattrs);
1016
1017         if (!ainfo)
1018                 return;
1019
1020         if (!dynamic_custom_attrs)
1021                 dynamic_custom_attrs = g_hash_table_new (NULL, NULL);
1022
1023         g_hash_table_insert (dynamic_custom_attrs, obj, ainfo);
1024 }
1025
1026 void
1027 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1028 {
1029         /* they are cached, so we don't free them */
1030         if (dynamic_custom_attrs && g_hash_table_lookup (dynamic_custom_attrs, ainfo))
1031                 return;
1032         g_free (ainfo);
1033 }
1034
1035 /*
1036  * idx is the table index of the object
1037  * type is one of CUSTOM_ATTR_*
1038  */
1039 static void
1040 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1041 {
1042         MonoDynamicTable *table;
1043         MonoReflectionCustomAttr *cattr;
1044         guint32 *values;
1045         guint32 count, i, token;
1046         char blob_size [6];
1047         char *p = blob_size;
1048         
1049         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1050         if (!cattrs)
1051                 return;
1052         count = mono_array_length (cattrs);
1053         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1054         table->rows += count;
1055         alloc_table (table, table->rows);
1056         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1057         idx <<= CUSTOM_ATTR_BITS;
1058         idx |= type;
1059         for (i = 0; i < count; ++i) {
1060                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1061                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1062                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
1063                 type = mono_metadata_token_index (token);
1064                 type <<= CUSTOM_ATTR_TYPE_BITS;
1065                 switch (mono_metadata_token_table (token)) {
1066                 case MONO_TABLE_METHOD:
1067                         type |= CUSTOM_ATTR_TYPE_METHODDEF;
1068                         break;
1069                 case MONO_TABLE_MEMBERREF:
1070                         type |= CUSTOM_ATTR_TYPE_MEMBERREF;
1071                         break;
1072                 default:
1073                         g_warning ("got wrong token in custom attr");
1074                         continue;
1075                 }
1076                 values [MONO_CUSTOM_ATTR_TYPE] = type;
1077                 p = blob_size;
1078                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1079                 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1080                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1081                 values += MONO_CUSTOM_ATTR_SIZE;
1082                 ++table->next_idx;
1083         }
1084 }
1085
1086 static void
1087 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token,
1088                                                           MonoArray *permissions)
1089 {
1090         MonoDynamicTable *table;
1091         guint32 *values;
1092         guint32 count, i, idx;
1093         MonoReflectionPermissionSet *perm;
1094
1095         if (!permissions)
1096                 return;
1097
1098         count = mono_array_length (permissions);
1099         table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1100         table->rows += count;
1101         alloc_table (table, table->rows);
1102
1103         for (i = 0; i < mono_array_length (permissions); ++i) {
1104                 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1105
1106                 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1107
1108                 idx = mono_metadata_token_index (parent_token);
1109                 idx <<= HAS_DECL_SECURITY_BITS;
1110                 switch (mono_metadata_token_table (parent_token)) {
1111                 case MONO_TABLE_TYPEDEF:
1112                         idx |= HAS_DECL_SECURITY_TYPEDEF;
1113                         break;
1114                 case MONO_TABLE_METHOD:
1115                         idx |= HAS_DECL_SECURITY_METHODDEF;
1116                         break;
1117                 case MONO_TABLE_ASSEMBLY:
1118                         idx |= HAS_DECL_SECURITY_ASSEMBLY;
1119                         break;
1120                 default:
1121                         g_assert_not_reached ();
1122                 }
1123
1124                 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1125                 values [MONO_DECL_SECURITY_PARENT] = idx;
1126                 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1127
1128                 ++table->next_idx;
1129         }
1130 }
1131
1132 /*
1133  * Fill in the MethodDef and ParamDef tables for a method.
1134  * This is used for both normal methods and constructors.
1135  */
1136 static void
1137 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1138 {
1139         MonoDynamicTable *table;
1140         guint32 *values;
1141         char *name;
1142         guint i, count;
1143
1144         /* room in this table is already allocated */
1145         table = &assembly->tables [MONO_TABLE_METHOD];
1146         *mb->table_idx = table->next_idx ++;
1147         mono_g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1148         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1149         name = mono_string_to_utf8 (mb->name);
1150         values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
1151         g_free (name);
1152         values [MONO_METHOD_FLAGS] = mb->attrs;
1153         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1154         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1155         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1156         
1157         table = &assembly->tables [MONO_TABLE_PARAM];
1158         values [MONO_METHOD_PARAMLIST] = table->next_idx;
1159
1160         mono_image_add_decl_security (assembly, 
1161                                                                   mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx),
1162                                                                   mb->permissions);
1163
1164         if (mb->pinfo) {
1165                 MonoDynamicTable *mtable;
1166                 guint32 *mvalues;
1167                 
1168                 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1169                 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1170                 
1171                 count = 0;
1172                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1173                         if (mono_array_get (mb->pinfo, gpointer, i))
1174                                 count++;
1175                 }
1176                 table->rows += count;
1177                 alloc_table (table, table->rows);
1178                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1179                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1180                         MonoReflectionParamBuilder *pb;
1181                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1182                                 values [MONO_PARAM_FLAGS] = pb->attrs;
1183                                 values [MONO_PARAM_SEQUENCE] = i;
1184                                 if (pb->name != NULL) {
1185                                         name = mono_string_to_utf8 (pb->name);
1186                                         values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
1187                                         g_free (name);
1188                                 }
1189                                 else
1190                                         values [MONO_PARAM_NAME] = 0;
1191                                 values += MONO_PARAM_SIZE;
1192                                 if (pb->marshal_info) {
1193                                         mtable->rows++;
1194                                         alloc_table (mtable, mtable->rows);
1195                                         mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1196                                         mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << HAS_FIELD_MARSHAL_BITS) | HAS_FIELD_MARSHAL_PARAMDEF;
1197                                         mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1198                                 }
1199                                 pb->table_idx = table->next_idx++;
1200                         }
1201                 }
1202         }
1203 }
1204
1205 static void
1206 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb,
1207                                                                                            MonoReflectionMethodBuilder *mb)
1208 {
1209         rmb->ilgen = mb->ilgen;
1210         rmb->rtype = mb->rtype;
1211         rmb->parameters = mb->parameters;
1212         rmb->generic_params = mb->generic_params;
1213         rmb->pinfo = mb->pinfo;
1214         rmb->attrs = mb->attrs;
1215         rmb->iattrs = mb->iattrs;
1216         rmb->call_conv = mb->call_conv;
1217         rmb->code = mb->code;
1218         rmb->type = mb->type;
1219         rmb->name = mb->name;
1220         rmb->table_idx = &mb->table_idx;
1221         rmb->init_locals = mb->init_locals;
1222         rmb->return_modreq = mb->return_modreq;
1223         rmb->return_modopt = mb->return_modopt;
1224         rmb->param_modreq = mb->param_modreq;
1225         rmb->param_modopt = mb->param_modopt;
1226         rmb->permissions = mb->permissions;
1227         rmb->mhandle = mb->mhandle;
1228         rmb->nrefs = 0;
1229         rmb->refs = NULL;
1230 }
1231
1232 static void
1233 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb,
1234                                                                                          MonoReflectionCtorBuilder *mb)
1235 {
1236         const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1237
1238         rmb->ilgen = mb->ilgen;
1239         rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1240         rmb->parameters = mb->parameters;
1241         rmb->generic_params = NULL;
1242         rmb->pinfo = mb->pinfo;
1243         rmb->attrs = mb->attrs;
1244         rmb->iattrs = mb->iattrs;
1245         rmb->call_conv = mb->call_conv;
1246         rmb->code = NULL;
1247         rmb->type = mb->type;
1248         rmb->name = mono_string_new (mono_domain_get (), name);
1249         rmb->table_idx = &mb->table_idx;
1250         rmb->init_locals = mb->init_locals;
1251         rmb->return_modreq = NULL;
1252         rmb->return_modopt = NULL;
1253         rmb->param_modreq = mb->param_modreq;
1254         rmb->param_modopt = mb->param_modopt;
1255         rmb->permissions = mb->permissions;
1256         rmb->mhandle = mb->mhandle;
1257         rmb->nrefs = 0;
1258         rmb->refs = NULL;
1259 }
1260
1261 static void
1262 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb,
1263                                                                                           MonoReflectionDynamicMethod *mb)
1264 {
1265         rmb->ilgen = mb->ilgen;
1266         rmb->rtype = mb->rtype;
1267         rmb->parameters = mb->parameters;
1268         rmb->generic_params = NULL;
1269         rmb->pinfo = NULL;
1270         rmb->attrs = mb->attrs;
1271         rmb->iattrs = 0;
1272         rmb->call_conv = mb->call_conv;
1273         rmb->code = NULL;
1274         rmb->type = NULL;
1275         rmb->name = mb->name;
1276         rmb->table_idx = NULL;
1277         rmb->init_locals = mb->init_locals;
1278         rmb->return_modreq = NULL;
1279         rmb->return_modopt = NULL;
1280         rmb->param_modreq = NULL;
1281         rmb->param_modopt = NULL;
1282         rmb->permissions = NULL;
1283         rmb->mhandle = mb->mhandle;
1284         rmb->nrefs = 0;
1285         rmb->refs = NULL;
1286 }       
1287
1288 static void
1289 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1290 {
1291         MonoDynamicTable *table;
1292         guint32 *values;
1293         char *name;
1294         ReflectionMethodBuilder rmb;
1295         int i;
1296
1297         reflection_methodbuilder_from_method_builder (&rmb, mb);
1298
1299         mono_image_basic_method (&rmb, assembly);
1300
1301         if (mb->dll) { /* It's a P/Invoke method */
1302                 guint32 moduleref;
1303                 int charset = mb->charset & 0xf;
1304                 int lasterr = mb->charset & 0x40;
1305                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1306                 table->rows ++;
1307                 alloc_table (table, table->rows);
1308                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1309                 /* map CharSet values to on-disk values */
1310                 
1311                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | (charset ? (charset - 1) * 2: 1) | lasterr;
1312                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1313                 name = mono_string_to_utf8 (mb->dllentry);
1314                 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
1315                 g_free (name);
1316                 name = mono_string_to_utf8 (mb->dll);
1317                 moduleref = string_heap_insert (&assembly->sheap, name);
1318                 g_free (name);
1319                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1320                         table = &assembly->tables [MONO_TABLE_MODULEREF];
1321                         table->rows ++;
1322                         alloc_table (table, table->rows);
1323                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1324                         values [MONO_IMPLMAP_SCOPE] = table->rows;
1325                 }
1326         }
1327
1328         if (mb->override_method) {
1329                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1330                 guint32 tok;
1331                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1332                 table->rows ++;
1333                 alloc_table (table, table->rows);
1334                 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1335                 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1336                 values [MONO_METHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
1337                 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method);
1338                 switch (mono_metadata_token_table (tok)) {
1339                 case MONO_TABLE_MEMBERREF:
1340                         tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODREF;
1341                         break;
1342                 case MONO_TABLE_METHOD:
1343                         tok = (mono_metadata_token_index (tok) << METHODDEFORREF_BITS ) | METHODDEFORREF_METHODDEF;
1344                         break;
1345                 default:
1346                         g_assert_not_reached ();
1347                 }
1348                 values [MONO_METHODIMPL_DECLARATION] = tok;
1349         }
1350
1351         if (mb->generic_params) {
1352                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1353                 table->rows += mono_array_length (mb->generic_params);
1354                 alloc_table (table, table->rows);
1355                 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1356                         guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1357
1358                         mono_image_get_generic_param_info (
1359                                 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1360                 }
1361         }
1362
1363 }
1364
1365 static void
1366 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1367 {
1368         ReflectionMethodBuilder rmb;
1369
1370         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1371
1372         mono_image_basic_method (&rmb, assembly);
1373 }
1374
1375 static char*
1376 type_get_fully_qualified_name (MonoType *type) {
1377         char *name, *result;
1378         MonoClass *klass;
1379         MonoAssembly *ta;
1380
1381         name = mono_type_get_name (type);
1382         klass = my_mono_class_from_mono_type (type);
1383         ta = klass->image->assembly;
1384
1385         /* missing public key */
1386         result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
1387                 name, ta->aname.name,
1388                 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1389                 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
1390         g_free (name);
1391         return result;
1392 }
1393
1394 static char*
1395 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1396         MonoClass *klass;
1397         MonoAssembly *ta;
1398
1399         klass = my_mono_class_from_mono_type (type);
1400         ta = klass->image->assembly;
1401         if (ta == ass || klass->image == mono_defaults.corlib)
1402                 return mono_type_get_name (type);
1403
1404         return type_get_fully_qualified_name (type);
1405 }
1406
1407 static guint32
1408 fieldref_encode_signature (MonoDynamicImage *assembly, MonoType *type)
1409 {
1410         char blob_size [64];
1411         char *b = blob_size;
1412         char *p;
1413         char* buf;
1414         guint32 idx;
1415
1416         if (!assembly->save)
1417                 return 0;
1418
1419         p = buf = g_malloc (64);
1420         
1421         mono_metadata_encode_value (0x06, p, &p);
1422         /* encode custom attributes before the type */
1423         encode_type (assembly, type, p, &p);
1424         g_assert (p-buf < 64);
1425         mono_metadata_encode_value (p-buf, b, &b);
1426         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1427         g_free (buf);
1428         return idx;
1429 }
1430
1431 static guint32
1432 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
1433 {
1434         char blob_size [64];
1435         char *b = blob_size;
1436         char *p;
1437         char* buf;
1438         guint32 idx;
1439         
1440         p = buf = g_malloc (64);
1441         
1442         mono_metadata_encode_value (0x06, p, &p);
1443         encode_custom_modifiers (assembly, fb->modreq, fb->modopt, p, &p);
1444         /* encode custom attributes before the type */
1445         encode_reflection_type (assembly, fb->type, p, &p);
1446         g_assert (p-buf < 64);
1447         mono_metadata_encode_value (p-buf, b, &b);
1448         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
1449         g_free (buf);
1450         return idx;
1451 }
1452
1453 static guint32
1454 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1455         char blob_size [64];
1456         char *b = blob_size;
1457         char *p, *box_val;
1458         char* buf;
1459         guint32 idx = 0, len = 0, dummy = 0;
1460         
1461         p = buf = g_malloc (64);
1462         if (!val) {
1463                 *ret_type = MONO_TYPE_CLASS;
1464                 len = 4;
1465                 box_val = (char*)&dummy;
1466         } else {
1467                 box_val = ((char*)val) + sizeof (MonoObject);
1468                 *ret_type = val->vtable->klass->byval_arg.type;
1469         }
1470 handle_enum:
1471         switch (*ret_type) {
1472         case MONO_TYPE_BOOLEAN:
1473         case MONO_TYPE_U1:
1474         case MONO_TYPE_I1:
1475                 len = 1;
1476                 break;
1477         case MONO_TYPE_CHAR:
1478         case MONO_TYPE_U2:
1479         case MONO_TYPE_I2:
1480                 len = 2;
1481                 break;
1482         case MONO_TYPE_U4:
1483         case MONO_TYPE_I4:
1484         case MONO_TYPE_R4:
1485                 len = 4;
1486                 break;
1487         case MONO_TYPE_U8:
1488         case MONO_TYPE_I8:
1489         case MONO_TYPE_R8:
1490                 len = 8;
1491                 break;
1492         case MONO_TYPE_VALUETYPE:
1493                 if (val->vtable->klass->enumtype) {
1494                         *ret_type = val->vtable->klass->enum_basetype->type;
1495                         goto handle_enum;
1496                 } else
1497                         g_error ("we can't encode valuetypes");
1498         case MONO_TYPE_CLASS:
1499                 break;
1500         case MONO_TYPE_STRING: {
1501                 MonoString *str = (MonoString*)val;
1502                 /* there is no signature */
1503                 len = str->length * 2;
1504                 mono_metadata_encode_value (len, b, &b);
1505 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1506                 {
1507                         char *swapped = g_malloc (2 * mono_string_length (str));
1508                         const char *p = (const char*)mono_string_chars (str);
1509
1510                         swap_with_size (swapped, p, 2, mono_string_length (str));
1511                         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1512                         g_free (swapped);
1513                 }
1514 #else
1515                 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1516 #endif
1517
1518                 g_free (buf);
1519                 return idx;
1520         }
1521         default:
1522                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1523         }
1524
1525         /* there is no signature */
1526         mono_metadata_encode_value (len, b, &b);
1527 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1528         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1529         swap_with_size (blob_size, box_val, len, 1);
1530         mono_image_add_stream_data (&assembly->blob, blob_size, len);
1531 #else
1532         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1533 #endif
1534
1535         g_free (buf);
1536         return idx;
1537 }
1538
1539 static guint32
1540 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1541         char blob_size [64];
1542         char *b = blob_size;
1543         char *p, *buf, *str;
1544         guint32 idx, len, bufsize = 256;
1545         
1546         p = buf = g_malloc (bufsize);
1547
1548         switch (minfo->type) {
1549         case MONO_NATIVE_BYVALTSTR:
1550         case MONO_NATIVE_BYVALARRAY:
1551                 mono_metadata_encode_value (minfo->type, p, &p);
1552                 mono_metadata_encode_value (minfo->count, p, &p);
1553                 break;
1554         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' && strncmp (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' && strncmp (p, "Culture=", 8) == 0) {
5218                         p += 8;
5219                         if (strncmp (p, "neutral", 7) == 0) {
5220                                 assembly->culture = "";
5221                                 p += 7;
5222                         } else {
5223                                 assembly->culture = p;
5224                                 while (*p && *p != ',') {
5225                                         p++;
5226                                 }
5227                         }
5228                 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
5229                         p += 15;
5230                         assembly->public_tok_value = p;
5231                         while (*p && *p != ',') {
5232                                 p++;
5233                         }
5234                 } else {
5235                         while (*p && *p != ',')
5236                                 p++;
5237                 }
5238                 found_sep = 0;
5239                 while (*p == ' ' || *p == ',') {
5240                         *p++ = 0;
5241                         found_sep = 1;
5242                         continue;
5243                 }
5244                 /* failed */
5245                 if (!found_sep)
5246                         return 1;
5247         }
5248
5249         return 0;
5250 }
5251
5252 /*
5253  * mono_reflection_parse_type:
5254  * @name: type name
5255  *
5256  * Parse a type name as accepted by the GetType () method and output the info
5257  * extracted in the info structure.
5258  * the name param will be mangled, so, make a copy before passing it to this function.
5259  * The fields in info will be valid until the memory pointed to by name is valid.
5260  * Returns 0 on parse error.
5261  * See also mono_type_get_name () below.
5262  */
5263 int
5264 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5265
5266         char *start, *p, *w, *last_point, *startn;
5267         int in_modifiers = 0;
5268         int isbyref = 0, rank;
5269
5270         start = p = w = name;
5271
5272         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5273         info->name = info->name_space = NULL;
5274         info->nested = NULL;
5275         info->modifiers = NULL;
5276
5277         /* last_point separates the namespace from the name */
5278         last_point = NULL;
5279
5280         while (*p) {
5281                 switch (*p) {
5282                 case '+':
5283                         *p = 0; /* NULL terminate the name */
5284                         startn = p + 1;
5285                         info->nested = g_list_append (info->nested, startn);
5286                         /* we have parsed the nesting namespace + name */
5287                         if (info->name)
5288                                 break;
5289                         if (last_point) {
5290                                 info->name_space = start;
5291                                 *last_point = 0;
5292                                 info->name = last_point + 1;
5293                         } else {
5294                                 info->name_space = (char *)"";
5295                                 info->name = start;
5296                         }
5297                         break;
5298                 case '.':
5299                         last_point = w;
5300                         break;
5301                 case '\\':
5302                         ++p;
5303                         break;
5304                 case '&':
5305                 case '*':
5306                 case '[':
5307                 case ',':
5308                         in_modifiers = 1;
5309                         break;
5310                 default:
5311                         break;
5312                 }
5313                 if (in_modifiers)
5314                         break;
5315                 *w++ = *p++;
5316         }
5317         
5318         if (!info->name) {
5319                 if (last_point) {
5320                         info->name_space = start;
5321                         *last_point = 0;
5322                         info->name = last_point + 1;
5323                 } else {
5324                         info->name_space = (char *)"";
5325                         info->name = start;
5326                 }
5327         }
5328         while (*p) {
5329                 switch (*p) {
5330                 case '&':
5331                         if (isbyref) /* only one level allowed by the spec */
5332                                 return 0;
5333                         isbyref = 1;
5334                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5335                         *p++ = 0;
5336                         break;
5337                 case '*':
5338                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5339                         *p++ = 0;
5340                         break;
5341                 case '[':
5342                         rank = 1;
5343                         *p++ = 0;
5344                         while (*p) {
5345                                 if (*p == ']')
5346                                         break;
5347                                 if (*p == ',')
5348                                         rank++;
5349                                 else if (*p != '*') /* '*' means unknown lower bound */
5350                                         return 0;
5351                                 ++p;
5352                         }
5353                         if (*p++ != ']')
5354                                 return 0;
5355                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5356                         break;
5357                 case ',':
5358                         *p++ = 0;
5359                         while (*p) {
5360                                 if (*p == ' ') {
5361                                         ++p;
5362                                         continue;
5363                                 }
5364                                 break;
5365                         }
5366                         if (!*p)
5367                                 return 0; /* missing assembly name */
5368                         if (!assembly_name_to_aname (&info->assembly, p))
5369                                 return 0;
5370                         break;
5371                 default:
5372                         return 0;
5373                         break;
5374                 }
5375                 if (info->assembly.name)
5376                         break;
5377         }
5378         *w = 0; /* terminate class name */
5379         if (!info->name || !*info->name)
5380                 return 0;
5381         /* add other consistency checks */
5382         return 1;
5383 }
5384
5385 static MonoType*
5386 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5387 {
5388         MonoClass *klass;
5389         GList *mod;
5390         int modval;
5391         
5392         if (!image)
5393                 image = mono_defaults.corlib;
5394
5395         if (ignorecase)
5396                 klass = mono_class_from_name_case (image, info->name_space, info->name);
5397         else
5398                 klass = mono_class_from_name (image, info->name_space, info->name);
5399         if (!klass)
5400                 return NULL;
5401         for (mod = info->nested; mod; mod = mod->next) {
5402                 GList *nested;
5403
5404                 mono_class_init (klass);
5405                 nested = klass->nested_classes;
5406                 klass = NULL;
5407                 while (nested) {
5408                         klass = nested->data;
5409                         if (ignorecase) {
5410                                 if (g_strcasecmp (klass->name, mod->data) == 0)
5411                                         break;
5412                         } else {
5413                                 if (strcmp (klass->name, mod->data) == 0)
5414                                         break;
5415                         }
5416                         klass = NULL;
5417                         nested = nested->next;
5418                 }
5419                 if (!klass)
5420                         break;
5421         }
5422         if (!klass)
5423                 return NULL;
5424         mono_class_init (klass);
5425         for (mod = info->modifiers; mod; mod = mod->next) {
5426                 modval = GPOINTER_TO_UINT (mod->data);
5427                 if (!modval) { /* byref: must be last modifier */
5428                         return &klass->this_arg;
5429                 } else if (modval == -1) {
5430                         klass = mono_ptr_class_get (&klass->byval_arg);
5431                 } else { /* array rank */
5432                         klass = mono_array_class_get (klass, modval);
5433                 }
5434                 mono_class_init (klass);
5435         }
5436
5437         return &klass->byval_arg;
5438 }
5439
5440 /*
5441  * mono_reflection_get_type:
5442  * @image: a metadata context
5443  * @info: type description structure
5444  * @ignorecase: flag for case-insensitive string compares
5445  *
5446  * Build a MonoType from the type description in @info.
5447  * 
5448  */
5449
5450 MonoType*
5451 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5452 {
5453         MonoType *type;
5454         MonoReflectionAssembly *assembly;
5455         GString *fullName;
5456         GList *mod;
5457
5458         type = mono_reflection_get_type_internal (image, info, ignorecase);
5459         if (type)
5460                 return type;
5461         if (!mono_domain_has_type_resolve (mono_domain_get ()))
5462                 return NULL;
5463         
5464         // Reconstruct the type name
5465         fullName = g_string_new ("");
5466         if (info->name_space && (info->name_space [0] != '\0'))
5467                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5468         else
5469                 g_string_printf (fullName, info->name);
5470         for (mod = info->nested; mod; mod = mod->next)
5471                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5472
5473         assembly = 
5474                 mono_domain_try_type_resolve (
5475                         mono_domain_get (), fullName->str, NULL);
5476         if (assembly && (!image || (assembly->assembly->image == image)))
5477                 type = mono_reflection_get_type_internal (assembly->assembly->image, 
5478                                                                                  info, ignorecase);
5479         g_string_free (fullName, TRUE);
5480         return type;
5481 }
5482
5483 /*
5484  * mono_reflection_type_from_name:
5485  * @name: type name.
5486  * @image: a metadata context (can be NULL).
5487  *
5488  * Retrieves a MonoType from its @name. If the name is not fully qualified,
5489  * it defaults to get the type from @image or, if @image is NULL or loading
5490  * from it fails, uses corlib.
5491  * 
5492  */
5493 MonoType*
5494 mono_reflection_type_from_name (char *name, MonoImage *image)
5495 {
5496         MonoType *type;
5497         MonoTypeNameParse info;
5498         MonoAssembly *assembly;
5499         
5500         /*g_print ("requested type %s\n", str);*/
5501         if (!mono_reflection_parse_type (name, &info)) {
5502                 g_list_free (info.modifiers);
5503                 g_list_free (info.nested);
5504                 return NULL;
5505         }
5506
5507         if (info.assembly.name) {
5508                 assembly = mono_assembly_loaded (&info.assembly);
5509                 /* do we need to load if it's not already loaded? */
5510                 if (!assembly) {
5511                         g_list_free (info.modifiers);
5512                         g_list_free (info.nested);
5513                         return NULL;
5514                 }
5515                 else
5516                         image = assembly->image;
5517         } else if (image == NULL) {
5518                 image = mono_defaults.corlib;
5519         }
5520
5521         type = mono_reflection_get_type (image, &info, FALSE);
5522         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5523                 image = mono_defaults.corlib;
5524                 type = mono_reflection_get_type (image, &info, FALSE);
5525         }
5526         
5527         g_list_free (info.modifiers);
5528         g_list_free (info.nested);
5529         return type;
5530 }
5531
5532 static void*
5533 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5534 {
5535         int slen, type = t->type;
5536 handle_enum:
5537         switch (type) {
5538         case MONO_TYPE_U1:
5539         case MONO_TYPE_I1:
5540         case MONO_TYPE_BOOLEAN: {
5541                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5542                 *bval = *p;
5543                 *end = p + 1;
5544                 return bval;
5545         }
5546         case MONO_TYPE_CHAR:
5547         case MONO_TYPE_U2:
5548         case MONO_TYPE_I2: {
5549                 guint16 *val = g_malloc (sizeof (guint16));
5550                 *val = read16 (p);
5551                 *end = p + 2;
5552                 return val;
5553         }
5554 #if SIZEOF_VOID_P == 4
5555         case MONO_TYPE_U:
5556         case MONO_TYPE_I:
5557 #endif
5558         case MONO_TYPE_R4:
5559         case MONO_TYPE_U4:
5560         case MONO_TYPE_I4: {
5561                 guint32 *val = g_malloc (sizeof (guint32));
5562                 *val = read32 (p);
5563                 *end = p + 4;
5564                 return val;
5565         }
5566 #if SIZEOF_VOID_P == 8
5567         case MONO_TYPE_U: /* error out instead? this should probably not happen */
5568         case MONO_TYPE_I:
5569 #endif
5570         case MONO_TYPE_R8:
5571         case MONO_TYPE_U8:
5572         case MONO_TYPE_I8: {
5573                 guint64 *val = g_malloc (sizeof (guint64));
5574                 *val = read64 (p);
5575                 *end = p + 8;
5576                 return val;
5577         }
5578         case MONO_TYPE_VALUETYPE:
5579                 if (t->data.klass->enumtype) {
5580                         type = t->data.klass->enum_basetype->type;
5581                         goto handle_enum;
5582                 } else {
5583                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5584                 }
5585                 break;
5586         case MONO_TYPE_STRING:
5587                 if (*p == (char)0xFF) {
5588                         *end = p + 1;
5589                         return NULL;
5590                 }
5591                 slen = mono_metadata_decode_value (p, &p);
5592                 *end = p + slen;
5593                 return mono_string_new_len (mono_domain_get (), p, slen);
5594         case MONO_TYPE_CLASS: {
5595                 char *n;
5596                 MonoType *t;
5597                 if (*p == (char)0xFF) {
5598                         *end = p + 1;
5599                         return NULL;
5600                 }
5601 handle_type:
5602                 slen = mono_metadata_decode_value (p, &p);
5603                 n = g_memdup (p, slen + 1);
5604                 n [slen] = 0;
5605                 t = mono_reflection_type_from_name (n, image);
5606                 if (!t)
5607                         g_warning ("Cannot load type '%s'", n);
5608                 g_free (n);
5609                 *end = p + slen;
5610                 if (t)
5611                         return mono_type_get_object (mono_domain_get (), t);
5612                 else
5613                         return NULL;
5614         }
5615         case MONO_TYPE_OBJECT: {
5616                 char subt = *p++;
5617                 MonoObject *obj;
5618                 MonoClass *subc = NULL;
5619                 void *val;
5620
5621                 if (subt == 0x50) {
5622                         goto handle_type;
5623                 } else if (subt == 0x0E) {
5624                         type = MONO_TYPE_STRING;
5625                         goto handle_enum;
5626                 } else if (subt == 0x55) {
5627                         char *n;
5628                         MonoType *t;
5629                         slen = mono_metadata_decode_value (p, &p);
5630                         n = g_memdup (p, slen + 1);
5631                         n [slen] = 0;
5632                         t = mono_reflection_type_from_name (n, image);
5633                         if (!t)
5634                                 g_warning ("Cannot load type '%s'", n);
5635                         g_free (n);
5636                         p += slen;
5637                         subc = mono_class_from_mono_type (t);
5638                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5639                         MonoType simple_type = {{0}};
5640                         simple_type.type = subt;
5641                         subc = mono_class_from_mono_type (&simple_type);
5642                 } else {
5643                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5644                 }
5645                 val = load_cattr_value (image, &subc->byval_arg, p, end);
5646                 obj = mono_object_new (mono_domain_get (), subc);
5647                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5648                 g_free (val);
5649                 return obj;
5650         }
5651         case MONO_TYPE_SZARRAY:
5652         {
5653                 MonoArray *arr;
5654                 guint32 i, alen, basetype;
5655                 alen = read32 (p);
5656                 p += 4;
5657                 if (alen == 0xffffffff) {
5658                         *end = p;
5659                         return NULL;
5660                 }
5661                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5662                 basetype = t->data.klass->byval_arg.type;
5663                 switch (basetype)
5664                 {
5665                         case MONO_TYPE_U1:
5666                         case MONO_TYPE_I1:
5667                         case MONO_TYPE_BOOLEAN:
5668                                 for (i=0;i<alen;i++)
5669                                 {
5670                                         MonoBoolean val=*p++;
5671                                         mono_array_set(arr,MonoBoolean,i,val);
5672                                 }
5673                                 break;
5674                         case MONO_TYPE_CHAR:
5675                         case MONO_TYPE_U2:
5676                         case MONO_TYPE_I2:
5677                                 for (i=0;i<alen;i++)
5678                                 {
5679                                         guint16 val=read16(p);
5680                                         mono_array_set(arr,guint16,i,val);
5681                                         p+=2;
5682                                 }
5683                                 break;
5684                         case MONO_TYPE_R4:
5685                         case MONO_TYPE_U4:
5686                         case MONO_TYPE_I4:
5687                                 for (i=0;i<alen;i++)
5688                                 {
5689                                         guint32 val=read32(p);
5690                                         mono_array_set(arr,guint32,i,val);
5691                                         p+=4;
5692                                 }
5693                                 break;
5694                         case MONO_TYPE_R8:
5695                         case MONO_TYPE_U8:
5696                         case MONO_TYPE_I8:
5697                                 for (i=0;i<alen;i++)
5698                                 {
5699                                         guint64 val=read64(p);
5700                                         mono_array_set(arr,guint64,i,val);
5701                                         p+=8;
5702                                 }
5703                                 break;
5704                         case MONO_TYPE_CLASS:
5705                         case MONO_TYPE_STRING:
5706                                 for (i = 0; i < alen; i++) {
5707                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5708                                         mono_array_set (arr, gpointer, i, item);
5709                                 }
5710                                 break;
5711                         default:
5712                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5713                 }
5714                 *end=p;
5715                 return arr;
5716         }
5717         default:
5718                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5719         }
5720         return NULL;
5721 }
5722
5723 static gboolean
5724 type_is_reference (MonoType *type)
5725 {
5726         switch (type->type) {
5727         case MONO_TYPE_BOOLEAN:
5728         case MONO_TYPE_CHAR:
5729         case MONO_TYPE_U:
5730         case MONO_TYPE_I:
5731         case MONO_TYPE_U1:
5732         case MONO_TYPE_I1:
5733         case MONO_TYPE_U2:
5734         case MONO_TYPE_I2:
5735         case MONO_TYPE_U4:
5736         case MONO_TYPE_I4:
5737         case MONO_TYPE_U8:
5738         case MONO_TYPE_I8:
5739         case MONO_TYPE_R8:
5740         case MONO_TYPE_R4:
5741         case MONO_TYPE_VALUETYPE:
5742                 return FALSE;
5743         default:
5744                 return TRUE;
5745         }
5746 }
5747
5748 static void
5749 free_param_data (MonoMethodSignature *sig, void **params) {
5750         int i;
5751         for (i = 0; i < sig->param_count; ++i) {
5752                 if (!type_is_reference (sig->params [i]))
5753                         g_free (params [i]);
5754         }
5755 }
5756
5757 /*
5758  * Find the method index in the metadata methodDef table.
5759  * Later put these three helper methods in metadata and export them.
5760  */
5761 static guint32
5762 find_method_index (MonoMethod *method) {
5763         MonoClass *klass = method->klass;
5764         int i;
5765
5766         for (i = 0; i < klass->method.count; ++i) {
5767                 if (method == klass->methods [i])
5768                         return klass->method.first + 1 + i;
5769         }
5770         return 0;
5771 }
5772
5773 /*
5774  * Find the field index in the metadata FieldDef table.
5775  */
5776 static guint32
5777 find_field_index (MonoClass *klass, MonoClassField *field) {
5778         int i;
5779
5780         for (i = 0; i < klass->field.count; ++i) {
5781                 if (field == &klass->fields [i])
5782                         return klass->field.first + 1 + i;
5783         }
5784         return 0;
5785 }
5786
5787 /*
5788  * Find the property index in the metadata Property table.
5789  */
5790 static guint32
5791 find_property_index (MonoClass *klass, MonoProperty *property) {
5792         int i;
5793
5794         for (i = 0; i < klass->property.count; ++i) {
5795                 if (property == &klass->properties [i])
5796                         return klass->property.first + 1 + i;
5797         }
5798         return 0;
5799 }
5800
5801 /*
5802  * Find the event index in the metadata Event table.
5803  */
5804 static guint32
5805 find_event_index (MonoClass *klass, MonoEvent *event) {
5806         int i;
5807
5808         for (i = 0; i < klass->event.count; ++i) {
5809                 if (event == &klass->events [i])
5810                         return klass->event.first + 1 + i;
5811         }
5812         return 0;
5813 }
5814
5815 static MonoObject*
5816 create_custom_attr (MonoImage *image, MonoMethod *method, 
5817                                         const char *data, guint32 len)
5818 {
5819         const char *p = data;
5820         const char *named;
5821         guint32 i, j, num_named;
5822         MonoObject *attr;
5823         void **params;
5824
5825         mono_class_init (method->klass);
5826
5827         if (len == 0) {
5828                 attr = mono_object_new (mono_domain_get (), method->klass);
5829                 mono_runtime_invoke (method, attr, NULL, NULL);
5830                 return attr;
5831         }
5832
5833         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5834                 return NULL;
5835
5836         /*g_print ("got attr %s\n", method->klass->name);*/
5837         
5838         params = g_new (void*, method->signature->param_count);
5839
5840         /* skip prolog */
5841         p += 2;
5842         for (i = 0; i < method->signature->param_count; ++i) {
5843                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5844         }
5845
5846         named = p;
5847         attr = mono_object_new (mono_domain_get (), method->klass);
5848         mono_runtime_invoke (method, attr, params, NULL);
5849         free_param_data (method->signature, params);
5850         g_free (params);
5851         num_named = read16 (named);
5852         named += 2;
5853         for (j = 0; j < num_named; j++) {
5854                 gint name_len;
5855                 char *name, named_type, data_type;
5856                 named_type = *named++;
5857                 data_type = *named++; /* type of data */
5858                 if (data_type == 0x55) {
5859                         gint type_len;
5860                         char *type_name;
5861                         type_len = mono_metadata_decode_blob_size (named, &named);
5862                         type_name = g_malloc (type_len + 1);
5863                         memcpy (type_name, named, type_len);
5864                         type_name [type_len] = 0;
5865                         named += type_len;
5866                         /* FIXME: lookup the type and check type consistency */
5867                 }
5868                 else
5869                         if (data_type == MONO_TYPE_SZARRAY)
5870                                 /* The spec does not mention this */
5871                                 named ++;
5872                 name_len = mono_metadata_decode_blob_size (named, &named);
5873                 name = g_malloc (name_len + 1);
5874                 memcpy (name, named, name_len);
5875                 name [name_len] = 0;
5876                 named += name_len;
5877                 if (named_type == 0x53) {
5878                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5879                         void *val = load_cattr_value (image, field->type, named, &named);
5880                                 mono_field_set_value (attr, field, val);
5881                                 if (!type_is_reference (field->type))
5882                                         g_free (val);
5883                 } else if (named_type == 0x54) {
5884                         MonoProperty *prop;
5885                         void *pparams [1];
5886                         MonoType *prop_type;
5887
5888                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5889                         /* can we have more that 1 arg in a custom attr named property? */
5890                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5891                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
5892                         mono_property_set_value (prop, attr, pparams, NULL);
5893                         if (!type_is_reference (prop_type))
5894                                 g_free (pparams [0]);
5895                 }
5896                 g_free (name);
5897         }
5898
5899         return attr;
5900 }
5901
5902 MonoArray*
5903 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5904 {
5905         MonoArray *result;
5906         MonoClass *klass;
5907         MonoObject *attr;
5908         int i;
5909
5910         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5911         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5912         for (i = 0; i < cinfo->num_attrs; ++i) {
5913                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5914                 mono_array_set (result, gpointer, i, attr);
5915         }
5916         return result;
5917 }
5918
5919 MonoCustomAttrInfo*
5920 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5921 {
5922         guint32 mtoken, i, len;
5923         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5924         MonoTableInfo *ca;
5925         MonoCustomAttrInfo *ainfo;
5926         GList *tmp, *list = NULL;
5927         const char *data;
5928
5929         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5930
5931         i = mono_metadata_custom_attrs_from_index (image, idx);
5932         if (!i)
5933                 return NULL;
5934         i --;
5935         while (i < ca->rows) {
5936                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5937                         break;
5938                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5939                 ++i;
5940         }
5941         len = g_list_length (list);
5942         if (!len)
5943                 return NULL;
5944         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5945         ainfo->num_attrs = len;
5946         ainfo->image = image;
5947         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5948                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5949                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5950                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5951                 case CUSTOM_ATTR_TYPE_METHODDEF:
5952                         mtoken |= MONO_TOKEN_METHOD_DEF;
5953                         break;
5954                 case CUSTOM_ATTR_TYPE_MEMBERREF:
5955                         mtoken |= MONO_TOKEN_MEMBER_REF;
5956                         break;
5957                 default:
5958                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5959                         break;
5960                 }
5961                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5962                 if (!ainfo->attrs [i].ctor)
5963                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5964                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5965                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5966                 ainfo->attrs [i].data = data;
5967         }
5968         g_list_free (list);
5969
5970         return ainfo;
5971 }
5972
5973 MonoCustomAttrInfo*
5974 mono_custom_attrs_from_method (MonoMethod *method)
5975 {
5976         MonoCustomAttrInfo *cinfo;
5977         guint32 idx;
5978         
5979         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5980                 return cinfo;
5981         idx = find_method_index (method);
5982         idx <<= CUSTOM_ATTR_BITS;
5983         idx |= CUSTOM_ATTR_METHODDEF;
5984         return mono_custom_attrs_from_index (method->klass->image, idx);
5985 }
5986
5987 MonoCustomAttrInfo*
5988 mono_custom_attrs_from_class (MonoClass *klass)
5989 {
5990         MonoCustomAttrInfo *cinfo;
5991         guint32 idx;
5992         
5993         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
5994                 return cinfo;
5995         idx = mono_metadata_token_index (klass->type_token);
5996         idx <<= CUSTOM_ATTR_BITS;
5997         idx |= CUSTOM_ATTR_TYPEDEF;
5998         return mono_custom_attrs_from_index (klass->image, idx);
5999 }
6000
6001 MonoCustomAttrInfo*
6002 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6003 {
6004         MonoCustomAttrInfo *cinfo;
6005         guint32 idx;
6006         
6007         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6008                 return cinfo;
6009         idx = 1; /* there is only one assembly */
6010         idx <<= CUSTOM_ATTR_BITS;
6011         idx |= CUSTOM_ATTR_ASSEMBLY;
6012         return mono_custom_attrs_from_index (assembly->image, idx);
6013 }
6014
6015 static MonoCustomAttrInfo*
6016 mono_custom_attrs_from_module (MonoImage *image)
6017 {
6018         MonoCustomAttrInfo *cinfo;
6019         guint32 idx;
6020         
6021         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6022                 return cinfo;
6023         idx = 1; /* there is only one module */
6024         idx <<= CUSTOM_ATTR_BITS;
6025         idx |= CUSTOM_ATTR_MODULE;
6026         return mono_custom_attrs_from_index (image, idx);
6027 }
6028
6029 MonoCustomAttrInfo*
6030 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6031 {
6032         MonoCustomAttrInfo *cinfo;
6033         guint32 idx;
6034         
6035         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6036                 return cinfo;
6037         idx = find_property_index (klass, property);
6038         idx <<= CUSTOM_ATTR_BITS;
6039         idx |= CUSTOM_ATTR_PROPERTY;
6040         return mono_custom_attrs_from_index (klass->image, idx);
6041 }
6042
6043 MonoCustomAttrInfo*
6044 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6045 {
6046         MonoCustomAttrInfo *cinfo;
6047         guint32 idx;
6048         
6049         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6050                 return cinfo;
6051         idx = find_event_index (klass, event);
6052         idx <<= CUSTOM_ATTR_BITS;
6053         idx |= CUSTOM_ATTR_EVENT;
6054         return mono_custom_attrs_from_index (klass->image, idx);
6055 }
6056
6057 MonoCustomAttrInfo*
6058 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6059 {
6060         MonoCustomAttrInfo *cinfo;
6061         guint32 idx;
6062         
6063         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6064                 return cinfo;
6065         idx = find_field_index (klass, field);
6066         idx <<= CUSTOM_ATTR_BITS;
6067         idx |= CUSTOM_ATTR_FIELDDEF;
6068         return mono_custom_attrs_from_index (klass->image, idx);
6069 }
6070
6071 MonoCustomAttrInfo*
6072 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6073 {
6074         MonoTableInfo *ca;
6075         guint32 i, idx, method_index;
6076         guint32 param_list, param_last, param_pos, found;
6077         MonoImage *image;
6078         MonoReflectionMethodAux *aux;
6079
6080         if (method->klass->image->dynamic) {
6081                 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6082                 if (!aux || !aux->param_cattr)
6083                         return NULL;
6084                 return aux->param_cattr [param];
6085         }
6086
6087         image = method->klass->image;
6088         method_index = find_method_index (method);
6089         ca = &image->tables [MONO_TABLE_METHOD];
6090
6091         if (method->klass->generic_inst || method->klass->gen_params ||
6092             method->signature->generic_param_count) {
6093                 // FIXME FIXME FIXME
6094                 return NULL;
6095         }
6096
6097         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6098         if (method_index == ca->rows) {
6099                 ca = &image->tables [MONO_TABLE_PARAM];
6100                 param_last = ca->rows + 1;
6101         } else {
6102                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6103                 ca = &image->tables [MONO_TABLE_PARAM];
6104         }
6105         found = FALSE;
6106         for (i = param_list; i < param_last; ++i) {
6107                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6108                 if (param_pos == param) {
6109                         found = TRUE;
6110                         break;
6111                 }
6112         }
6113         if (!found)
6114                 return NULL;
6115         idx = i;
6116         idx <<= CUSTOM_ATTR_BITS;
6117         idx |= CUSTOM_ATTR_PARAMDEF;
6118         return mono_custom_attrs_from_index (image, idx);
6119 }
6120
6121 /*
6122  * mono_reflection_get_custom_attrs:
6123  * @obj: a reflection object handle
6124  *
6125  * Return an array with all the custom attributes defined of the
6126  * reflection handle @obj. The objects are fully build.
6127  */
6128 MonoArray*
6129 mono_reflection_get_custom_attrs (MonoObject *obj)
6130 {
6131         MonoClass *klass;
6132         MonoArray *result;
6133         MonoCustomAttrInfo *cinfo = NULL;
6134         
6135         MONO_ARCH_SAVE_REGS;
6136
6137         klass = obj->vtable->klass;
6138         /* FIXME: need to handle: Module */
6139         if (klass == mono_defaults.monotype_class) {
6140                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6141                 klass = mono_class_from_mono_type (rtype->type);
6142                 cinfo = mono_custom_attrs_from_class (klass);
6143         } else if (strcmp ("Assembly", klass->name) == 0) {
6144                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6145                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6146         } else if (strcmp ("Module", klass->name) == 0) {
6147                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6148                 cinfo = mono_custom_attrs_from_module (module->image);
6149         } else if (strcmp ("MonoProperty", klass->name) == 0) {
6150                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6151                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6152         } else if (strcmp ("MonoEvent", klass->name) == 0) {
6153                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6154                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6155         } else if (strcmp ("MonoField", klass->name) == 0) {
6156                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6157                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6158         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6159                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6160                 cinfo = mono_custom_attrs_from_method (rmethod->method);
6161         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6162                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6163                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6164                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6165         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6166                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6167                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6168         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6169                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6170                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6171         } else { /* handle other types here... */
6172                 g_error ("get custom attrs not yet supported for %s", klass->name);
6173         }
6174
6175         if (cinfo) {
6176                 result = mono_custom_attrs_construct (cinfo);
6177         } else {
6178                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6179                 result = mono_array_new (mono_domain_get (), klass, 0);
6180         }
6181
6182         return result;
6183 }
6184
6185 static MonoMethodSignature*
6186 parameters_to_signature (MonoArray *parameters) {
6187         MonoMethodSignature *sig;
6188         int count, i;
6189
6190         count = parameters? mono_array_length (parameters): 0;
6191
6192         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6193         sig->param_count = count;
6194         sig->sentinelpos = -1; /* FIXME */
6195         for (i = 0; i < count; ++i) {
6196                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6197                 sig->params [i] = pt->type;
6198         }
6199         return sig;
6200 }
6201
6202 static MonoMethodSignature*
6203 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6204         MonoMethodSignature *sig;
6205
6206         sig = parameters_to_signature (ctor->parameters);
6207         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6208         sig->ret = &mono_defaults.void_class->byval_arg;
6209         return sig;
6210 }
6211
6212 static MonoMethodSignature*
6213 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6214         MonoMethodSignature *sig;
6215
6216         sig = parameters_to_signature (method->parameters);
6217         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6218         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6219         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6220         return sig;
6221 }
6222
6223 static MonoMethodSignature*
6224 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6225         MonoMethodSignature *sig;
6226
6227         sig = parameters_to_signature (method->parameters);
6228         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6229         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6230         sig->generic_param_count = 0;
6231         return sig;
6232 }
6233
6234 static void
6235 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6236 {
6237         MonoClass *klass = mono_object_class (prop);
6238         if (strcmp (klass->name, "PropertyBuilder") == 0) {
6239                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6240                 *name = mono_string_to_utf8 (pb->name);
6241                 *type = pb->type->type;
6242         } else {
6243                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6244                 *name = g_strdup (p->property->name);
6245                 if (p->property->get)
6246                         *type = p->property->get->signature->ret;
6247                 else
6248                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6249         }
6250 }
6251
6252 static void
6253 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6254 {
6255         MonoClass *klass = mono_object_class (field);
6256         if (strcmp (klass->name, "FieldBuilder") == 0) {
6257                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6258                 *name = mono_string_to_utf8 (fb->name);
6259                 *type = fb->type->type;
6260         } else {
6261                 MonoReflectionField *f = (MonoReflectionField *)field;
6262                 *name = g_strdup (f->field->name);
6263                 *type = f->field->type;
6264         }
6265 }
6266
6267 static void
6268 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6269 {
6270         char *argval;
6271         MonoTypeEnum simple_type;
6272         
6273         if ((p-buffer) + 10 >= *buflen) {
6274                 char *newbuf;
6275                 *buflen *= 2;
6276                 newbuf = g_realloc (buffer, *buflen);
6277                 p = newbuf + (p-buffer);
6278                 buffer = newbuf;
6279         }
6280         argval = ((char*)arg + sizeof (MonoObject));
6281         simple_type = type->type;
6282 handle_enum:
6283         switch (simple_type) {
6284         case MONO_TYPE_BOOLEAN:
6285         case MONO_TYPE_U1:
6286         case MONO_TYPE_I1:
6287                 *p++ = *argval;
6288                 break;
6289         case MONO_TYPE_CHAR:
6290         case MONO_TYPE_U2:
6291         case MONO_TYPE_I2:
6292                 swap_with_size (p, argval, 2, 1);
6293                 p += 2;
6294                 break;
6295         case MONO_TYPE_U4:
6296         case MONO_TYPE_I4:
6297         case MONO_TYPE_R4:
6298                 swap_with_size (p, argval, 4, 1);
6299                 p += 4;
6300                 break;
6301         case MONO_TYPE_U8:
6302         case MONO_TYPE_I8:
6303         case MONO_TYPE_R8:
6304                 swap_with_size (p, argval, 8, 1);
6305                 p += 8;
6306                 break;
6307         case MONO_TYPE_VALUETYPE:
6308                 if (type->data.klass->enumtype) {
6309                         simple_type = type->data.klass->enum_basetype->type;
6310                         goto handle_enum;
6311                 } else {
6312                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6313                 }
6314                 break;
6315         case MONO_TYPE_STRING: {
6316                 char *str;
6317                 guint32 slen;
6318                 if (!arg) {
6319                         *p++ = 0xFF;
6320                         break;
6321                 }
6322                 str = mono_string_to_utf8 ((MonoString*)arg);
6323                 slen = strlen (str);
6324                 if ((p-buffer) + 10 + slen >= *buflen) {
6325                         char *newbuf;
6326                         *buflen *= 2;
6327                         *buflen += slen;
6328                         newbuf = g_realloc (buffer, *buflen);
6329                         p = newbuf + (p-buffer);
6330                         buffer = newbuf;
6331                 }
6332                 mono_metadata_encode_value (slen, p, &p);
6333                 memcpy (p, str, slen);
6334                 p += slen;
6335                 g_free (str);
6336                 break;
6337         }
6338         case MONO_TYPE_CLASS: {
6339                 char *str;
6340                 guint32 slen;
6341                 MonoClass *k;
6342                 if (!arg) {
6343                         *p++ = 0xFF;
6344                         break;
6345                 }
6346                 k = mono_object_class (arg);
6347                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6348                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6349                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6350 handle_type:
6351                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6352                 slen = strlen (str);
6353                 if ((p-buffer) + 10 + slen >= *buflen) {
6354                         char *newbuf;
6355                         *buflen *= 2;
6356                         *buflen += slen;
6357                         newbuf = g_realloc (buffer, *buflen);
6358                         p = newbuf + (p-buffer);
6359                         buffer = newbuf;
6360                 }
6361                 mono_metadata_encode_value (slen, p, &p);
6362                 memcpy (p, str, slen);
6363                 p += slen;
6364                 g_free (str);
6365                 break;
6366         }
6367         case MONO_TYPE_SZARRAY: {
6368                 int len, i;
6369                 MonoClass *eclass;
6370
6371                 if (!arg) {
6372                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6373                         break;
6374                 }
6375                 len = mono_array_length ((MonoArray*)arg);
6376                 *p++ = len & 0xff;
6377                 *p++ = (len >> 8) & 0xff;
6378                 *p++ = (len >> 16) & 0xff;
6379                 *p++ = (len >> 24) & 0xff;
6380                 *retp = p;
6381                 *retbuffer = buffer;
6382                 eclass = type->data.klass;
6383                 for (i = 0; i < len; ++i) {
6384                         encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6385                 }
6386                 break;
6387         }
6388         /* it may be a boxed value or a Type */
6389         case MONO_TYPE_OBJECT: {
6390                 MonoClass *klass = mono_object_class (arg);
6391                 char *str;
6392                 guint32 slen;
6393                 
6394                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6395                         *p++ = 0x50;
6396                         goto handle_type;
6397                 } else if (klass->enumtype) {
6398                         *p++ = 0x55;
6399                 } else if (klass == mono_defaults.string_class) {
6400                         simple_type = MONO_TYPE_STRING;
6401                         *p++ = 0x0E;
6402                         goto handle_enum;
6403                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6404                         *p++ = simple_type = klass->byval_arg.type;
6405                         goto handle_enum;
6406                 } else {
6407                         g_error ("unhandled type in custom attr");
6408                 }
6409                 str = type_get_qualified_name (klass->enum_basetype, NULL);
6410                 slen = strlen (str);
6411                 if ((p-buffer) + 10 + slen >= *buflen) {
6412                         char *newbuf;
6413                         *buflen *= 2;
6414                         *buflen += slen;
6415                         newbuf = g_realloc (buffer, *buflen);
6416                         p = newbuf + (p-buffer);
6417                         buffer = newbuf;
6418                 }
6419                 mono_metadata_encode_value (slen, p, &p);
6420                 memcpy (p, str, slen);
6421                 p += slen;
6422                 g_free (str);
6423                 simple_type = klass->enum_basetype->type;
6424                 goto handle_enum;
6425         }
6426         default:
6427                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6428         }
6429         *retp = p;
6430         *retbuffer = buffer;
6431 }
6432
6433 /*
6434  * mono_reflection_get_custom_attrs_blob:
6435  * @ctor: custom attribute constructor
6436  * @ctorArgs: arguments o the constructor
6437  * @properties:
6438  * @propValues:
6439  * @fields:
6440  * @fieldValues:
6441  * 
6442  * Creates the blob of data that needs to be saved in the metadata and that represents
6443  * the custom attributed described by @ctor, @ctorArgs etc.
6444  * Returns: a Byte array representing the blob of data.
6445  */
6446 MonoArray*
6447 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
6448 {
6449         MonoArray *result;
6450         MonoMethodSignature *sig;
6451         MonoObject *arg;
6452         char *buffer, *p;
6453         guint32 buflen, i;
6454
6455         MONO_ARCH_SAVE_REGS;
6456
6457         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6458                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6459         } else {
6460                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6461         }
6462         g_assert (mono_array_length (ctorArgs) == sig->param_count);
6463         buflen = 256;
6464         p = buffer = g_malloc (buflen);
6465         /* write the prolog */
6466         *p++ = 1;
6467         *p++ = 0;
6468         for (i = 0; i < sig->param_count; ++i) {
6469                 arg = mono_array_get (ctorArgs, MonoObject*, i);
6470                 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6471         }
6472         i = 0;
6473         if (properties)
6474                 i += mono_array_length (properties);
6475         if (fields)
6476                 i += mono_array_length (fields);
6477         *p++ = i & 0xff;
6478         *p++ = (i >> 8) & 0xff;
6479         if (properties) {
6480                 MonoObject *prop;
6481                 for (i = 0; i < mono_array_length (properties); ++i) {
6482                         MonoType *ptype;
6483                         char *pname;
6484                         int len;
6485                         
6486                         prop = mono_array_get (properties, gpointer, i);
6487                         get_prop_name_and_type (prop, &pname, &ptype);
6488                         *p++ = 0x54; /* PROPERTY signature */
6489
6490                         /* Preallocate a large enough buffer */
6491                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6492                                 char *str = type_get_qualified_name (ptype, NULL);
6493                                 len = strlen (str);
6494                                 g_free (str);
6495                         }
6496                         else
6497                                 len = 0;
6498                         len += strlen (pname);
6499
6500                         if ((p-buffer) + 20 + len >= buflen) {
6501                                 char *newbuf;
6502                                 buflen *= 2;
6503                                 buflen += len;
6504                                 newbuf = g_realloc (buffer, buflen);
6505                                 p = newbuf + (p-buffer);
6506                                 buffer = newbuf;
6507                         }
6508
6509                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6510                                 char *str = type_get_qualified_name (ptype, NULL);
6511                                 int slen = strlen (str);
6512
6513                                 *p++ = 0x55;
6514                                 /*
6515                                  * This seems to be optional...
6516                                  * *p++ = 0x80;
6517                                  */
6518                                 mono_metadata_encode_value (slen, p, &p);
6519                                 memcpy (p, str, slen);
6520                                 p += slen;
6521                                 g_free (str);
6522                         } else {
6523                                 mono_metadata_encode_value (ptype->type, p, &p);
6524                                 if (ptype->type == MONO_TYPE_SZARRAY)
6525                                         mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6526                         }
6527                         len = strlen (pname);
6528                         mono_metadata_encode_value (len, p, &p);
6529                         memcpy (p, pname, len);
6530                         p += len;
6531                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6532                         g_free (pname);
6533                 }
6534         }
6535
6536         if (fields) {
6537                 MonoObject *field;
6538                 for (i = 0; i < mono_array_length (fields); ++i) {
6539                         MonoType *ftype;
6540                         char *fname;
6541                         int len;
6542                         
6543                         field = mono_array_get (fields, gpointer, i);
6544                         get_field_name_and_type (field, &fname, &ftype);
6545                         *p++ = 0x53; /* FIELD signature */
6546                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6547                                 char *str = type_get_qualified_name (ftype, NULL);
6548                                 int slen = strlen (str);
6549                                 if ((p-buffer) + 10 + slen >= buflen) {
6550                                         char *newbuf;
6551                                         buflen *= 2;
6552                                         buflen += slen;
6553                                         newbuf = g_realloc (buffer, buflen);
6554                                         p = newbuf + (p-buffer);
6555                                         buffer = newbuf;
6556                                 }
6557                                 *p++ = 0x55;
6558                                 /*
6559                                  * This seems to be optional...
6560                                  * *p++ = 0x80;
6561                                  */
6562                                 mono_metadata_encode_value (slen, p, &p);
6563                                 memcpy (p, str, slen);
6564                                 p += slen;
6565                                 g_free (str);
6566                         } else {
6567                                 mono_metadata_encode_value (ftype->type, p, &p);
6568                         }
6569                         len = strlen (fname);
6570                         mono_metadata_encode_value (len, p, &p);
6571                         memcpy (p, fname, len);
6572                         p += len;
6573                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6574                         g_free (fname);
6575                 }
6576         }
6577
6578         g_assert (p - buffer <= buflen);
6579         buflen = p - buffer;
6580         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6581         p = mono_array_addr (result, char, 0);
6582         memcpy (p, buffer, buflen);
6583         g_free (buffer);
6584         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6585                 g_free (sig);
6586         return result;
6587 }
6588
6589 /*
6590  * mono_reflection_setup_internal_class:
6591  * @tb: a TypeBuilder object
6592  *
6593  * Creates a MonoClass that represents the TypeBuilder.
6594  * This is a trick that lets us simplify a lot of reflection code
6595  * (and will allow us to support Build and Run assemblies easier).
6596  */
6597 void
6598 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6599 {
6600         MonoClass *klass, *parent;
6601
6602         MONO_ARCH_SAVE_REGS;
6603
6604         klass = g_new0 (MonoClass, 1);
6605
6606         klass->image = &tb->module->dynamic_image->image;
6607
6608         if (tb->parent) {
6609                 /* check so we can compile corlib correctly */
6610                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6611                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6612                         parent = tb->parent->type->data.klass;
6613                 } else 
6614                         parent = my_mono_class_from_mono_type (tb->parent->type);
6615         } else
6616                 parent = NULL;
6617         
6618         klass->inited = 1; /* we lie to the runtime */
6619         klass->name = mono_string_to_utf8 (tb->name);
6620         klass->name_space = mono_string_to_utf8 (tb->nspace);
6621         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6622         klass->flags = tb->attrs;
6623
6624         klass->element_class = klass;
6625         klass->reflection_info = tb; /* need to pin. */
6626
6627         /* Put into cache so mono_class_get () will find it */
6628         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6629                                                                   tb->table_idx);
6630
6631         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6632                                                           GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6633                                                           tb);
6634
6635         if (parent != NULL)
6636                 mono_class_setup_parent (klass, parent);
6637         else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6638                 const char *old_n = klass->name;
6639                 /* trick to get relative numbering right when compiling corlib */
6640                 klass->name = "BuildingObject";
6641                 mono_class_setup_parent (klass, mono_defaults.object_class);
6642                 klass->name = old_n;
6643         }
6644         mono_class_setup_mono_type (klass);
6645
6646         mono_class_setup_supertypes (klass);
6647
6648         /*
6649          * FIXME: handle interfaces.
6650          */
6651
6652         tb->type.type = &klass->byval_arg;
6653
6654         if (tb->nesting_type) {
6655                 g_assert (tb->nesting_type->type);
6656                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6657         }
6658
6659         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6660 }
6661
6662 /*
6663  * mono_reflection_setup_generic_class:
6664  * @tb: a TypeBuilder object
6665  *
6666  * Setup the generic class after all generic parameters have been added.
6667  */
6668 void
6669 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6670 {
6671         MonoClass *klass;
6672         int count, i;
6673
6674         MONO_ARCH_SAVE_REGS;
6675
6676         klass = my_mono_class_from_mono_type (tb->type.type);
6677
6678         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6679
6680         if (klass->gen_params || (count == 0))
6681                 return;
6682
6683         klass->num_gen_params = count;
6684         klass->gen_params = g_new0 (MonoGenericParam, count);
6685
6686         for (i = 0; i < count; i++) {
6687                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6688                 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6689         }
6690 }
6691
6692 /*
6693  * mono_reflection_create_internal_class:
6694  * @tb: a TypeBuilder object
6695  *
6696  * Actually create the MonoClass that is associated with the TypeBuilder.
6697  */
6698 void
6699 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6700 {
6701         MonoClass *klass;
6702
6703         MONO_ARCH_SAVE_REGS;
6704
6705         klass = my_mono_class_from_mono_type (tb->type.type);
6706
6707         if (klass->enumtype && klass->enum_basetype == NULL) {
6708                 MonoReflectionFieldBuilder *fb;
6709
6710                 g_assert (tb->fields != NULL);
6711                 g_assert (mono_array_length (tb->fields) >= 1);
6712
6713                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6714
6715                 klass->enum_basetype = fb->type->type;
6716                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6717                 if (!klass->element_class)
6718                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6719                 klass->instance_size = klass->element_class->instance_size;
6720                 klass->size_inited = 1;
6721                 /* 
6722                  * this is almost safe to do with enums and it's needed to be able
6723                  * to create objects of the enum type (for use in SetConstant).
6724                  */
6725                 /* FIXME: Does this mean enums can't have method overrides ? */
6726                 mono_class_setup_vtable (klass, NULL, 0);
6727         }
6728 }
6729
6730 static MonoMarshalSpec*
6731 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6732                                                                 MonoReflectionMarshal *minfo)
6733 {
6734         MonoMarshalSpec *res;
6735
6736         res = g_new0 (MonoMarshalSpec, 1);
6737         res->native = minfo->type;
6738
6739         switch (minfo->type) {
6740         case MONO_NATIVE_LPARRAY:
6741                 res->data.array_data.elem_type = minfo->eltype;
6742                 res->data.array_data.param_num = 0; /* Not yet */
6743                 res->data.array_data.num_elem = minfo->count;
6744                 break;
6745
6746         case MONO_NATIVE_BYVALTSTR:
6747         case MONO_NATIVE_BYVALARRAY:
6748                 res->data.array_data.num_elem = minfo->count;
6749                 break;
6750
6751         case MONO_NATIVE_CUSTOM:
6752                 if (minfo->marshaltyperef)
6753                         res->data.custom_data.custom_name =
6754                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6755                 if (minfo->mcookie)
6756                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6757                 break;
6758
6759         default:
6760                 break;
6761         }
6762
6763         return res;
6764 }
6765
6766 static MonoMethod*
6767 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6768                                          ReflectionMethodBuilder *rmb,
6769                                          MonoMethodSignature *sig)
6770 {
6771         MonoMethod *m;
6772         MonoMethodNormal *pm;
6773         MonoMarshalSpec **specs;
6774         MonoReflectionMethodAux *method_aux;
6775         int i;
6776
6777         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6778             (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6779                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6780         else 
6781                 if (rmb->refs)
6782                         m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6783         else
6784                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6785
6786         pm = (MonoMethodNormal*)m;
6787
6788         m->slot = -1;
6789         m->flags = rmb->attrs;
6790         m->iflags = rmb->iattrs;
6791         m->name = mono_string_to_utf8 (rmb->name);
6792         m->klass = klass;
6793         m->signature = sig;
6794         if (rmb->table_idx)
6795                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6796
6797         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6798                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6799                         m->string_ctor = 1;
6800
6801                 m->signature->pinvoke = 1;
6802         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6803                 /* TODO */
6804                 m->signature->pinvoke = 1;
6805                 return m;
6806         } else if (!m->klass->dummy && 
6807                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6808                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6809                 MonoMethodHeader *header;
6810                 guint32 code_size;
6811                 gint32 max_stack, i;
6812                 gint32 num_locals = 0;
6813                 gint32 num_clauses = 0;
6814                 guint8 *code;
6815
6816                 if (rmb->ilgen) {
6817                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6818                         code_size = rmb->ilgen->code_len;
6819                         max_stack = rmb->ilgen->max_stack;
6820                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6821                         if (rmb->ilgen->ex_handlers)
6822                                 num_clauses = method_count_clauses (rmb->ilgen);
6823                 } else {
6824                         if (rmb->code) {
6825                                 code = mono_array_addr (rmb->code, guint8, 0);
6826                                 code_size = mono_array_length (rmb->code);
6827                                 /* we probably need to run a verifier on the code... */
6828                                 max_stack = 8; 
6829                         }
6830                         else {
6831                                 code = NULL;
6832                                 code_size = 0;
6833                                 max_stack = 8;
6834                         }
6835                 }
6836
6837                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
6838                                                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6839                 header->code_size = code_size;
6840                 header->code = g_malloc (code_size);
6841                 memcpy ((char*)header->code, code, code_size);
6842                 header->max_stack = max_stack;
6843                 header->init_locals = rmb->init_locals;
6844                 header->num_locals = num_locals;
6845
6846                 for (i = 0; i < num_locals; ++i) {
6847                         MonoReflectionLocalBuilder *lb = 
6848                                 mono_array_get (rmb->ilgen->locals, 
6849                                                                 MonoReflectionLocalBuilder*, i);
6850
6851                         header->locals [i] = g_new0 (MonoType, 1);
6852                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6853                 }
6854
6855                 header->num_clauses = num_clauses;
6856                 if (num_clauses) {
6857                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6858                                                                  rmb->ilgen,
6859                                                                  num_clauses);
6860                 }
6861
6862                 if (rmb->generic_params) {
6863                         int count = mono_array_length (rmb->generic_params);
6864                         header->gen_params = g_new0 (MonoGenericParam, count);
6865                         for (i = 0; i < count; i++) {
6866                                 MonoReflectionGenericParam *gp =
6867                                         mono_array_get (rmb->generic_params,
6868                                                         MonoReflectionGenericParam*, i);
6869
6870                                 header->gen_params [i] = *gp->type.type->data.generic_param;
6871                         }
6872                 }
6873
6874                 pm->header = header;
6875         }
6876
6877         if (rmb->refs) {
6878                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6879                 int i;
6880
6881                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6882
6883                 for (i = 0; i < rmb->nrefs; ++i)
6884                         mw->data = g_list_append (mw->data, rmb->refs [i]);
6885         }
6886
6887         method_aux = NULL;
6888
6889         /* Parameter names */
6890         if (rmb->pinfo) {
6891                 if (!method_aux)
6892                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
6893                 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
6894                 for (i = 0; i <= m->signature->param_count; ++i) {
6895                         MonoReflectionParamBuilder *pb;
6896                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6897                                 if (pb->name)
6898                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6899                                 if (pb->cattrs) {
6900                                         if (!method_aux->param_cattr)
6901                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
6902                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
6903                                 }
6904                         }
6905                 }
6906         }
6907
6908         /* Parameter marshalling */
6909         specs = NULL;
6910         if (rmb->pinfo)         
6911                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6912                         MonoReflectionParamBuilder *pb;
6913                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6914                                 if (pb->marshal_info) {
6915                                         if (specs == NULL)
6916                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6917                                         specs [pb->position] = 
6918                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6919                                 }
6920                         }
6921                 }
6922         if (specs != NULL) {
6923                 if (!method_aux)
6924                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
6925                 method_aux->param_marshall = specs;
6926         }
6927
6928         if (klass->image->dynamic && method_aux)
6929                 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6930
6931         return m;
6932 }       
6933
6934 static MonoMethod*
6935 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6936 {
6937         ReflectionMethodBuilder rmb;
6938         MonoMethodSignature *sig;
6939
6940         sig = ctor_builder_to_signature (mb);
6941
6942         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6943
6944         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6945         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6946
6947         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6948                 /* ilgen is no longer needed */
6949                 mb->ilgen = NULL;
6950         }
6951
6952         return mb->mhandle;
6953 }
6954
6955 static MonoMethod*
6956 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6957 {
6958         ReflectionMethodBuilder rmb;
6959         MonoMethodSignature *sig;
6960
6961         sig = method_builder_to_signature (mb);
6962
6963         reflection_methodbuilder_from_method_builder (&rmb, mb);
6964
6965         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6966         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6967
6968         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6969                 /* ilgen is no longer needed */
6970                 mb->ilgen = NULL;
6971         }
6972         return mb->mhandle;
6973 }
6974
6975 static MonoClassField*
6976 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6977 {
6978         MonoClassField *field;
6979         const char *p, *p2;
6980         guint32 len, idx;
6981
6982         if (fb->handle)
6983                 return fb->handle;
6984
6985         field = g_new0 (MonoClassField, 1);
6986
6987         field->name = mono_string_to_utf8 (fb->name);
6988         if (fb->attrs) {
6989                 /* FIXME: handle type modifiers */
6990                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
6991                 field->type->attrs = fb->attrs;
6992         } else {
6993                 field->type = fb->type->type;
6994         }
6995         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
6996                 field->data = mono_array_addr (fb->rva_data, char, 0);
6997         if (fb->offset != -1)
6998                 field->offset = fb->offset;
6999         field->parent = klass;
7000         fb->handle = field;
7001         mono_save_custom_attrs (klass->image, field, fb->cattrs);
7002
7003         if (fb->def_value) {
7004                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7005                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7006                 field->def_value = g_new0 (MonoConstant, 1);
7007                 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7008                 /* Copy the data from the blob since it might get realloc-ed */
7009                 p = assembly->blob.data + idx;
7010                 len = mono_metadata_decode_blob_size (p, &p2);
7011                 len += p2 - p;
7012                 field->def_value->value = g_malloc (len);
7013                 memcpy (field->def_value->value, p, len);
7014         }
7015
7016         return field;
7017 }
7018
7019 static MonoType*
7020 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7021                                             MonoType **types)
7022 {
7023         MonoClass *klass;
7024         MonoReflectionTypeBuilder *tb = NULL;
7025         MonoGenericInst *ginst;
7026         MonoDomain *domain;
7027         MonoType *geninst;
7028         int icount, i;
7029
7030         klass = mono_class_from_mono_type (type->type);
7031         if (!klass->gen_params && !klass->generic_inst &&
7032             !(klass->nested_in && klass->nested_in->gen_params))
7033                 return NULL;
7034
7035         mono_loader_lock ();
7036
7037         domain = mono_object_domain (type);
7038
7039         ginst = g_new0 (MonoGenericInst, 1);
7040
7041         if (!klass->generic_inst) {
7042                 ginst->type_argc = type_argc;
7043                 ginst->type_argv = types;
7044
7045                 for (i = 0; i < ginst->type_argc; ++i) {
7046                         if (!ginst->is_open)
7047                                 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7048                 }
7049
7050                 ginst->generic_type = &klass->byval_arg;
7051         } else {
7052                 MonoGenericInst *kginst = klass->generic_inst;
7053
7054                 ginst->type_argc = kginst->type_argc;
7055                 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7056
7057                 for (i = 0; i < ginst->type_argc; i++) {
7058                         MonoType *t = kginst->type_argv [i];
7059
7060                         if (t->type == MONO_TYPE_VAR)
7061                                 t = types [t->data.generic_param->num];
7062
7063                         if (!ginst->is_open)
7064                                 ginst->is_open = mono_class_is_open_constructed_type (t);
7065
7066                         ginst->type_argv [i] = t;
7067                 }
7068
7069                 ginst->generic_type = kginst->generic_type;
7070         }
7071
7072         geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7073         if (geninst) {
7074                 g_free (ginst);
7075                 mono_loader_unlock ();
7076                 return geninst;
7077         }
7078
7079         ginst->context = g_new0 (MonoGenericContext, 1);
7080         ginst->context->ginst = ginst;
7081
7082         geninst = g_new0 (MonoType, 1);
7083         geninst->type = MONO_TYPE_GENERICINST;
7084         geninst->data.generic_inst = ginst;
7085
7086         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7087                 tb = (MonoReflectionTypeBuilder *) type;
7088
7089                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7090                 ginst->is_dynamic = TRUE;
7091         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7092                 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7093                 MonoReflectionType *rgt = rgi->generic_type;
7094
7095                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7096                 tb = (MonoReflectionTypeBuilder *) rgt;
7097
7098                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7099                 ginst->is_dynamic = TRUE;
7100         } else
7101                 icount = klass->interface_count;
7102
7103         ginst->ifaces = g_new0 (MonoType *, icount);
7104         ginst->count_ifaces = icount;
7105
7106         for (i = 0; i < icount; i++) {
7107                 MonoReflectionType *itype;
7108
7109                 if (tb)
7110                         itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7111                 else
7112                         itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7113                 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7114                 if (!ginst->ifaces [i])
7115                         ginst->ifaces [i] = itype->type;
7116         }
7117
7118         mono_class_create_generic (ginst);
7119
7120         g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7121
7122         mono_loader_unlock ();
7123
7124         return geninst;
7125 }
7126
7127 MonoType*
7128 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7129 {
7130         MonoClass *klass, *pklass = NULL;
7131         MonoReflectionType *parent = NULL;
7132         MonoType *geninst;
7133         MonoReflectionTypeBuilder *tb = NULL;
7134         MonoGenericInst *ginst;
7135         MonoDomain *domain;
7136
7137         domain = mono_object_domain (type);
7138         klass = mono_class_from_mono_type (type->type);
7139
7140         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7141                 tb = (MonoReflectionTypeBuilder *) type;
7142
7143                 if (tb->parent) {
7144                         parent = tb->parent;
7145                         pklass = mono_class_from_mono_type (parent->type);
7146                 }
7147         } else {
7148                 pklass = klass->parent;
7149                 if (pklass)
7150                         parent = mono_type_get_object (domain, &pklass->byval_arg);
7151         }
7152
7153         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7154         if (!geninst)
7155                 return NULL;
7156
7157         ginst = geninst->data.generic_inst;
7158
7159         if (pklass && pklass->generic_inst)
7160                 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7161
7162         return geninst;
7163 }
7164
7165 MonoReflectionMethod*
7166 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7167 {
7168         MonoMethod *method, *inflated;
7169         MonoReflectionMethodBuilder *mb = NULL;
7170         MonoGenericMethod *gmethod;
7171         MonoGenericContext *context;
7172         int count, i;
7173
7174         MONO_ARCH_SAVE_REGS;
7175         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7176                 MonoReflectionTypeBuilder *tb;
7177                 MonoClass *klass;
7178
7179                 mb = (MonoReflectionMethodBuilder *) rmethod;
7180                 tb = (MonoReflectionTypeBuilder *) mb->type;
7181                 klass = mono_class_from_mono_type (tb->type.type);
7182
7183                 method = methodbuilder_to_mono_method (klass, mb);
7184         } else
7185                 method = rmethod->method;
7186
7187         count = method->signature->generic_param_count;
7188         if (count != mono_array_length (types))
7189                 return NULL;
7190
7191         gmethod = g_new0 (MonoGenericMethod, 1);
7192         gmethod->mtype_argc = count;
7193         gmethod->mtype_argv = g_new0 (MonoType *, count);
7194         for (i = 0; i < count; i++) {
7195                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7196                 gmethod->mtype_argv [i] = garg->type;
7197         }
7198
7199         context = g_new0 (MonoGenericContext, 1);
7200         context->ginst = method->klass->generic_inst;
7201         context->gmethod = gmethod;
7202
7203         inflated = mono_class_inflate_generic_method (method, context, NULL);
7204
7205         return mono_method_get_object (
7206                 mono_object_domain (rmethod), inflated, NULL);
7207 }
7208
7209 static MonoMethod *
7210 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7211 {
7212         MonoGenericMethod *gmethod;
7213         MonoGenericInst *ginst;
7214         MonoGenericContext *context;
7215         int i;
7216
7217         ginst = type->type.type->data.generic_inst;
7218
7219         gmethod = g_new0 (MonoGenericMethod, 1);
7220         gmethod->reflection_info = obj;
7221
7222         gmethod->mtype_argc = method->signature->generic_param_count;
7223         gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7224
7225         for (i = 0; i < gmethod->mtype_argc; i++) {
7226                 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7227                 MonoGenericParam *gparam = &mn->header->gen_params [i];
7228
7229                 g_assert (gparam->pklass);
7230                 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7231         }
7232
7233         context = g_new0 (MonoGenericContext, 1);
7234         context->ginst = ginst;
7235         context->gmethod = gmethod;
7236
7237         return mono_class_inflate_generic_method (method, context, ginst->klass);
7238 }
7239
7240 static MonoMethod *
7241 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7242 {
7243         MonoMethod *method;
7244         MonoClass *klass;
7245
7246         klass = mono_class_from_mono_type (type->type.type);
7247
7248         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7249                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7250         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7251                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7252         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7253                  !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7254                 method = ((MonoReflectionMethod *) obj)->method;
7255         else {
7256                 method = NULL; /* prevent compiler warning */
7257                 g_assert_not_reached ();
7258         }
7259
7260         return inflate_mono_method (type, method, obj);
7261 }
7262
7263 void
7264 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7265                                          MonoArray *methods, MonoArray *ctors,
7266                                          MonoArray *fields, MonoArray *properties,
7267                                          MonoArray *events)
7268 {
7269         MonoGenericInst *ginst;
7270         MonoDynamicGenericInst *dginst;
7271         MonoClass *klass, *gklass, *pklass;
7272         int i;
7273
7274         MONO_ARCH_SAVE_REGS;
7275
7276         klass = mono_class_from_mono_type (type->type.type);
7277         ginst = type->type.type->data.generic_inst;
7278
7279         if (ginst->initialized)
7280                 return;
7281
7282         dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7283
7284         gklass = mono_class_from_mono_type (ginst->generic_type);
7285         mono_class_init (gklass);
7286
7287         if (ginst->parent)
7288                 pklass = mono_class_from_mono_type (ginst->parent);
7289         else
7290                 pklass = gklass->parent;
7291
7292         mono_class_setup_parent (klass, pklass);
7293
7294         dginst->count_methods = methods ? mono_array_length (methods) : 0;
7295         dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7296         dginst->count_fields = fields ? mono_array_length (fields) : 0;
7297         dginst->count_properties = properties ? mono_array_length (properties) : 0;
7298         dginst->count_events = events ? mono_array_length (events) : 0;
7299
7300         dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7301         dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7302         dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7303         dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7304         dginst->events = g_new0 (MonoEvent, dginst->count_events);
7305
7306         for (i = 0; i < dginst->count_methods; i++) {
7307                 MonoObject *obj = mono_array_get (methods, gpointer, i);
7308
7309                 dginst->methods [i] = inflate_method (type, obj);
7310         }
7311
7312         for (i = 0; i < dginst->count_ctors; i++) {
7313                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7314
7315                 dginst->ctors [i] = inflate_method (type, obj);
7316         }
7317
7318         for (i = 0; i < dginst->count_fields; i++) {
7319                 MonoObject *obj = mono_array_get (fields, gpointer, i);
7320                 MonoClassField *field;
7321
7322                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7323                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7324                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7325                         field = ((MonoReflectionField *) obj)->field;
7326                 else {
7327                         field = NULL; /* prevent compiler warning */
7328                         g_assert_not_reached ();
7329                 }
7330
7331                 dginst->fields [i] = *field;
7332                 dginst->fields [i].generic_type = field->type;
7333                 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7334         }
7335
7336         for (i = 0; i < dginst->count_properties; i++) {
7337                 MonoObject *obj = mono_array_get (properties, gpointer, i);
7338                 MonoProperty *property = &dginst->properties [i];
7339
7340                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7341                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7342
7343                         property->parent = klass;
7344                         property->attrs = pb->attrs;
7345                         property->name = mono_string_to_utf8 (pb->name);
7346                         if (pb->get_method)
7347                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7348                         if (pb->set_method)
7349                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7350                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7351                         *property = *((MonoReflectionProperty *) obj)->property;
7352
7353                         if (property->get)
7354                                 property->get = inflate_mono_method (type, property->get, NULL);
7355                         if (property->set)
7356                                 property->set = inflate_mono_method (type, property->set, NULL);
7357                 } else
7358                         g_assert_not_reached ();
7359         }
7360
7361         for (i = 0; i < dginst->count_events; i++) {
7362                 MonoObject *obj = mono_array_get (events, gpointer, i);
7363                 MonoEvent *event = &dginst->events [i];
7364
7365                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7366                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7367
7368                         event->parent = klass;
7369                         event->attrs = eb->attrs;
7370                         event->name = mono_string_to_utf8 (eb->name);
7371                         if (eb->add_method)
7372                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7373                         if (eb->remove_method)
7374                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7375                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7376                         *event = *((MonoReflectionEvent *) obj)->event;
7377
7378                         if (event->add)
7379                                 event->add = inflate_mono_method (type, event->add, NULL);
7380                         if (event->remove)
7381                                 event->remove = inflate_mono_method (type, event->remove, NULL);
7382                 } else
7383                         g_assert_not_reached ();
7384         }
7385
7386         ginst->initialized = TRUE;
7387 }
7388
7389 static void
7390 ensure_runtime_vtable (MonoClass *klass)
7391 {
7392         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7393         int i, num, j, onum;
7394         MonoMethod **overrides;
7395
7396         if (!tb || klass->wastypebuilder)
7397                 return;
7398         if (klass->parent)
7399                 ensure_runtime_vtable (klass->parent);
7400
7401         num = tb->ctors? mono_array_length (tb->ctors): 0;
7402         num += tb->num_methods;
7403         klass->method.count = num;
7404         klass->methods = g_new (MonoMethod*, num);
7405         num = tb->ctors? mono_array_length (tb->ctors): 0;
7406         for (i = 0; i < num; ++i)
7407                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7408         num = tb->num_methods;
7409         j = i;
7410         for (i = 0; i < num; ++i)
7411                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7412
7413         klass->wastypebuilder = TRUE;
7414         if (tb->interfaces) {
7415                 klass->interface_count = mono_array_length (tb->interfaces);
7416                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7417                 for (i = 0; i < klass->interface_count; ++i) {
7418                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7419                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7420                 }
7421         }
7422
7423         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7424                 for (i = 0; i < klass->method.count; ++i)
7425                         klass->methods [i]->slot = i;
7426
7427         /* Overrides */
7428         onum = 0;
7429         if (tb->methods) {
7430                 for (i = 0; i < tb->num_methods; ++i) {
7431                         MonoReflectionMethodBuilder *mb = 
7432                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7433                         if (mb->override_method)
7434                                 onum ++;
7435                 }
7436         }
7437
7438         overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7439
7440         if (tb->methods) {
7441                 onum = 0;
7442                 for (i = 0; i < tb->num_methods; ++i) {
7443                         MonoReflectionMethodBuilder *mb = 
7444                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7445                         if (mb->override_method) {
7446                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7447                                 overrides [onum * 2] = 
7448                                         mb->override_method->method;
7449                                 overrides [onum * 2 + 1] =
7450                                         mb->mhandle;
7451
7452                                 g_assert (mb->mhandle);
7453
7454                                 onum ++;
7455                         }
7456                 }
7457         }
7458
7459         mono_class_setup_vtable (klass, overrides, onum);
7460 }
7461
7462 static void
7463 typebuilder_setup_fields (MonoClass *klass)
7464 {
7465         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7466         MonoReflectionFieldBuilder *fb;
7467         MonoClassField *field;
7468         const char *p, *p2;
7469         int i;
7470         guint32 len, idx;
7471
7472         klass->field.count = tb->num_fields;
7473         klass->field.first = 0;
7474         klass->field.last = klass->field.count;
7475
7476         if (!klass->field.count)
7477                 return;
7478         
7479         klass->fields = g_new0 (MonoClassField, klass->field.count);
7480
7481         for (i = 0; i < klass->field.count; ++i) {
7482                 fb = mono_array_get (tb->fields, gpointer, i);
7483                 field = &klass->fields [i];
7484                 field->name = mono_string_to_utf8 (fb->name);
7485                 if (fb->attrs) {
7486                         /* FIXME: handle type modifiers */
7487                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
7488                         field->type->attrs = fb->attrs;
7489                 } else {
7490                         field->type = fb->type->type;
7491                 }
7492                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7493                         field->data = mono_array_addr (fb->rva_data, char, 0);
7494                 if (fb->offset != -1)
7495                         field->offset = fb->offset;
7496                 field->parent = klass;
7497                 fb->handle = field;
7498                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7499
7500                 if (fb->def_value) {
7501                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7502                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7503                         field->def_value = g_new0 (MonoConstant, 1);
7504                         idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7505                         /* Copy the data from the blob since it might get realloc-ed */
7506                         p = assembly->blob.data + idx;
7507                         len = mono_metadata_decode_blob_size (p, &p2);
7508                         len += p2 - p;
7509                         field->def_value->value = g_malloc (len);
7510                         memcpy (field->def_value->value, p, len);
7511                 }
7512         }
7513         mono_class_layout_fields (klass);
7514 }
7515
7516 static void
7517 typebuilder_setup_properties (MonoClass *klass)
7518 {
7519         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7520         MonoReflectionPropertyBuilder *pb;
7521         int i;
7522
7523         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7524         klass->property.first = 0;
7525         klass->property.last = klass->property.count;
7526
7527         klass->properties = g_new0 (MonoProperty, klass->property.count);
7528         for (i = 0; i < klass->property.count; ++i) {
7529                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7530                 klass->properties [i].parent = klass;
7531                 klass->properties [i].attrs = pb->attrs;
7532                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7533                 if (pb->get_method)
7534                         klass->properties [i].get = pb->get_method->mhandle;
7535                 if (pb->set_method)
7536                         klass->properties [i].set = pb->set_method->mhandle;
7537         }
7538 }
7539
7540 MonoReflectionEvent *
7541 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7542 {
7543         MonoEvent *event = g_new0 (MonoEvent, 1);
7544         MonoClass *klass;
7545         int j;
7546
7547         klass = my_mono_class_from_mono_type (tb->type.type);
7548
7549         event->parent = klass;
7550         event->attrs = eb->attrs;
7551         event->name = mono_string_to_utf8 (eb->name);
7552         if (eb->add_method)
7553                 event->add = eb->add_method->mhandle;
7554         if (eb->remove_method)
7555                 event->remove = eb->remove_method->mhandle;
7556         if (eb->raise_method)
7557                 event->raise = eb->raise_method->mhandle;
7558
7559         if (eb->other_methods) {
7560                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7561                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7562                         MonoReflectionMethodBuilder *mb = 
7563                                 mono_array_get (eb->other_methods,
7564                                                 MonoReflectionMethodBuilder*, j);
7565                         event->other [j] = mb->mhandle;
7566                 }
7567         }
7568
7569         return mono_event_get_object (mono_object_domain (tb), klass, event);
7570 }
7571
7572 static void
7573 typebuilder_setup_events (MonoClass *klass)
7574 {
7575         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7576         MonoReflectionEventBuilder *eb;
7577         int i, j;
7578
7579         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7580         klass->event.first = 0;
7581         klass->event.last = klass->event.count;
7582
7583         klass->events = g_new0 (MonoEvent, klass->event.count);
7584         for (i = 0; i < klass->event.count; ++i) {
7585                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7586                 klass->events [i].parent = klass;
7587                 klass->events [i].attrs = eb->attrs;
7588                 klass->events [i].name = mono_string_to_utf8 (eb->name);
7589                 if (eb->add_method)
7590                         klass->events [i].add = eb->add_method->mhandle;
7591                 if (eb->remove_method)
7592                         klass->events [i].remove = eb->remove_method->mhandle;
7593                 if (eb->raise_method)
7594                         klass->events [i].raise = eb->raise_method->mhandle;
7595
7596                 if (eb->other_methods) {
7597                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7598                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7599                                 MonoReflectionMethodBuilder *mb = 
7600                                         mono_array_get (eb->other_methods,
7601                                                                         MonoReflectionMethodBuilder*, j);
7602                                 klass->events [i].other [j] = mb->mhandle;
7603                         }
7604                 }
7605         }
7606 }
7607
7608 MonoReflectionType*
7609 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7610 {
7611         MonoClass *klass;
7612         MonoReflectionType* res;
7613
7614         MONO_ARCH_SAVE_REGS;
7615
7616         klass = my_mono_class_from_mono_type (tb->type.type);
7617
7618         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7619
7620         /*
7621          * Fields to set in klass:
7622          * the various flags: delegate/unicode/contextbound etc.
7623          * nested_classes
7624          */
7625         klass->flags = tb->attrs;
7626
7627         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7628                 /* No need to fully construct the type */
7629                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7630
7631         /* enums are done right away */
7632         if (!klass->enumtype)
7633                 ensure_runtime_vtable (klass);
7634
7635         /* fields and object layout */
7636         if (klass->parent) {
7637                 if (!klass->parent->size_inited)
7638                         mono_class_init (klass->parent);
7639                 klass->instance_size += klass->parent->instance_size;
7640                 klass->class_size += klass->parent->class_size;
7641                 klass->min_align = klass->parent->min_align;
7642         } else {
7643                 klass->instance_size = sizeof (MonoObject);
7644                 klass->min_align = 1;
7645         }
7646
7647         /* FIXME: handle packing_size and instance_size */
7648         typebuilder_setup_fields (klass);
7649
7650         typebuilder_setup_properties (klass);
7651
7652         typebuilder_setup_events (klass);
7653
7654         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7655         /* with enums res == tb: need to fix that. */
7656         if (!klass->enumtype)
7657                 g_assert (res != (MonoReflectionType*)tb);
7658         return res;
7659 }
7660
7661 void
7662 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7663 {
7664         MonoGenericParam *param;
7665         MonoImage *image;
7666
7667         MONO_ARCH_SAVE_REGS;
7668
7669         param = g_new0 (MonoGenericParam, 1);
7670
7671         param->method = NULL;
7672         param->name = mono_string_to_utf8 (gparam->name);
7673         param->num = gparam->index;
7674
7675         image = &gparam->tbuilder->module->dynamic_image->image;
7676         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7677
7678         param->pklass->reflection_info = gparam;
7679
7680         gparam->type.type = g_new0 (MonoType, 1);
7681         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7682         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7683         gparam->type.type->data.generic_param = param;
7684 }
7685
7686 MonoArray *
7687 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7688 {
7689         MonoDynamicImage *assembly = sig->module->dynamic_image;
7690         guint32 na = mono_array_length (sig->arguments);
7691         guint32 buflen, i;
7692         MonoArray *result;
7693         char *buf, *p;
7694
7695         MONO_ARCH_SAVE_REGS;
7696
7697         p = buf = g_malloc (10 + na * 10);
7698
7699         mono_metadata_encode_value (0x07, p, &p);
7700         mono_metadata_encode_value (na, p, &p);
7701         for (i = 0; i < na; ++i) {
7702                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7703                 encode_reflection_type (assembly, type, p, &p);
7704         }
7705
7706         buflen = p - buf;
7707         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7708         p = mono_array_addr (result, char, 0);
7709         memcpy (p, buf, buflen);
7710         g_free (buf);
7711
7712         return result;
7713 }
7714
7715 MonoArray *
7716 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7717 {
7718         MonoDynamicImage *assembly = sig->module->dynamic_image;
7719         guint32 na = mono_array_length (sig->arguments);
7720         guint32 buflen, i;
7721         MonoArray *result;
7722         char *buf, *p;
7723
7724         MONO_ARCH_SAVE_REGS;
7725
7726         p = buf = g_malloc (10 + na * 10);
7727
7728         mono_metadata_encode_value (0x06, p, &p);
7729         for (i = 0; i < na; ++i) {
7730                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7731                 encode_reflection_type (assembly, type, p, &p);
7732         }
7733
7734         buflen = p - buf;
7735         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7736         p = mono_array_addr (result, char, 0);
7737         memcpy (p, buf, buflen);
7738         g_free (buf);
7739
7740         return result;
7741 }
7742
7743 void 
7744 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7745 {
7746         ReflectionMethodBuilder rmb;
7747         MonoMethodSignature *sig;
7748         int i;
7749
7750         sig = dynamic_method_to_signature (mb);
7751
7752         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7753
7754         /*
7755          * Resolve references.
7756          */
7757         rmb.nrefs = mb->nrefs;
7758         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7759         for (i = 0; i < mb->nrefs; ++i) {
7760                 gpointer ref = resolve_object (mb->module->image, 
7761                                                mono_array_get (mb->refs, MonoObject*, i));
7762                 if (!ref) {
7763                         g_free (rmb.refs);
7764                         mono_raise_exception (mono_get_exception_type_load (NULL));
7765                         return;
7766                 }
7767                 rmb.refs [i] = ref;
7768         }               
7769
7770         /* FIXME: class */
7771         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7772
7773         g_free (rmb.refs);
7774
7775         /* ilgen is no longer needed */
7776         mb->ilgen = NULL;
7777 }
7778
7779 /**
7780  * mono_reflection_lookup_dynamic_token:
7781  *
7782  *  Finish the Builder object pointed to by TOKEN and return the corresponding
7783  * runtime structure.
7784  */
7785 gpointer
7786 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7787 {
7788         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7789         MonoObject *obj;
7790
7791         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7792         g_assert (obj);
7793
7794         return resolve_object (image, obj);
7795 }
7796
7797 static gpointer
7798 resolve_object (MonoImage *image, MonoObject *obj)
7799 {
7800         gpointer result = NULL;
7801
7802         if (strcmp (obj->vtable->klass->name, "String") == 0) {
7803                 result = mono_string_intern ((MonoString*)obj);
7804                 g_assert (result);
7805         }
7806         else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7807                 MonoReflectionType *tb = (MonoReflectionType*)obj;
7808                 result = mono_class_from_mono_type (tb->type);
7809                 g_assert (result);
7810         }
7811         else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7812                 result = ((MonoReflectionMethod*)obj)->method;
7813                 g_assert (result);
7814         }
7815         else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7816                 result = ((MonoReflectionMethod*)obj)->method;
7817                 g_assert (result);
7818         }
7819         else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7820                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7821                 result = mb->mhandle;
7822                 if (!result) {
7823                         /* Type is not yet created */
7824                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7825
7826                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7827
7828                         /*
7829                          * Hopefully this has been filled in by calling CreateType() on the
7830                          * TypeBuilder.
7831                          */
7832                         /**
7833                          * TODO: This won't work if the application finishes another 
7834                          * TypeBuilder instance instead of this one.
7835                          */
7836                         result = mb->mhandle;
7837                 }
7838         }
7839         else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7840                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7841
7842                 result = cb->mhandle;
7843                 if (!result) {
7844                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7845
7846                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7847                         result = cb->mhandle;
7848                 }
7849         }
7850         else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7851                 result = ((MonoReflectionField*)obj)->field;
7852                 g_assert (result);
7853         }
7854         else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7855                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7856                 result = fb->handle;
7857
7858                 if (!result) {
7859                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7860
7861                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7862                         result = fb->handle;
7863                 }
7864         }
7865         else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7866                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7867                 MonoClass *klass;
7868
7869                 klass = tb->type.type->data.klass;
7870                 if (klass->wastypebuilder) {
7871                         /* Already created */
7872                         result = klass;
7873                 }
7874                 else {
7875                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7876                         result = tb->type.type->data.klass;
7877                         g_assert (result);
7878                 }
7879         }
7880         else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7881                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7882                 MonoMethodSignature *sig;
7883                 int nargs, i;
7884
7885                 if (helper->arguments)
7886                         nargs = mono_array_length (helper->arguments);
7887                 else
7888                         nargs = 0;
7889
7890                 sig = mono_metadata_signature_alloc (image, nargs);
7891                 sig->explicit_this = helper->call_conv & 64;
7892                 sig->hasthis = helper->call_conv & 32;
7893
7894                 if (helper->call_conv == 0) /* unmanaged */
7895                         sig->call_convention = helper->unmanaged_call_conv - 1;
7896                 else
7897                         if (helper->call_conv & 0x02)
7898                                 sig->call_convention = MONO_CALL_VARARG;
7899                 else
7900                         sig->call_convention = MONO_CALL_DEFAULT;
7901
7902                 sig->param_count = nargs;
7903                 /* TODO: Copy type ? */
7904                 sig->ret = helper->return_type->type;
7905                 for (i = 0; i < nargs; ++i) {
7906                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7907                         sig->params [i] = rt->type;
7908                 }
7909
7910                 result = sig;
7911         }
7912         else {
7913                 g_print (obj->vtable->klass->name);
7914                 g_assert_not_reached ();
7915         }
7916         return result;
7917 }