Thu Aug 5 17:11:44 CEST 2004 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / reflection.c
1 /*
2  * reflection.c: Routines for creating an image at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
8  *
9  */
10 #include <config.h>
11 #include "mono/utils/mono-digest.h"
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/metadata-internals.h"
15 #include "mono/metadata/class-internals.h"
16 #include "mono/metadata/tokentype.h"
17 #include "mono/metadata/domain-internals.h"
18 #include "mono/metadata/opcodes.h"
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/object-internals.h"
21 #include <mono/metadata/exception.h>
22 #include <stdio.h>
23 #include <glib.h>
24 #include <errno.h>
25 #include <time.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include "image.h"
29 #include "cil-coff.h"
30 #include "rawbuffer.h"
31 #include "mono-endian.h"
32 #include "private.h"
33 #include <mono/os/gc_wrapper.h>
34
35 #define TEXT_OFFSET 512
36 #define CLI_H_SIZE 136
37 #define FILE_ALIGN 512
38 #define VIRT_ALIGN 8192
39 #define START_TEXT_RVA  0x00002000
40
41 typedef struct {
42         MonoReflectionILGen *ilgen;
43         MonoReflectionType *rtype;
44         MonoArray *parameters;
45         MonoArray *generic_params;
46         MonoArray *pinfo;
47         MonoArray *opt_types;
48         guint32 attrs;
49         guint32 iattrs;
50         guint32 call_conv;
51         guint32 *table_idx; /* note: it's a pointer */
52         MonoArray *code;
53         MonoObject *type;
54         MonoString *name;
55         MonoBoolean init_locals;
56         MonoArray *return_modreq;
57         MonoArray *return_modopt;
58         MonoArray *param_modreq;
59         MonoArray *param_modopt;
60         MonoArray *permissions;
61         MonoMethod *mhandle;
62         guint32 nrefs;
63         gpointer *refs;
64 } 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_OBJECT:
5867                         case MONO_TYPE_STRING:
5868                                 for (i = 0; i < alen; i++) {
5869                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5870                                         mono_array_set (arr, gpointer, i, item);
5871                                 }
5872                                 break;
5873                         default:
5874                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5875                 }
5876                 *end=p;
5877                 return arr;
5878         }
5879         default:
5880                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5881         }
5882         return NULL;
5883 }
5884
5885 static gboolean
5886 type_is_reference (MonoType *type)
5887 {
5888         switch (type->type) {
5889         case MONO_TYPE_BOOLEAN:
5890         case MONO_TYPE_CHAR:
5891         case MONO_TYPE_U:
5892         case MONO_TYPE_I:
5893         case MONO_TYPE_U1:
5894         case MONO_TYPE_I1:
5895         case MONO_TYPE_U2:
5896         case MONO_TYPE_I2:
5897         case MONO_TYPE_U4:
5898         case MONO_TYPE_I4:
5899         case MONO_TYPE_U8:
5900         case MONO_TYPE_I8:
5901         case MONO_TYPE_R8:
5902         case MONO_TYPE_R4:
5903         case MONO_TYPE_VALUETYPE:
5904                 return FALSE;
5905         default:
5906                 return TRUE;
5907         }
5908 }
5909
5910 static void
5911 free_param_data (MonoMethodSignature *sig, void **params) {
5912         int i;
5913         for (i = 0; i < sig->param_count; ++i) {
5914                 if (!type_is_reference (sig->params [i]))
5915                         g_free (params [i]);
5916         }
5917 }
5918
5919 /*
5920  * Find the method index in the metadata methodDef table.
5921  * Later put these three helper methods in metadata and export them.
5922  */
5923 static guint32
5924 find_method_index (MonoMethod *method) {
5925         MonoClass *klass = method->klass;
5926         int i;
5927
5928         for (i = 0; i < klass->method.count; ++i) {
5929                 if (method == klass->methods [i])
5930                         return klass->method.first + 1 + i;
5931         }
5932         return 0;
5933 }
5934
5935 /*
5936  * Find the field index in the metadata FieldDef table.
5937  */
5938 static guint32
5939 find_field_index (MonoClass *klass, MonoClassField *field) {
5940         int i;
5941
5942         for (i = 0; i < klass->field.count; ++i) {
5943                 if (field == &klass->fields [i])
5944                         return klass->field.first + 1 + i;
5945         }
5946         return 0;
5947 }
5948
5949 /*
5950  * Find the property index in the metadata Property table.
5951  */
5952 static guint32
5953 find_property_index (MonoClass *klass, MonoProperty *property) {
5954         int i;
5955
5956         for (i = 0; i < klass->property.count; ++i) {
5957                 if (property == &klass->properties [i])
5958                         return klass->property.first + 1 + i;
5959         }
5960         return 0;
5961 }
5962
5963 /*
5964  * Find the event index in the metadata Event table.
5965  */
5966 static guint32
5967 find_event_index (MonoClass *klass, MonoEvent *event) {
5968         int i;
5969
5970         for (i = 0; i < klass->event.count; ++i) {
5971                 if (event == &klass->events [i])
5972                         return klass->event.first + 1 + i;
5973         }
5974         return 0;
5975 }
5976
5977 static MonoObject*
5978 create_custom_attr (MonoImage *image, MonoMethod *method, 
5979                                         const char *data, guint32 len)
5980 {
5981         const char *p = data;
5982         const char *named;
5983         guint32 i, j, num_named;
5984         MonoObject *attr;
5985         void **params;
5986
5987         mono_class_init (method->klass);
5988
5989         if (len == 0) {
5990                 attr = mono_object_new (mono_domain_get (), method->klass);
5991                 mono_runtime_invoke (method, attr, NULL, NULL);
5992                 return attr;
5993         }
5994
5995         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5996                 return NULL;
5997
5998         /*g_print ("got attr %s\n", method->klass->name);*/
5999         
6000         params = g_new (void*, method->signature->param_count);
6001
6002         /* skip prolog */
6003         p += 2;
6004         for (i = 0; i < method->signature->param_count; ++i) {
6005                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6006         }
6007
6008         named = p;
6009         attr = mono_object_new (mono_domain_get (), method->klass);
6010         mono_runtime_invoke (method, attr, params, NULL);
6011         free_param_data (method->signature, params);
6012         g_free (params);
6013         num_named = read16 (named);
6014         named += 2;
6015         for (j = 0; j < num_named; j++) {
6016                 gint name_len;
6017                 char *name, named_type, data_type;
6018                 named_type = *named++;
6019                 data_type = *named++; /* type of data */
6020                 if (data_type == 0x55) {
6021                         gint type_len;
6022                         char *type_name;
6023                         type_len = mono_metadata_decode_blob_size (named, &named);
6024                         type_name = g_malloc (type_len + 1);
6025                         memcpy (type_name, named, type_len);
6026                         type_name [type_len] = 0;
6027                         named += type_len;
6028                         /* FIXME: lookup the type and check type consistency */
6029                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6030                         /* this seems to be the type of the element of the array */
6031                         /* g_print ("skipping 0x%02x after prop\n", *named); */
6032                         named++;
6033                 }
6034                 name_len = mono_metadata_decode_blob_size (named, &named);
6035                 name = g_malloc (name_len + 1);
6036                 memcpy (name, named, name_len);
6037                 name [name_len] = 0;
6038                 named += name_len;
6039                 if (named_type == 0x53) {
6040                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6041                         void *val = load_cattr_value (image, field->type, named, &named);
6042                         mono_field_set_value (attr, field, val);
6043                         if (!type_is_reference (field->type))
6044                                 g_free (val);
6045                 } else if (named_type == 0x54) {
6046                         MonoProperty *prop;
6047                         void *pparams [1];
6048                         MonoType *prop_type;
6049
6050                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6051                         /* can we have more that 1 arg in a custom attr named property? */
6052                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6053                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
6054                         mono_property_set_value (prop, attr, pparams, NULL);
6055                         if (!type_is_reference (prop_type))
6056                                 g_free (pparams [0]);
6057                 }
6058                 g_free (name);
6059         }
6060
6061         return attr;
6062 }
6063
6064 MonoArray*
6065 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6066 {
6067         MonoArray *result;
6068         MonoClass *klass;
6069         MonoObject *attr;
6070         int i;
6071
6072         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6073         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6074         for (i = 0; i < cinfo->num_attrs; ++i) {
6075                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6076                 mono_array_set (result, gpointer, i, attr);
6077         }
6078         return result;
6079 }
6080
6081 MonoCustomAttrInfo*
6082 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6083 {
6084         guint32 mtoken, i, len;
6085         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6086         MonoTableInfo *ca;
6087         MonoCustomAttrInfo *ainfo;
6088         GList *tmp, *list = NULL;
6089         const char *data;
6090
6091         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6092
6093         i = mono_metadata_custom_attrs_from_index (image, idx);
6094         if (!i)
6095                 return NULL;
6096         i --;
6097         while (i < ca->rows) {
6098                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6099                         break;
6100                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6101                 ++i;
6102         }
6103         len = g_list_length (list);
6104         if (!len)
6105                 return NULL;
6106         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6107         ainfo->num_attrs = len;
6108         ainfo->image = image;
6109         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6110                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6111                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6112                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6113                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6114                         mtoken |= MONO_TOKEN_METHOD_DEF;
6115                         break;
6116                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6117                         mtoken |= MONO_TOKEN_MEMBER_REF;
6118                         break;
6119                 default:
6120                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6121                         break;
6122                 }
6123                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6124                 if (!ainfo->attrs [i].ctor)
6125                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6126                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6127                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6128                 ainfo->attrs [i].data = data;
6129         }
6130         g_list_free (list);
6131
6132         return ainfo;
6133 }
6134
6135 MonoCustomAttrInfo*
6136 mono_custom_attrs_from_method (MonoMethod *method)
6137 {
6138         MonoCustomAttrInfo *cinfo;
6139         guint32 idx;
6140         
6141         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6142                 return cinfo;
6143         idx = find_method_index (method);
6144         idx <<= MONO_CUSTOM_ATTR_BITS;
6145         idx |= MONO_CUSTOM_ATTR_METHODDEF;
6146         return mono_custom_attrs_from_index (method->klass->image, idx);
6147 }
6148
6149 MonoCustomAttrInfo*
6150 mono_custom_attrs_from_class (MonoClass *klass)
6151 {
6152         MonoCustomAttrInfo *cinfo;
6153         guint32 idx;
6154         
6155         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6156                 return cinfo;
6157         idx = mono_metadata_token_index (klass->type_token);
6158         idx <<= MONO_CUSTOM_ATTR_BITS;
6159         idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6160         return mono_custom_attrs_from_index (klass->image, idx);
6161 }
6162
6163 MonoCustomAttrInfo*
6164 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6165 {
6166         MonoCustomAttrInfo *cinfo;
6167         guint32 idx;
6168         
6169         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6170                 return cinfo;
6171         idx = 1; /* there is only one assembly */
6172         idx <<= MONO_CUSTOM_ATTR_BITS;
6173         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6174         return mono_custom_attrs_from_index (assembly->image, idx);
6175 }
6176
6177 static MonoCustomAttrInfo*
6178 mono_custom_attrs_from_module (MonoImage *image)
6179 {
6180         MonoCustomAttrInfo *cinfo;
6181         guint32 idx;
6182         
6183         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6184                 return cinfo;
6185         idx = 1; /* there is only one module */
6186         idx <<= MONO_CUSTOM_ATTR_BITS;
6187         idx |= MONO_CUSTOM_ATTR_MODULE;
6188         return mono_custom_attrs_from_index (image, idx);
6189 }
6190
6191 MonoCustomAttrInfo*
6192 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6193 {
6194         MonoCustomAttrInfo *cinfo;
6195         guint32 idx;
6196         
6197         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6198                 return cinfo;
6199         idx = find_property_index (klass, property);
6200         idx <<= MONO_CUSTOM_ATTR_BITS;
6201         idx |= MONO_CUSTOM_ATTR_PROPERTY;
6202         return mono_custom_attrs_from_index (klass->image, idx);
6203 }
6204
6205 MonoCustomAttrInfo*
6206 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6207 {
6208         MonoCustomAttrInfo *cinfo;
6209         guint32 idx;
6210         
6211         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6212                 return cinfo;
6213         idx = find_event_index (klass, event);
6214         idx <<= MONO_CUSTOM_ATTR_BITS;
6215         idx |= MONO_CUSTOM_ATTR_EVENT;
6216         return mono_custom_attrs_from_index (klass->image, idx);
6217 }
6218
6219 MonoCustomAttrInfo*
6220 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6221 {
6222         MonoCustomAttrInfo *cinfo;
6223         guint32 idx;
6224         
6225         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6226                 return cinfo;
6227         idx = find_field_index (klass, field);
6228         idx <<= MONO_CUSTOM_ATTR_BITS;
6229         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6230         return mono_custom_attrs_from_index (klass->image, idx);
6231 }
6232
6233 MonoCustomAttrInfo*
6234 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6235 {
6236         MonoTableInfo *ca;
6237         guint32 i, idx, method_index;
6238         guint32 param_list, param_last, param_pos, found;
6239         MonoImage *image;
6240         MonoReflectionMethodAux *aux;
6241
6242         if (method->klass->image->dynamic) {
6243                 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6244                 if (!aux || !aux->param_cattr)
6245                         return NULL;
6246                 return aux->param_cattr [param];
6247         }
6248
6249         image = method->klass->image;
6250         method_index = find_method_index (method);
6251         ca = &image->tables [MONO_TABLE_METHOD];
6252
6253         if (method->klass->generic_inst || method->klass->gen_params ||
6254             method->signature->generic_param_count) {
6255                 /* FIXME FIXME FIXME */
6256                 return NULL;
6257         }
6258
6259         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6260         if (method_index == ca->rows) {
6261                 ca = &image->tables [MONO_TABLE_PARAM];
6262                 param_last = ca->rows + 1;
6263         } else {
6264                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6265                 ca = &image->tables [MONO_TABLE_PARAM];
6266         }
6267         found = FALSE;
6268         for (i = param_list; i < param_last; ++i) {
6269                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6270                 if (param_pos == param) {
6271                         found = TRUE;
6272                         break;
6273                 }
6274         }
6275         if (!found)
6276                 return NULL;
6277         idx = i;
6278         idx <<= MONO_CUSTOM_ATTR_BITS;
6279         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6280         return mono_custom_attrs_from_index (image, idx);
6281 }
6282
6283 /*
6284  * mono_reflection_get_custom_attrs:
6285  * @obj: a reflection object handle
6286  *
6287  * Return an array with all the custom attributes defined of the
6288  * reflection handle @obj. The objects are fully build.
6289  */
6290 MonoArray*
6291 mono_reflection_get_custom_attrs (MonoObject *obj)
6292 {
6293         MonoClass *klass;
6294         MonoArray *result;
6295         MonoCustomAttrInfo *cinfo = NULL;
6296         
6297         MONO_ARCH_SAVE_REGS;
6298
6299         klass = obj->vtable->klass;
6300         /* FIXME: need to handle: Module */
6301         if (klass == mono_defaults.monotype_class) {
6302                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6303                 klass = mono_class_from_mono_type (rtype->type);
6304                 cinfo = mono_custom_attrs_from_class (klass);
6305         } else if (strcmp ("Assembly", klass->name) == 0) {
6306                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6307                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6308         } else if (strcmp ("Module", klass->name) == 0) {
6309                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6310                 cinfo = mono_custom_attrs_from_module (module->image);
6311         } else if (strcmp ("MonoProperty", klass->name) == 0) {
6312                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6313                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6314         } else if (strcmp ("MonoEvent", klass->name) == 0) {
6315                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6316                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6317         } else if (strcmp ("MonoField", klass->name) == 0) {
6318                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6319                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6320         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6321                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6322                 cinfo = mono_custom_attrs_from_method (rmethod->method);
6323         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6324                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6325                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6326                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6327         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6328                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6329                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6330         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6331                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6332                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6333         } else { /* handle other types here... */
6334                 g_error ("get custom attrs not yet supported for %s", klass->name);
6335         }
6336
6337         if (cinfo) {
6338                 result = mono_custom_attrs_construct (cinfo);
6339                 if (!cinfo->cached)
6340                         mono_custom_attrs_free (cinfo);
6341         } else {
6342                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6343                 result = mono_array_new (mono_domain_get (), klass, 0);
6344         }
6345
6346         return result;
6347 }
6348
6349 static MonoMethodSignature*
6350 parameters_to_signature (MonoArray *parameters) {
6351         MonoMethodSignature *sig;
6352         int count, i;
6353
6354         count = parameters? mono_array_length (parameters): 0;
6355
6356         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6357         sig->param_count = count;
6358         sig->sentinelpos = -1; /* FIXME */
6359         for (i = 0; i < count; ++i) {
6360                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6361                 sig->params [i] = pt->type;
6362         }
6363         return sig;
6364 }
6365
6366 static MonoMethodSignature*
6367 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6368         MonoMethodSignature *sig;
6369
6370         sig = parameters_to_signature (ctor->parameters);
6371         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6372         sig->ret = &mono_defaults.void_class->byval_arg;
6373         return sig;
6374 }
6375
6376 static MonoMethodSignature*
6377 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6378         MonoMethodSignature *sig;
6379
6380         sig = parameters_to_signature (method->parameters);
6381         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6382         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6383         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6384         return sig;
6385 }
6386
6387 static MonoMethodSignature*
6388 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6389         MonoMethodSignature *sig;
6390
6391         sig = parameters_to_signature (method->parameters);
6392         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6393         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6394         sig->generic_param_count = 0;
6395         return sig;
6396 }
6397
6398 static void
6399 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6400 {
6401         MonoClass *klass = mono_object_class (prop);
6402         if (strcmp (klass->name, "PropertyBuilder") == 0) {
6403                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6404                 *name = mono_string_to_utf8 (pb->name);
6405                 *type = pb->type->type;
6406         } else {
6407                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6408                 *name = g_strdup (p->property->name);
6409                 if (p->property->get)
6410                         *type = p->property->get->signature->ret;
6411                 else
6412                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6413         }
6414 }
6415
6416 static void
6417 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6418 {
6419         MonoClass *klass = mono_object_class (field);
6420         if (strcmp (klass->name, "FieldBuilder") == 0) {
6421                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6422                 *name = mono_string_to_utf8 (fb->name);
6423                 *type = fb->type->type;
6424         } else {
6425                 MonoReflectionField *f = (MonoReflectionField *)field;
6426                 *name = g_strdup (f->field->name);
6427                 *type = f->field->type;
6428         }
6429 }
6430
6431 /*
6432  * Encode a value in a custom attribute stream of bytes.
6433  * The value to encode is either supplied as an object in argument val
6434  * (valuetypes are boxed), or as a pointer to the data in the
6435  * argument argval.
6436  * @type represents the type of the value
6437  * @buffer is the start of the buffer
6438  * @p the current position in the buffer
6439  * @buflen contains the size of the buffer and is used to return the new buffer size
6440  * if this needs to be realloced.
6441  * @retbuffer and @retp return the start and the position of the buffer
6442  */
6443 static void
6444 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6445 {
6446         MonoTypeEnum simple_type;
6447         
6448         if ((p-buffer) + 10 >= *buflen) {
6449                 char *newbuf;
6450                 *buflen *= 2;
6451                 newbuf = g_realloc (buffer, *buflen);
6452                 p = newbuf + (p-buffer);
6453                 buffer = newbuf;
6454         }
6455         if (!argval)
6456                 argval = ((char*)arg + sizeof (MonoObject));
6457         simple_type = type->type;
6458 handle_enum:
6459         switch (simple_type) {
6460         case MONO_TYPE_BOOLEAN:
6461         case MONO_TYPE_U1:
6462         case MONO_TYPE_I1:
6463                 *p++ = *argval;
6464                 break;
6465         case MONO_TYPE_CHAR:
6466         case MONO_TYPE_U2:
6467         case MONO_TYPE_I2:
6468                 swap_with_size (p, argval, 2, 1);
6469                 p += 2;
6470                 break;
6471         case MONO_TYPE_U4:
6472         case MONO_TYPE_I4:
6473         case MONO_TYPE_R4:
6474                 swap_with_size (p, argval, 4, 1);
6475                 p += 4;
6476                 break;
6477         case MONO_TYPE_U8:
6478         case MONO_TYPE_I8:
6479         case MONO_TYPE_R8:
6480                 swap_with_size (p, argval, 8, 1);
6481                 p += 8;
6482                 break;
6483         case MONO_TYPE_VALUETYPE:
6484                 if (type->data.klass->enumtype) {
6485                         simple_type = type->data.klass->enum_basetype->type;
6486                         goto handle_enum;
6487                 } else {
6488                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6489                 }
6490                 break;
6491         case MONO_TYPE_STRING: {
6492                 char *str;
6493                 guint32 slen;
6494                 if (!arg) {
6495                         *p++ = 0xFF;
6496                         break;
6497                 }
6498                 str = mono_string_to_utf8 ((MonoString*)arg);
6499                 slen = strlen (str);
6500                 if ((p-buffer) + 10 + slen >= *buflen) {
6501                         char *newbuf;
6502                         *buflen *= 2;
6503                         *buflen += slen;
6504                         newbuf = g_realloc (buffer, *buflen);
6505                         p = newbuf + (p-buffer);
6506                         buffer = newbuf;
6507                 }
6508                 mono_metadata_encode_value (slen, p, &p);
6509                 memcpy (p, str, slen);
6510                 p += slen;
6511                 g_free (str);
6512                 break;
6513         }
6514         case MONO_TYPE_CLASS: {
6515                 char *str;
6516                 guint32 slen;
6517                 MonoClass *k;
6518                 if (!arg) {
6519                         *p++ = 0xFF;
6520                         break;
6521                 }
6522                 k = mono_object_class (arg);
6523                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6524                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6525                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6526 handle_type:
6527                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6528                 slen = strlen (str);
6529                 if ((p-buffer) + 10 + slen >= *buflen) {
6530                         char *newbuf;
6531                         *buflen *= 2;
6532                         *buflen += slen;
6533                         newbuf = g_realloc (buffer, *buflen);
6534                         p = newbuf + (p-buffer);
6535                         buffer = newbuf;
6536                 }
6537                 mono_metadata_encode_value (slen, p, &p);
6538                 memcpy (p, str, slen);
6539                 p += slen;
6540                 g_free (str);
6541                 break;
6542         }
6543         case MONO_TYPE_SZARRAY: {
6544                 int len, i;
6545                 MonoClass *eclass, *arg_eclass;
6546
6547                 if (!arg) {
6548                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6549                         break;
6550                 }
6551                 len = mono_array_length ((MonoArray*)arg);
6552                 *p++ = len & 0xff;
6553                 *p++ = (len >> 8) & 0xff;
6554                 *p++ = (len >> 16) & 0xff;
6555                 *p++ = (len >> 24) & 0xff;
6556                 *retp = p;
6557                 *retbuffer = buffer;
6558                 eclass = type->data.klass;
6559                 arg_eclass = mono_object_class (arg)->element_class;
6560                 if (eclass->valuetype && arg_eclass->valuetype) {
6561                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6562                         int elsize = mono_class_array_element_size (eclass);
6563                         for (i = 0; i < len; ++i) {
6564                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6565                                 elptr += elsize;
6566                         }
6567                 } else {
6568                         for (i = 0; i < len; ++i) {
6569                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6570                         }
6571                 }
6572                 break;
6573         }
6574         /* it may be a boxed value or a Type */
6575         case MONO_TYPE_OBJECT: {
6576                 MonoClass *klass = mono_object_class (arg);
6577                 char *str;
6578                 guint32 slen;
6579                 
6580                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6581                         *p++ = 0x50;
6582                         goto handle_type;
6583                 } else if (klass->enumtype) {
6584                         *p++ = 0x55;
6585                 } else if (klass == mono_defaults.string_class) {
6586                         simple_type = MONO_TYPE_STRING;
6587                         *p++ = 0x0E;
6588                         goto handle_enum;
6589                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6590                         *p++ = simple_type = klass->byval_arg.type;
6591                         goto handle_enum;
6592                 } else {
6593                         g_error ("unhandled type in custom attr");
6594                 }
6595                 str = type_get_qualified_name (klass->enum_basetype, NULL);
6596                 slen = strlen (str);
6597                 if ((p-buffer) + 10 + slen >= *buflen) {
6598                         char *newbuf;
6599                         *buflen *= 2;
6600                         *buflen += slen;
6601                         newbuf = g_realloc (buffer, *buflen);
6602                         p = newbuf + (p-buffer);
6603                         buffer = newbuf;
6604                 }
6605                 mono_metadata_encode_value (slen, p, &p);
6606                 memcpy (p, str, slen);
6607                 p += slen;
6608                 g_free (str);
6609                 simple_type = klass->enum_basetype->type;
6610                 goto handle_enum;
6611         }
6612         default:
6613                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6614         }
6615         *retp = p;
6616         *retbuffer = buffer;
6617 }
6618
6619 /*
6620  * mono_reflection_get_custom_attrs_blob:
6621  * @ctor: custom attribute constructor
6622  * @ctorArgs: arguments o the constructor
6623  * @properties:
6624  * @propValues:
6625  * @fields:
6626  * @fieldValues:
6627  * 
6628  * Creates the blob of data that needs to be saved in the metadata and that represents
6629  * the custom attributed described by @ctor, @ctorArgs etc.
6630  * Returns: a Byte array representing the blob of data.
6631  */
6632 MonoArray*
6633 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
6634 {
6635         MonoArray *result;
6636         MonoMethodSignature *sig;
6637         MonoObject *arg;
6638         char *buffer, *p;
6639         guint32 buflen, i;
6640
6641         MONO_ARCH_SAVE_REGS;
6642
6643         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6644                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6645         } else {
6646                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6647         }
6648         g_assert (mono_array_length (ctorArgs) == sig->param_count);
6649         buflen = 256;
6650         p = buffer = g_malloc (buflen);
6651         /* write the prolog */
6652         *p++ = 1;
6653         *p++ = 0;
6654         for (i = 0; i < sig->param_count; ++i) {
6655                 arg = mono_array_get (ctorArgs, MonoObject*, i);
6656                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
6657         }
6658         i = 0;
6659         if (properties)
6660                 i += mono_array_length (properties);
6661         if (fields)
6662                 i += mono_array_length (fields);
6663         *p++ = i & 0xff;
6664         *p++ = (i >> 8) & 0xff;
6665         if (properties) {
6666                 MonoObject *prop;
6667                 for (i = 0; i < mono_array_length (properties); ++i) {
6668                         MonoType *ptype;
6669                         char *pname;
6670                         int len;
6671                         
6672                         prop = mono_array_get (properties, gpointer, i);
6673                         get_prop_name_and_type (prop, &pname, &ptype);
6674                         *p++ = 0x54; /* PROPERTY signature */
6675
6676                         /* Preallocate a large enough buffer */
6677                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6678                                 char *str = type_get_qualified_name (ptype, NULL);
6679                                 len = strlen (str);
6680                                 g_free (str);
6681                         }
6682                         else
6683                                 len = 0;
6684                         len += strlen (pname);
6685
6686                         if ((p-buffer) + 20 + len >= buflen) {
6687                                 char *newbuf;
6688                                 buflen *= 2;
6689                                 buflen += len;
6690                                 newbuf = g_realloc (buffer, buflen);
6691                                 p = newbuf + (p-buffer);
6692                                 buffer = newbuf;
6693                         }
6694
6695                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6696                                 char *str = type_get_qualified_name (ptype, NULL);
6697                                 int slen = strlen (str);
6698
6699                                 *p++ = 0x55;
6700                                 /*
6701                                  * This seems to be optional...
6702                                  * *p++ = 0x80;
6703                                  */
6704                                 mono_metadata_encode_value (slen, p, &p);
6705                                 memcpy (p, str, slen);
6706                                 p += slen;
6707                                 g_free (str);
6708                         } else {
6709                                 mono_metadata_encode_value (ptype->type, p, &p);
6710                                 if (ptype->type == MONO_TYPE_SZARRAY)
6711                                         mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6712                         }
6713                         len = strlen (pname);
6714                         mono_metadata_encode_value (len, p, &p);
6715                         memcpy (p, pname, len);
6716                         p += len;
6717                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
6718                         g_free (pname);
6719                 }
6720         }
6721
6722         if (fields) {
6723                 MonoObject *field;
6724                 for (i = 0; i < mono_array_length (fields); ++i) {
6725                         MonoType *ftype;
6726                         char *fname;
6727                         int len;
6728                         
6729                         field = mono_array_get (fields, gpointer, i);
6730                         get_field_name_and_type (field, &fname, &ftype);
6731                         *p++ = 0x53; /* FIELD signature */
6732                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6733                                 char *str = type_get_qualified_name (ftype, NULL);
6734                                 int slen = strlen (str);
6735                                 if ((p-buffer) + 10 + slen >= buflen) {
6736                                         char *newbuf;
6737                                         buflen *= 2;
6738                                         buflen += slen;
6739                                         newbuf = g_realloc (buffer, buflen);
6740                                         p = newbuf + (p-buffer);
6741                                         buffer = newbuf;
6742                                 }
6743                                 *p++ = 0x55;
6744                                 /*
6745                                  * This seems to be optional...
6746                                  * *p++ = 0x80;
6747                                  */
6748                                 mono_metadata_encode_value (slen, p, &p);
6749                                 memcpy (p, str, slen);
6750                                 p += slen;
6751                                 g_free (str);
6752                         } else {
6753                                 mono_metadata_encode_value (ftype->type, p, &p);
6754                                 if (ftype->type == MONO_TYPE_SZARRAY)
6755                                         mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
6756                         }
6757                         len = strlen (fname);
6758                         mono_metadata_encode_value (len, p, &p);
6759                         memcpy (p, fname, len);
6760                         p += len;
6761                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
6762                         g_free (fname);
6763                 }
6764         }
6765
6766         g_assert (p - buffer <= buflen);
6767         buflen = p - buffer;
6768         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6769         p = mono_array_addr (result, char, 0);
6770         memcpy (p, buffer, buflen);
6771         g_free (buffer);
6772         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6773                 g_free (sig);
6774         return result;
6775 }
6776
6777 /*
6778  * mono_reflection_setup_internal_class:
6779  * @tb: a TypeBuilder object
6780  *
6781  * Creates a MonoClass that represents the TypeBuilder.
6782  * This is a trick that lets us simplify a lot of reflection code
6783  * (and will allow us to support Build and Run assemblies easier).
6784  */
6785 void
6786 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6787 {
6788         MonoClass *klass, *parent;
6789
6790         MONO_ARCH_SAVE_REGS;
6791
6792         if (tb->parent) {
6793                 /* check so we can compile corlib correctly */
6794                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6795                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6796                         parent = tb->parent->type->data.klass;
6797                 } else 
6798                         parent = my_mono_class_from_mono_type (tb->parent->type);
6799         } else
6800                 parent = NULL;
6801         
6802         /* the type has already being created: it means we just have to change the parent */
6803         if (tb->type.type) {
6804                 klass = mono_class_from_mono_type (tb->type.type);
6805                 klass->parent = NULL;
6806                 /* fool mono_class_setup_parent */
6807                 g_free (klass->supertypes);
6808                 klass->supertypes = NULL;
6809                 mono_class_setup_parent (klass, parent);
6810                 return;
6811         }
6812         
6813         klass = g_new0 (MonoClass, 1);
6814
6815         klass->image = &tb->module->dynamic_image->image;
6816
6817         klass->inited = 1; /* we lie to the runtime */
6818         klass->name = mono_string_to_utf8 (tb->name);
6819         klass->name_space = mono_string_to_utf8 (tb->nspace);
6820         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6821         klass->flags = tb->attrs;
6822
6823         klass->element_class = klass;
6824         klass->reflection_info = tb; /* need to pin. */
6825
6826         /* Put into cache so mono_class_get () will find it */
6827         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6828                                                                   tb->table_idx);
6829
6830         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6831                                                           GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6832                                                           tb);
6833
6834         if (parent != NULL)
6835                 mono_class_setup_parent (klass, parent);
6836         else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6837                 const char *old_n = klass->name;
6838                 /* trick to get relative numbering right when compiling corlib */
6839                 klass->name = "BuildingObject";
6840                 mono_class_setup_parent (klass, mono_defaults.object_class);
6841                 klass->name = old_n;
6842         }
6843         mono_class_setup_mono_type (klass);
6844
6845         mono_class_setup_supertypes (klass);
6846
6847         /*
6848          * FIXME: handle interfaces.
6849          */
6850
6851         tb->type.type = &klass->byval_arg;
6852
6853         if (tb->nesting_type) {
6854                 g_assert (tb->nesting_type->type);
6855                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6856         }
6857
6858         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6859 }
6860
6861 /*
6862  * mono_reflection_setup_generic_class:
6863  * @tb: a TypeBuilder object
6864  *
6865  * Setup the generic class after all generic parameters have been added.
6866  */
6867 void
6868 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6869 {
6870         MonoClass *klass;
6871         int count, i;
6872
6873         MONO_ARCH_SAVE_REGS;
6874
6875         klass = my_mono_class_from_mono_type (tb->type.type);
6876
6877         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6878
6879         if (klass->gen_params || (count == 0))
6880                 return;
6881
6882         klass->num_gen_params = count;
6883         klass->gen_params = g_new0 (MonoGenericParam, count);
6884
6885         for (i = 0; i < count; i++) {
6886                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6887                 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6888         }
6889 }
6890
6891 /*
6892  * mono_reflection_create_internal_class:
6893  * @tb: a TypeBuilder object
6894  *
6895  * Actually create the MonoClass that is associated with the TypeBuilder.
6896  */
6897 void
6898 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6899 {
6900         MonoClass *klass;
6901
6902         MONO_ARCH_SAVE_REGS;
6903
6904         klass = my_mono_class_from_mono_type (tb->type.type);
6905
6906         if (klass->enumtype && klass->enum_basetype == NULL) {
6907                 MonoReflectionFieldBuilder *fb;
6908
6909                 g_assert (tb->fields != NULL);
6910                 g_assert (mono_array_length (tb->fields) >= 1);
6911
6912                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6913
6914                 klass->enum_basetype = fb->type->type;
6915                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6916                 if (!klass->element_class)
6917                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6918                 klass->instance_size = klass->element_class->instance_size;
6919                 klass->size_inited = 1;
6920                 /* 
6921                  * this is almost safe to do with enums and it's needed to be able
6922                  * to create objects of the enum type (for use in SetConstant).
6923                  */
6924                 /* FIXME: Does this mean enums can't have method overrides ? */
6925                 mono_class_setup_vtable (klass, NULL, 0);
6926         }
6927 }
6928
6929 static MonoMarshalSpec*
6930 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6931                                                                 MonoReflectionMarshal *minfo)
6932 {
6933         MonoMarshalSpec *res;
6934
6935         res = g_new0 (MonoMarshalSpec, 1);
6936         res->native = minfo->type;
6937
6938         switch (minfo->type) {
6939         case MONO_NATIVE_LPARRAY:
6940                 res->data.array_data.elem_type = minfo->eltype;
6941                 res->data.array_data.param_num = 0; /* Not yet */
6942                 res->data.array_data.num_elem = minfo->count;
6943                 break;
6944
6945         case MONO_NATIVE_BYVALTSTR:
6946         case MONO_NATIVE_BYVALARRAY:
6947                 res->data.array_data.num_elem = minfo->count;
6948                 break;
6949
6950         case MONO_NATIVE_CUSTOM:
6951                 if (minfo->marshaltyperef)
6952                         res->data.custom_data.custom_name =
6953                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6954                 if (minfo->mcookie)
6955                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6956                 break;
6957
6958         default:
6959                 break;
6960         }
6961
6962         return res;
6963 }
6964
6965 static MonoMethod*
6966 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6967                                          ReflectionMethodBuilder *rmb,
6968                                          MonoMethodSignature *sig)
6969 {
6970         MonoMethod *m;
6971         MonoMethodNormal *pm;
6972         MonoMarshalSpec **specs;
6973         MonoReflectionMethodAux *method_aux;
6974         int i;
6975
6976         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6977             (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6978                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6979         else 
6980                 if (rmb->refs)
6981                         m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6982         else
6983                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6984
6985         pm = (MonoMethodNormal*)m;
6986
6987         m->slot = -1;
6988         m->flags = rmb->attrs;
6989         m->iflags = rmb->iattrs;
6990         m->name = mono_string_to_utf8 (rmb->name);
6991         m->klass = klass;
6992         m->signature = sig;
6993         if (rmb->table_idx)
6994                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6995
6996         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6997                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6998                         m->string_ctor = 1;
6999
7000                 m->signature->pinvoke = 1;
7001         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7002                 /* TODO */
7003                 m->signature->pinvoke = 1;
7004                 return m;
7005         } else if (!m->klass->dummy && 
7006                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7007                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7008                 MonoMethodHeader *header;
7009                 guint32 code_size;
7010                 gint32 max_stack, i;
7011                 gint32 num_locals = 0;
7012                 gint32 num_clauses = 0;
7013                 guint8 *code;
7014
7015                 if (rmb->ilgen) {
7016                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7017                         code_size = rmb->ilgen->code_len;
7018                         max_stack = rmb->ilgen->max_stack;
7019                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7020                         if (rmb->ilgen->ex_handlers)
7021                                 num_clauses = method_count_clauses (rmb->ilgen);
7022                 } else {
7023                         if (rmb->code) {
7024                                 code = mono_array_addr (rmb->code, guint8, 0);
7025                                 code_size = mono_array_length (rmb->code);
7026                                 /* we probably need to run a verifier on the code... */
7027                                 max_stack = 8; 
7028                         }
7029                         else {
7030                                 code = NULL;
7031                                 code_size = 0;
7032                                 max_stack = 8;
7033                         }
7034                 }
7035
7036                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
7037                                                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7038                 header->code_size = code_size;
7039                 header->code = g_malloc (code_size);
7040                 memcpy ((char*)header->code, code, code_size);
7041                 header->max_stack = max_stack;
7042                 header->init_locals = rmb->init_locals;
7043                 header->num_locals = num_locals;
7044
7045                 for (i = 0; i < num_locals; ++i) {
7046                         MonoReflectionLocalBuilder *lb = 
7047                                 mono_array_get (rmb->ilgen->locals, 
7048                                                                 MonoReflectionLocalBuilder*, i);
7049
7050                         header->locals [i] = g_new0 (MonoType, 1);
7051                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7052                 }
7053
7054                 header->num_clauses = num_clauses;
7055                 if (num_clauses) {
7056                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7057                                                                  rmb->ilgen,
7058                                                                  num_clauses);
7059                 }
7060
7061                 if (rmb->generic_params) {
7062                         int count = mono_array_length (rmb->generic_params);
7063                         header->gen_params = g_new0 (MonoGenericParam, count);
7064                         for (i = 0; i < count; i++) {
7065                                 MonoReflectionGenericParam *gp =
7066                                         mono_array_get (rmb->generic_params,
7067                                                         MonoReflectionGenericParam*, i);
7068
7069                                 header->gen_params [i] = *gp->type.type->data.generic_param;
7070                         }
7071                 }
7072
7073                 pm->header = header;
7074         }
7075
7076         if (rmb->refs) {
7077                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7078                 int i;
7079
7080                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7081
7082                 for (i = 0; i < rmb->nrefs; ++i)
7083                         mw->data = g_list_append (mw->data, rmb->refs [i]);
7084         }
7085
7086         method_aux = NULL;
7087
7088         /* Parameter names */
7089         if (rmb->pinfo) {
7090                 if (!method_aux)
7091                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7092                 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7093                 for (i = 0; i <= m->signature->param_count; ++i) {
7094                         MonoReflectionParamBuilder *pb;
7095                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7096                                 if (pb->name)
7097                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7098                                 if (pb->cattrs) {
7099                                         if (!method_aux->param_cattr)
7100                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7101                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7102                                 }
7103                         }
7104                 }
7105         }
7106
7107         /* Parameter marshalling */
7108         specs = NULL;
7109         if (rmb->pinfo)         
7110                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7111                         MonoReflectionParamBuilder *pb;
7112                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7113                                 if (pb->marshal_info) {
7114                                         if (specs == NULL)
7115                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7116                                         specs [pb->position] = 
7117                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7118                                 }
7119                         }
7120                 }
7121         if (specs != NULL) {
7122                 if (!method_aux)
7123                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7124                 method_aux->param_marshall = specs;
7125         }
7126
7127         if (klass->image->dynamic && method_aux)
7128                 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7129
7130         return m;
7131 }       
7132
7133 static MonoMethod*
7134 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7135 {
7136         ReflectionMethodBuilder rmb;
7137         MonoMethodSignature *sig;
7138
7139         sig = ctor_builder_to_signature (mb);
7140
7141         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7142
7143         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7144         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7145
7146         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7147                 /* ilgen is no longer needed */
7148                 mb->ilgen = NULL;
7149         }
7150
7151         return mb->mhandle;
7152 }
7153
7154 static MonoMethod*
7155 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7156 {
7157         ReflectionMethodBuilder rmb;
7158         MonoMethodSignature *sig;
7159
7160         sig = method_builder_to_signature (mb);
7161
7162         reflection_methodbuilder_from_method_builder (&rmb, mb);
7163
7164         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7165         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7166
7167         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7168                 /* ilgen is no longer needed */
7169                 mb->ilgen = NULL;
7170         }
7171         return mb->mhandle;
7172 }
7173
7174 static MonoClassField*
7175 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7176 {
7177         MonoClassField *field;
7178         const char *p, *p2;
7179         guint32 len, idx;
7180
7181         if (fb->handle)
7182                 return fb->handle;
7183
7184         field = g_new0 (MonoClassField, 1);
7185
7186         field->name = mono_string_to_utf8 (fb->name);
7187         if (fb->attrs) {
7188                 /* FIXME: handle type modifiers */
7189                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7190                 field->type->attrs = fb->attrs;
7191         } else {
7192                 field->type = fb->type->type;
7193         }
7194         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7195                 field->data = mono_array_addr (fb->rva_data, char, 0);
7196         if (fb->offset != -1)
7197                 field->offset = fb->offset;
7198         field->parent = klass;
7199         fb->handle = field;
7200         mono_save_custom_attrs (klass->image, field, fb->cattrs);
7201
7202         if (fb->def_value) {
7203                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7204                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7205                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7206                 /* Copy the data from the blob since it might get realloc-ed */
7207                 p = assembly->blob.data + idx;
7208                 len = mono_metadata_decode_blob_size (p, &p2);
7209                 len += p2 - p;
7210                 field->data = g_malloc (len);
7211                 memcpy (field->data, p, len);
7212         }
7213
7214         return field;
7215 }
7216
7217 static MonoType*
7218 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7219                                             MonoType **types)
7220 {
7221         MonoClass *klass;
7222         MonoReflectionTypeBuilder *tb = NULL;
7223         MonoGenericInst *ginst;
7224         MonoDomain *domain;
7225         MonoType *geninst;
7226         int icount, i;
7227
7228         klass = mono_class_from_mono_type (type->type);
7229         if (!klass->gen_params && !klass->generic_inst &&
7230             !(klass->nested_in && klass->nested_in->gen_params))
7231                 return NULL;
7232
7233         mono_loader_lock ();
7234
7235         domain = mono_object_domain (type);
7236
7237         ginst = g_new0 (MonoGenericInst, 1);
7238
7239         if (!klass->generic_inst) {
7240                 ginst->type_argc = type_argc;
7241                 ginst->type_argv = types;
7242
7243                 for (i = 0; i < ginst->type_argc; ++i) {
7244                         if (!ginst->is_open)
7245                                 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7246                 }
7247
7248                 ginst->generic_type = &klass->byval_arg;
7249         } else {
7250                 MonoGenericInst *kginst = klass->generic_inst;
7251
7252                 ginst->type_argc = kginst->type_argc;
7253                 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7254
7255                 for (i = 0; i < ginst->type_argc; i++) {
7256                         MonoType *t = kginst->type_argv [i];
7257
7258                         if (t->type == MONO_TYPE_VAR)
7259                                 t = types [t->data.generic_param->num];
7260
7261                         if (!ginst->is_open)
7262                                 ginst->is_open = mono_class_is_open_constructed_type (t);
7263
7264                         ginst->type_argv [i] = t;
7265                 }
7266
7267                 ginst->generic_type = kginst->generic_type;
7268         }
7269
7270         geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7271         if (geninst) {
7272                 g_free (ginst);
7273                 mono_loader_unlock ();
7274                 return geninst;
7275         }
7276
7277         ginst->context = g_new0 (MonoGenericContext, 1);
7278         ginst->context->ginst = ginst;
7279
7280         geninst = g_new0 (MonoType, 1);
7281         geninst->type = MONO_TYPE_GENERICINST;
7282         geninst->data.generic_inst = ginst;
7283
7284         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7285                 tb = (MonoReflectionTypeBuilder *) type;
7286
7287                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7288                 ginst->is_dynamic = TRUE;
7289         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7290                 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7291                 MonoReflectionType *rgt = rgi->generic_type;
7292
7293                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7294                 tb = (MonoReflectionTypeBuilder *) rgt;
7295
7296                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7297                 ginst->is_dynamic = TRUE;
7298         } else
7299                 icount = klass->interface_count;
7300
7301         ginst->ifaces = g_new0 (MonoType *, icount);
7302         ginst->count_ifaces = icount;
7303
7304         for (i = 0; i < icount; i++) {
7305                 MonoReflectionType *itype;
7306
7307                 if (tb)
7308                         itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7309                 else
7310                         itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7311                 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7312                 if (!ginst->ifaces [i])
7313                         ginst->ifaces [i] = itype->type;
7314         }
7315
7316         mono_class_create_generic (ginst);
7317
7318         g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7319
7320         mono_loader_unlock ();
7321
7322         return geninst;
7323 }
7324
7325 MonoType*
7326 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7327 {
7328         MonoClass *klass, *pklass = NULL;
7329         MonoReflectionType *parent = NULL;
7330         MonoType *geninst;
7331         MonoReflectionTypeBuilder *tb = NULL;
7332         MonoGenericInst *ginst;
7333         MonoDomain *domain;
7334
7335         domain = mono_object_domain (type);
7336         klass = mono_class_from_mono_type (type->type);
7337
7338         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7339                 tb = (MonoReflectionTypeBuilder *) type;
7340
7341                 if (tb->parent) {
7342                         parent = tb->parent;
7343                         pklass = mono_class_from_mono_type (parent->type);
7344                 }
7345         } else {
7346                 pklass = klass->parent;
7347                 if (pklass)
7348                         parent = mono_type_get_object (domain, &pklass->byval_arg);
7349         }
7350
7351         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7352         if (!geninst)
7353                 return NULL;
7354
7355         ginst = geninst->data.generic_inst;
7356
7357         if (pklass && pklass->generic_inst)
7358                 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7359
7360         return geninst;
7361 }
7362
7363 MonoReflectionMethod*
7364 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7365 {
7366         MonoMethod *method, *inflated;
7367         MonoReflectionMethodBuilder *mb = NULL;
7368         MonoGenericMethod *gmethod;
7369         MonoGenericContext *context;
7370         int count, i;
7371
7372         MONO_ARCH_SAVE_REGS;
7373         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7374                 MonoReflectionTypeBuilder *tb;
7375                 MonoClass *klass;
7376
7377                 mb = (MonoReflectionMethodBuilder *) rmethod;
7378                 tb = (MonoReflectionTypeBuilder *) mb->type;
7379                 klass = mono_class_from_mono_type (tb->type.type);
7380
7381                 method = methodbuilder_to_mono_method (klass, mb);
7382         } else
7383                 method = rmethod->method;
7384
7385         count = method->signature->generic_param_count;
7386         if (count != mono_array_length (types))
7387                 return NULL;
7388
7389         gmethod = g_new0 (MonoGenericMethod, 1);
7390         gmethod->mtype_argc = count;
7391         gmethod->mtype_argv = g_new0 (MonoType *, count);
7392         for (i = 0; i < count; i++) {
7393                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7394                 gmethod->mtype_argv [i] = garg->type;
7395         }
7396
7397         gmethod->reflection_info = rmethod;
7398
7399         context = g_new0 (MonoGenericContext, 1);
7400         context->ginst = method->klass->generic_inst;
7401         context->gmethod = gmethod;
7402
7403         inflated = mono_class_inflate_generic_method (method, context, NULL);
7404
7405         return mono_method_get_object (
7406                 mono_object_domain (rmethod), inflated, NULL);
7407 }
7408
7409 static MonoMethod *
7410 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7411 {
7412         MonoGenericMethod *gmethod;
7413         MonoGenericInst *ginst;
7414         MonoGenericContext *context;
7415         int i;
7416
7417         ginst = type->type.type->data.generic_inst;
7418
7419         gmethod = g_new0 (MonoGenericMethod, 1);
7420         gmethod->reflection_info = obj;
7421
7422         gmethod->mtype_argc = method->signature->generic_param_count;
7423         gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7424
7425         for (i = 0; i < gmethod->mtype_argc; i++) {
7426                 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7427                 MonoGenericParam *gparam = &mn->header->gen_params [i];
7428
7429                 g_assert (gparam->pklass);
7430                 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7431         }
7432
7433         context = g_new0 (MonoGenericContext, 1);
7434         context->ginst = ginst;
7435         context->gmethod = gmethod;
7436
7437         return mono_class_inflate_generic_method (method, context, ginst->klass);
7438 }
7439
7440 static MonoMethod *
7441 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7442 {
7443         MonoMethod *method;
7444         MonoClass *klass;
7445
7446         klass = mono_class_from_mono_type (type->type.type);
7447
7448         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7449                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7450         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7451                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7452         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7453                  !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7454                 method = ((MonoReflectionMethod *) obj)->method;
7455         else {
7456                 method = NULL; /* prevent compiler warning */
7457                 g_assert_not_reached ();
7458         }
7459
7460         return inflate_mono_method (type, method, obj);
7461 }
7462
7463 void
7464 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7465                                          MonoArray *methods, MonoArray *ctors,
7466                                          MonoArray *fields, MonoArray *properties,
7467                                          MonoArray *events)
7468 {
7469         MonoGenericInst *ginst;
7470         MonoDynamicGenericInst *dginst;
7471         MonoClass *klass, *gklass, *pklass;
7472         int i;
7473
7474         MONO_ARCH_SAVE_REGS;
7475
7476         klass = mono_class_from_mono_type (type->type.type);
7477         ginst = type->type.type->data.generic_inst;
7478
7479         if (ginst->initialized)
7480                 return;
7481
7482         dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7483
7484         gklass = mono_class_from_mono_type (ginst->generic_type);
7485         mono_class_init (gklass);
7486
7487         if (ginst->parent)
7488                 pklass = mono_class_from_mono_type (ginst->parent);
7489         else
7490                 pklass = gklass->parent;
7491
7492         mono_class_setup_parent (klass, pklass);
7493
7494         dginst->count_methods = methods ? mono_array_length (methods) : 0;
7495         dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7496         dginst->count_fields = fields ? mono_array_length (fields) : 0;
7497         dginst->count_properties = properties ? mono_array_length (properties) : 0;
7498         dginst->count_events = events ? mono_array_length (events) : 0;
7499
7500         dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7501         dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7502         dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7503         dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7504         dginst->events = g_new0 (MonoEvent, dginst->count_events);
7505
7506         for (i = 0; i < dginst->count_methods; i++) {
7507                 MonoObject *obj = mono_array_get (methods, gpointer, i);
7508
7509                 dginst->methods [i] = inflate_method (type, obj);
7510         }
7511
7512         for (i = 0; i < dginst->count_ctors; i++) {
7513                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7514
7515                 dginst->ctors [i] = inflate_method (type, obj);
7516         }
7517
7518         for (i = 0; i < dginst->count_fields; i++) {
7519                 MonoObject *obj = mono_array_get (fields, gpointer, i);
7520                 MonoClassField *field;
7521                 MonoInflatedField *ifield;
7522
7523                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7524                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7525                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7526                         field = ((MonoReflectionField *) obj)->field;
7527                 else {
7528                         field = NULL; /* prevent compiler warning */
7529                         g_assert_not_reached ();
7530                 }
7531
7532                 ifield = g_new0 (MonoInflatedField, 1);
7533                 ifield->generic_type = field->type;
7534                 ifield->reflection_info = obj;
7535
7536                 dginst->fields [i] = *field;
7537                 dginst->fields [i].generic_info = ifield;
7538                 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7539         }
7540
7541         for (i = 0; i < dginst->count_properties; i++) {
7542                 MonoObject *obj = mono_array_get (properties, gpointer, i);
7543                 MonoProperty *property = &dginst->properties [i];
7544
7545                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7546                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7547
7548                         property->parent = klass;
7549                         property->attrs = pb->attrs;
7550                         property->name = mono_string_to_utf8 (pb->name);
7551                         if (pb->get_method)
7552                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7553                         if (pb->set_method)
7554                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7555                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7556                         *property = *((MonoReflectionProperty *) obj)->property;
7557
7558                         if (property->get)
7559                                 property->get = inflate_mono_method (type, property->get, NULL);
7560                         if (property->set)
7561                                 property->set = inflate_mono_method (type, property->set, NULL);
7562                 } else
7563                         g_assert_not_reached ();
7564         }
7565
7566         for (i = 0; i < dginst->count_events; i++) {
7567                 MonoObject *obj = mono_array_get (events, gpointer, i);
7568                 MonoEvent *event = &dginst->events [i];
7569
7570                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7571                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7572
7573                         event->parent = klass;
7574                         event->attrs = eb->attrs;
7575                         event->name = mono_string_to_utf8 (eb->name);
7576                         if (eb->add_method)
7577                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7578                         if (eb->remove_method)
7579                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7580                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7581                         *event = *((MonoReflectionEvent *) obj)->event;
7582
7583                         if (event->add)
7584                                 event->add = inflate_mono_method (type, event->add, NULL);
7585                         if (event->remove)
7586                                 event->remove = inflate_mono_method (type, event->remove, NULL);
7587                 } else
7588                         g_assert_not_reached ();
7589         }
7590
7591         ginst->initialized = TRUE;
7592 }
7593
7594 static void
7595 ensure_runtime_vtable (MonoClass *klass)
7596 {
7597         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7598         int i, num, j, onum;
7599         MonoMethod **overrides;
7600
7601         if (!tb || klass->wastypebuilder)
7602                 return;
7603         if (klass->parent)
7604                 ensure_runtime_vtable (klass->parent);
7605
7606         num = tb->ctors? mono_array_length (tb->ctors): 0;
7607         num += tb->num_methods;
7608         klass->method.count = num;
7609         klass->methods = g_new (MonoMethod*, num);
7610         num = tb->ctors? mono_array_length (tb->ctors): 0;
7611         for (i = 0; i < num; ++i)
7612                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7613         num = tb->num_methods;
7614         j = i;
7615         for (i = 0; i < num; ++i)
7616                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7617
7618         klass->wastypebuilder = TRUE;
7619         if (tb->interfaces) {
7620                 klass->interface_count = mono_array_length (tb->interfaces);
7621                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7622                 for (i = 0; i < klass->interface_count; ++i) {
7623                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7624                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7625                 }
7626         }
7627
7628         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7629                 for (i = 0; i < klass->method.count; ++i)
7630                         klass->methods [i]->slot = i;
7631
7632         /* Overrides */
7633         onum = 0;
7634         if (tb->methods) {
7635                 for (i = 0; i < tb->num_methods; ++i) {
7636                         MonoReflectionMethodBuilder *mb = 
7637                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7638                         if (mb->override_method)
7639                                 onum ++;
7640                 }
7641         }
7642
7643         overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7644
7645         if (tb->methods) {
7646                 onum = 0;
7647                 for (i = 0; i < tb->num_methods; ++i) {
7648                         MonoReflectionMethodBuilder *mb = 
7649                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7650                         if (mb->override_method) {
7651                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7652                                 overrides [onum * 2] = 
7653                                         mb->override_method->method;
7654                                 overrides [onum * 2 + 1] =
7655                                         mb->mhandle;
7656
7657                                 g_assert (mb->mhandle);
7658
7659                                 onum ++;
7660                         }
7661                 }
7662         }
7663
7664         mono_class_setup_vtable (klass, overrides, onum);
7665 }
7666
7667 static void
7668 typebuilder_setup_fields (MonoClass *klass)
7669 {
7670         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7671         MonoReflectionFieldBuilder *fb;
7672         MonoClassField *field;
7673         const char *p, *p2;
7674         int i;
7675         guint32 len, idx;
7676
7677         klass->field.count = tb->num_fields;
7678         klass->field.first = 0;
7679         klass->field.last = klass->field.count;
7680
7681         if (!klass->field.count)
7682                 return;
7683         
7684         klass->fields = g_new0 (MonoClassField, klass->field.count);
7685
7686         for (i = 0; i < klass->field.count; ++i) {
7687                 fb = mono_array_get (tb->fields, gpointer, i);
7688                 field = &klass->fields [i];
7689                 field->name = mono_string_to_utf8 (fb->name);
7690                 if (fb->attrs) {
7691                         /* FIXME: handle type modifiers */
7692                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
7693                         field->type->attrs = fb->attrs;
7694                 } else {
7695                         field->type = fb->type->type;
7696                 }
7697                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7698                         field->data = mono_array_addr (fb->rva_data, char, 0);
7699                 if (fb->offset != -1)
7700                         field->offset = fb->offset;
7701                 field->parent = klass;
7702                 fb->handle = field;
7703                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7704
7705                 if (fb->def_value) {
7706                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7707                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7708                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
7709                         /* Copy the data from the blob since it might get realloc-ed */
7710                         p = assembly->blob.data + idx;
7711                         len = mono_metadata_decode_blob_size (p, &p2);
7712                         len += p2 - p;
7713                         field->data = g_malloc (len);
7714                         memcpy (field->data, p, len);
7715                 }
7716         }
7717         mono_class_layout_fields (klass);
7718 }
7719
7720 static void
7721 typebuilder_setup_properties (MonoClass *klass)
7722 {
7723         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7724         MonoReflectionPropertyBuilder *pb;
7725         int i;
7726
7727         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7728         klass->property.first = 0;
7729         klass->property.last = klass->property.count;
7730
7731         klass->properties = g_new0 (MonoProperty, klass->property.count);
7732         for (i = 0; i < klass->property.count; ++i) {
7733                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7734                 klass->properties [i].parent = klass;
7735                 klass->properties [i].attrs = pb->attrs;
7736                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7737                 if (pb->get_method)
7738                         klass->properties [i].get = pb->get_method->mhandle;
7739                 if (pb->set_method)
7740                         klass->properties [i].set = pb->set_method->mhandle;
7741         }
7742 }
7743
7744 MonoReflectionEvent *
7745 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7746 {
7747         MonoEvent *event = g_new0 (MonoEvent, 1);
7748         MonoClass *klass;
7749         int j;
7750
7751         klass = my_mono_class_from_mono_type (tb->type.type);
7752
7753         event->parent = klass;
7754         event->attrs = eb->attrs;
7755         event->name = mono_string_to_utf8 (eb->name);
7756         if (eb->add_method)
7757                 event->add = eb->add_method->mhandle;
7758         if (eb->remove_method)
7759                 event->remove = eb->remove_method->mhandle;
7760         if (eb->raise_method)
7761                 event->raise = eb->raise_method->mhandle;
7762
7763         if (eb->other_methods) {
7764                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7765                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7766                         MonoReflectionMethodBuilder *mb = 
7767                                 mono_array_get (eb->other_methods,
7768                                                 MonoReflectionMethodBuilder*, j);
7769                         event->other [j] = mb->mhandle;
7770                 }
7771         }
7772
7773         return mono_event_get_object (mono_object_domain (tb), klass, event);
7774 }
7775
7776 static void
7777 typebuilder_setup_events (MonoClass *klass)
7778 {
7779         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7780         MonoReflectionEventBuilder *eb;
7781         int i, j;
7782
7783         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7784         klass->event.first = 0;
7785         klass->event.last = klass->event.count;
7786
7787         klass->events = g_new0 (MonoEvent, klass->event.count);
7788         for (i = 0; i < klass->event.count; ++i) {
7789                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7790                 klass->events [i].parent = klass;
7791                 klass->events [i].attrs = eb->attrs;
7792                 klass->events [i].name = mono_string_to_utf8 (eb->name);
7793                 if (eb->add_method)
7794                         klass->events [i].add = eb->add_method->mhandle;
7795                 if (eb->remove_method)
7796                         klass->events [i].remove = eb->remove_method->mhandle;
7797                 if (eb->raise_method)
7798                         klass->events [i].raise = eb->raise_method->mhandle;
7799
7800                 if (eb->other_methods) {
7801                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7802                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7803                                 MonoReflectionMethodBuilder *mb = 
7804                                         mono_array_get (eb->other_methods,
7805                                                                         MonoReflectionMethodBuilder*, j);
7806                                 klass->events [i].other [j] = mb->mhandle;
7807                         }
7808                 }
7809         }
7810 }
7811
7812 MonoReflectionType*
7813 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7814 {
7815         MonoClass *klass;
7816         MonoReflectionType* res;
7817
7818         MONO_ARCH_SAVE_REGS;
7819
7820         klass = my_mono_class_from_mono_type (tb->type.type);
7821
7822         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7823
7824         /*
7825          * Fields to set in klass:
7826          * the various flags: delegate/unicode/contextbound etc.
7827          * nested_classes
7828          */
7829         klass->flags = tb->attrs;
7830
7831         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7832                 /* No need to fully construct the type */
7833                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7834
7835         /* enums are done right away */
7836         if (!klass->enumtype)
7837                 ensure_runtime_vtable (klass);
7838
7839         /* fields and object layout */
7840         if (klass->parent) {
7841                 if (!klass->parent->size_inited)
7842                         mono_class_init (klass->parent);
7843                 klass->instance_size += klass->parent->instance_size;
7844                 klass->class_size += klass->parent->class_size;
7845                 klass->min_align = klass->parent->min_align;
7846         } else {
7847                 klass->instance_size = sizeof (MonoObject);
7848                 klass->min_align = 1;
7849         }
7850
7851         /* FIXME: handle packing_size and instance_size */
7852         typebuilder_setup_fields (klass);
7853
7854         typebuilder_setup_properties (klass);
7855
7856         typebuilder_setup_events (klass);
7857
7858         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7859         /* with enums res == tb: need to fix that. */
7860         if (!klass->enumtype)
7861                 g_assert (res != (MonoReflectionType*)tb);
7862         return res;
7863 }
7864
7865 void
7866 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7867 {
7868         MonoGenericParam *param;
7869         MonoImage *image;
7870
7871         MONO_ARCH_SAVE_REGS;
7872
7873         param = g_new0 (MonoGenericParam, 1);
7874
7875         param->method = NULL;
7876         param->name = mono_string_to_utf8 (gparam->name);
7877         param->num = gparam->index;
7878
7879         image = &gparam->tbuilder->module->dynamic_image->image;
7880         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7881
7882         param->pklass->reflection_info = gparam;
7883
7884         gparam->type.type = g_new0 (MonoType, 1);
7885         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7886         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7887         gparam->type.type->data.generic_param = param;
7888 }
7889
7890 MonoArray *
7891 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7892 {
7893         MonoDynamicImage *assembly = sig->module->dynamic_image;
7894         guint32 na = mono_array_length (sig->arguments);
7895         guint32 buflen, i;
7896         MonoArray *result;
7897         char *buf, *p;
7898
7899         MONO_ARCH_SAVE_REGS;
7900
7901         p = buf = g_malloc (10 + na * 10);
7902
7903         mono_metadata_encode_value (0x07, p, &p);
7904         mono_metadata_encode_value (na, p, &p);
7905         for (i = 0; i < na; ++i) {
7906                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7907                 encode_reflection_type (assembly, type, p, &p);
7908         }
7909
7910         buflen = p - buf;
7911         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7912         p = mono_array_addr (result, char, 0);
7913         memcpy (p, buf, buflen);
7914         g_free (buf);
7915
7916         return result;
7917 }
7918
7919 MonoArray *
7920 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7921 {
7922         MonoDynamicImage *assembly = sig->module->dynamic_image;
7923         guint32 na = mono_array_length (sig->arguments);
7924         guint32 buflen, i;
7925         MonoArray *result;
7926         char *buf, *p;
7927
7928         MONO_ARCH_SAVE_REGS;
7929
7930         p = buf = g_malloc (10 + na * 10);
7931
7932         mono_metadata_encode_value (0x06, p, &p);
7933         for (i = 0; i < na; ++i) {
7934                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7935                 encode_reflection_type (assembly, type, p, &p);
7936         }
7937
7938         buflen = p - buf;
7939         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7940         p = mono_array_addr (result, char, 0);
7941         memcpy (p, buf, buflen);
7942         g_free (buf);
7943
7944         return result;
7945 }
7946
7947 void 
7948 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7949 {
7950         ReflectionMethodBuilder rmb;
7951         MonoMethodSignature *sig;
7952         int i;
7953
7954         sig = dynamic_method_to_signature (mb);
7955
7956         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7957
7958         /*
7959          * Resolve references.
7960          */
7961         rmb.nrefs = mb->nrefs;
7962         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7963         for (i = 0; i < mb->nrefs; ++i) {
7964                 gpointer ref = resolve_object (mb->module->image, 
7965                                                mono_array_get (mb->refs, MonoObject*, i));
7966                 if (!ref) {
7967                         g_free (rmb.refs);
7968                         mono_raise_exception (mono_get_exception_type_load (NULL));
7969                         return;
7970                 }
7971                 rmb.refs [i] = ref;
7972         }               
7973
7974         /* FIXME: class */
7975         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7976
7977         g_free (rmb.refs);
7978
7979         /* ilgen is no longer needed */
7980         mb->ilgen = NULL;
7981 }
7982
7983 /**
7984  * mono_reflection_lookup_dynamic_token:
7985  *
7986  *  Finish the Builder object pointed to by TOKEN and return the corresponding
7987  * runtime structure.
7988  */
7989 gpointer
7990 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7991 {
7992         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7993         MonoObject *obj;
7994
7995         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7996         g_assert (obj);
7997
7998         return resolve_object (image, obj);
7999 }
8000
8001 static gpointer
8002 resolve_object (MonoImage *image, MonoObject *obj)
8003 {
8004         gpointer result = NULL;
8005
8006         if (strcmp (obj->vtable->klass->name, "String") == 0) {
8007                 result = mono_string_intern ((MonoString*)obj);
8008                 g_assert (result);
8009         }
8010         else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8011                 MonoReflectionType *tb = (MonoReflectionType*)obj;
8012                 result = mono_class_from_mono_type (tb->type);
8013                 g_assert (result);
8014         }
8015         else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8016                 result = ((MonoReflectionMethod*)obj)->method;
8017                 g_assert (result);
8018         }
8019         else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8020                 result = ((MonoReflectionMethod*)obj)->method;
8021                 g_assert (result);
8022         }
8023         else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8024                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8025                 result = mb->mhandle;
8026                 if (!result) {
8027                         /* Type is not yet created */
8028                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8029
8030                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8031
8032                         /*
8033                          * Hopefully this has been filled in by calling CreateType() on the
8034                          * TypeBuilder.
8035                          */
8036                         /**
8037                          * TODO: This won't work if the application finishes another 
8038                          * TypeBuilder instance instead of this one.
8039                          */
8040                         result = mb->mhandle;
8041                 }
8042         }
8043         else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8044                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8045
8046                 result = cb->mhandle;
8047                 if (!result) {
8048                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8049
8050                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8051                         result = cb->mhandle;
8052                 }
8053         }
8054         else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8055                 result = ((MonoReflectionField*)obj)->field;
8056                 g_assert (result);
8057         }
8058         else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8059                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8060                 result = fb->handle;
8061
8062                 if (!result) {
8063                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8064
8065                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8066                         result = fb->handle;
8067                 }
8068         }
8069         else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8070                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8071                 MonoClass *klass;
8072
8073                 klass = tb->type.type->data.klass;
8074                 if (klass->wastypebuilder) {
8075                         /* Already created */
8076                         result = klass;
8077                 }
8078                 else {
8079                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8080                         result = tb->type.type->data.klass;
8081                         g_assert (result);
8082                 }
8083         }
8084         else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8085                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8086                 MonoMethodSignature *sig;
8087                 int nargs, i;
8088
8089                 if (helper->arguments)
8090                         nargs = mono_array_length (helper->arguments);
8091                 else
8092                         nargs = 0;
8093
8094                 sig = mono_metadata_signature_alloc (image, nargs);
8095                 sig->explicit_this = helper->call_conv & 64;
8096                 sig->hasthis = helper->call_conv & 32;
8097
8098                 if (helper->call_conv == 0) /* unmanaged */
8099                         sig->call_convention = helper->unmanaged_call_conv - 1;
8100                 else
8101                         if (helper->call_conv & 0x02)
8102                                 sig->call_convention = MONO_CALL_VARARG;
8103                 else
8104                         sig->call_convention = MONO_CALL_DEFAULT;
8105
8106                 sig->param_count = nargs;
8107                 /* TODO: Copy type ? */
8108                 sig->ret = helper->return_type->type;
8109                 for (i = 0; i < nargs; ++i) {
8110                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8111                         sig->params [i] = rt->type;
8112                 }
8113
8114                 result = sig;
8115         }
8116         else {
8117                 g_print (obj->vtable->klass->name);
8118                 g_assert_not_reached ();
8119         }
8120         return result;
8121 }