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