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