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