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