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