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