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