2004-04-25 Nick Drochak <ndrochak@gol.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         /* missing public key */
1386         result = g_strdup_printf ("%s, %s, Version=%d.%d.%d.%d, Culture=%s",
1387                 name, ta->aname.name,
1388                 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
1389                 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral");
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         if (strcmp ("corlib", image->assembly_name) == 0)
2032                 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
2033         else
2034                 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2035         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2036         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2037         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2038         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2039         values [MONO_ASSEMBLYREF_FLAGS] = 0;
2040         values [MONO_ASSEMBLYREF_CULTURE] = 0;
2041         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2042
2043         if (strcmp ("", image->assembly->aname.culture)) {
2044                 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2045                                 image->assembly->aname.culture);
2046         }
2047
2048         if ((pubkey = mono_image_get_public_key (image, &publen))) {
2049                 guchar pubtoken [9];
2050                 pubtoken [0] = 8;
2051                 mono_digest_get_public_token (pubtoken + 1, pubkey, publen);
2052                 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, pubtoken, 9);
2053         } else {
2054                 /* 
2055                  * We add the pubtoken from ms, so that the ms runtime can handle our binaries.
2056                  * This is currently only a problem with references to System.Xml (see bug#27706),
2057                  * but there may be other cases that makes this necessary. Note, we need to set 
2058                  * the version as well. When/if we sign our assemblies, we'd need to get our pubtoken 
2059                  * recognized by ms, yuck!
2060                  * FIXME: need to add more assembly names, as needed.
2061                  */
2062                 if (strcmp (image->assembly_name, "corlib") == 0 ||
2063                                 strcmp (image->assembly_name, "mscorlib") == 0 ||
2064                                 strcmp (image->assembly_name, "System") == 0 ||
2065                                 strcmp (image->assembly_name, "System.Runtime.Remoting") == 0 ||
2066                                 strcmp (image->assembly_name, "System.Xml") == 0 ||
2067                                 strcmp (image->assembly_name, "System.Data") == 0 ||
2068                                 strcmp (image->assembly_name, "System.Windows.Forms") == 0) {
2069                         static const guchar ptoken [9] = {8, '\xB7', '\x7A', '\x5C', '\x56', '\x19', '\x34', '\xE0', '\x89'};
2070                         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2071                         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2072                         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2073                 } else if (strcmp (image->assembly_name, "Accessibility") == 0 ||
2074                                 strcmp (image->assembly_name, "cscompmgd") == 0 ||
2075                                 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2076                                 strcmp (image->assembly_name, "Microsoft.JScript") == 0 ||
2077                                 strcmp (image->assembly_name, "Microsoft.VisualBasic") == 0 ||
2078                                 strcmp (image->assembly_name, "Microsoft.VisualBasic.Vsa") == 0 ||
2079                                 strcmp (image->assembly_name, "Microsoft.VisualC") == 0 ||
2080                                 strcmp (image->assembly_name, "Microsoft.Vsa") == 0 ||
2081                                 strcmp (image->assembly_name, "System.Configuration.Install") == 0 ||
2082                                 strcmp (image->assembly_name, "System.DirectoryServices") == 0 ||
2083                                 strcmp (image->assembly_name, "System.Design") == 0 ||
2084                                 strcmp (image->assembly_name, "System.Drawing") == 0 ||
2085                                 strcmp (image->assembly_name, "System.Drawing.Design") == 0 ||
2086                                 strcmp (image->assembly_name, "System.EnterpriseServices") == 0 ||
2087                                 strcmp (image->assembly_name, "System.Management") == 0 ||
2088                                 strcmp (image->assembly_name, "System.Messaging") == 0 ||
2089                                 strcmp (image->assembly_name, "System.Runtime.Serialization.Formatters.Soap") == 0 ||
2090                                 strcmp (image->assembly_name, "System.Security") == 0 ||
2091                                 strcmp (image->assembly_name, "System.ServiceProcess") == 0 ||
2092                                 strcmp (image->assembly_name, "System.Web.Services") == 0 ||
2093                                 strcmp (image->assembly_name, "CustomMarshalers") == 0 ||
2094                                 strcmp (image->assembly_name, "System.Web") == 0) {
2095                         static const guchar ptoken [9] = {8, '\xb0', '\x3f', '\x5f', '\x7f', '\x11', '\xd5', '\x0a', '\x3a'};
2096                         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, ptoken, 9);
2097                         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = 1;
2098                         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = 3300;
2099                 } else {
2100                         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2101                 }
2102         }
2103         token <<= RESOLTION_SCOPE_BITS;
2104         token |= RESOLTION_SCOPE_ASSEMBLYREF;
2105         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2106         return token;
2107 }
2108
2109 static guint32
2110 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2111 {
2112         MonoDynamicTable *table;
2113         guint32 *values;
2114         guint32 token;
2115         char sig [128];
2116         char *p = sig;
2117         char blob_size [6];
2118         char *b = blob_size;
2119
2120         switch (type->type) {
2121         case MONO_TYPE_FNPTR:
2122         case MONO_TYPE_PTR:
2123         case MONO_TYPE_SZARRAY:
2124         case MONO_TYPE_ARRAY:
2125         case MONO_TYPE_VAR:
2126         case MONO_TYPE_MVAR:
2127         case MONO_TYPE_GENERICINST:
2128                 encode_type (assembly, type, p, &p);
2129                 break;
2130         case MONO_TYPE_CLASS:
2131         case MONO_TYPE_VALUETYPE: {
2132                 MonoClass *k = mono_class_from_mono_type (type);
2133                 if (!k || !k->generic_inst)
2134                         return 0;
2135                 encode_generic_inst (assembly, k->generic_inst, p, &p);
2136                 break;
2137         }
2138         default:
2139                 return 0;
2140         }
2141
2142         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2143         if (assembly->save) {
2144                 g_assert (p-sig < 128);
2145                 mono_metadata_encode_value (p-sig, b, &b);
2146                 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2147                 alloc_table (table, table->rows + 1);
2148                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2149                 values [MONO_TYPESPEC_SIGNATURE] = token;
2150         }
2151
2152         token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2153         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2154         table->next_idx ++;
2155         return token;
2156 }
2157
2158 /*
2159  * Despite the name, we handle also TypeSpec (with the above helper).
2160  */
2161 static guint32
2162 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2163 {
2164         MonoDynamicTable *table;
2165         guint32 *values;
2166         guint32 token, scope, enclosing;
2167         MonoClass *klass;
2168
2169         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2170         if (token)
2171                 return token;
2172         token = create_typespec (assembly, type);
2173         if (token)
2174                 return token;
2175         klass = my_mono_class_from_mono_type (type);
2176         if (!klass)
2177                 klass = mono_class_from_mono_type (type);
2178
2179         /*
2180          * If it's in the same module and not a generic type parameter:
2181          */
2182         if ((klass->image == &assembly->image) &&
2183             (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR)) {
2184                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
2185                 token = TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
2186                 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2187                 return token;
2188         }
2189
2190         if (klass->nested_in) {
2191                 enclosing = mono_image_typedef_or_ref (assembly, &klass->nested_in->byval_arg);
2192                 /* get the typeref idx of the enclosing type */
2193                 enclosing >>= TYPEDEFORREF_BITS;
2194                 scope = (enclosing << RESOLTION_SCOPE_BITS) | RESOLTION_SCOPE_TYPEREF;
2195         } else {
2196                 scope = resolution_scope_from_image (assembly, klass->image);
2197         }
2198         table = &assembly->tables [MONO_TABLE_TYPEREF];
2199         if (assembly->save) {
2200                 alloc_table (table, table->rows + 1);
2201                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2202                 values [MONO_TYPEREF_SCOPE] = scope;
2203                 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2204                 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2205         }
2206         token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
2207         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2208         table->next_idx ++;
2209         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), klass->reflection_info);
2210         return token;
2211 }
2212
2213 /*
2214  * Insert a memberef row into the metadata: the token that point to the memberref
2215  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2216  * mono_image_get_fieldref_token()).
2217  * The sig param is an index to an already built signature.
2218  */
2219 static guint32
2220 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2221 {
2222         MonoDynamicTable *table;
2223         guint32 *values;
2224         guint32 token, pclass;
2225         guint32 parent;
2226
2227         parent = mono_image_typedef_or_ref (assembly, type);
2228         switch (parent & TYPEDEFORREF_MASK) {
2229         case TYPEDEFORREF_TYPEREF:
2230                 pclass = MEMBERREF_PARENT_TYPEREF;
2231                 break;
2232         case TYPEDEFORREF_TYPESPEC:
2233                 pclass = MEMBERREF_PARENT_TYPESPEC;
2234                 break;
2235         case TYPEDEFORREF_TYPEDEF:
2236                 pclass = MEMBERREF_PARENT_TYPEDEF;
2237                 break;
2238         default:
2239                 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2240                 return 0;
2241         }
2242         /* extract the index */
2243         parent >>= TYPEDEFORREF_BITS;
2244
2245         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2246
2247         if (assembly->save) {
2248                 alloc_table (table, table->rows + 1);
2249                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2250                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2251                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2252                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2253         }
2254
2255         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2256         table->next_idx ++;
2257
2258         return token;
2259 }
2260
2261 static guint32
2262 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method)
2263 {
2264         guint32 token;
2265         
2266         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2267         if (token)
2268                 return token;
2269         token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2270                 method->name,  method_encode_signature (assembly, method->signature));
2271         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2272         return token;
2273 }
2274
2275 static guint32
2276 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2277 {
2278         guint32 token;
2279         ReflectionMethodBuilder rmb;
2280         
2281         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2282         if (token)
2283                 return token;
2284
2285         reflection_methodbuilder_from_method_builder (&rmb, mb);
2286         
2287         token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2288                                                                                         mono_string_to_utf8 (rmb.name),
2289                                                                                         method_builder_encode_signature (assembly, &rmb));
2290         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2291         return token;
2292 }
2293
2294 static guint32
2295 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2296 {
2297         guint32 token;
2298         ReflectionMethodBuilder rmb;
2299         
2300         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, mb));
2301         if (token)
2302                 return token;
2303
2304         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2305
2306         token = mono_image_get_memberref_token (assembly, ((MonoReflectionTypeBuilder*)rmb.type)->type.type,
2307                                                                                         mono_string_to_utf8 (rmb.name),
2308                                                                                         method_builder_encode_signature (assembly, &rmb));
2309         g_hash_table_insert (assembly->handleref, mb, GUINT_TO_POINTER(token));
2310         return token;
2311 }
2312
2313 static guint32
2314 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2315 {
2316         MonoType *type;
2317         guint32 token;
2318
2319         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, f));
2320         if (token)
2321                 return token;
2322         g_assert (f->field->parent);
2323         type = f->field->generic_type ? f->field->generic_type : f->field->type;
2324         token = mono_image_get_memberref_token (assembly, &f->klass->byval_arg, 
2325                 f->field->name,  fieldref_encode_signature (assembly, type));
2326         g_hash_table_insert (assembly->handleref, f, GUINT_TO_POINTER(token));
2327         return token;
2328 }
2329
2330 static guint32
2331 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericMethod *gmethod)
2332 {
2333         char *buf;
2334         char *p;
2335         int i;
2336         guint32 nparams =  gmethod->mtype_argc;
2337         guint32 size = 10 + nparams * 10;
2338         guint32 idx;
2339         char blob_size [6];
2340         char *b = blob_size;
2341
2342         if (!assembly->save)
2343                 return 0;
2344
2345         p = buf = g_malloc (size);
2346         /*
2347          * FIXME: vararg, explicit_this, differenc call_conv values...
2348          */
2349         mono_metadata_encode_value (0xa, p, &p); /// FIXME FIXME FIXME
2350         mono_metadata_encode_value (nparams, p, &p);
2351
2352         for (i = 0; i < nparams; i++)
2353                 encode_type (assembly, gmethod->mtype_argv [i], p, &p);
2354
2355         /* store length */
2356         g_assert (p - buf < size);
2357         mono_metadata_encode_value (p-buf, b, &b);
2358         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2359         g_free (buf);
2360         return idx;
2361 }
2362
2363 static guint32
2364 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2365 {
2366         MonoDynamicTable *table;
2367         guint32 *values;
2368         guint32 token, mtoken = 0, sig;
2369         MonoMethodInflated *imethod;
2370         MonoMethod *declaring;
2371
2372         table = &assembly->tables [MONO_TABLE_METHODSPEC];
2373
2374         g_assert (method->signature->is_inflated);
2375         imethod = (MonoMethodInflated *) method;
2376         declaring = imethod->declaring;
2377
2378         sig = method_encode_signature (assembly, declaring->signature);
2379         mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2380                                                  declaring->name, sig);
2381
2382         if (!declaring->signature->generic_param_count)
2383                 return mtoken;
2384
2385         switch (mono_metadata_token_table (mtoken)) {
2386         case MONO_TABLE_MEMBERREF:
2387                 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODREF;
2388                 break;
2389         case MONO_TABLE_METHOD:
2390                 mtoken = (mono_metadata_token_index (mtoken) << METHODDEFORREF_BITS) | METHODDEFORREF_METHODDEF;
2391                 break;
2392         default:
2393                 g_assert_not_reached ();
2394         }
2395
2396         sig = encode_generic_method_sig (assembly, imethod->context->gmethod);
2397
2398         if (assembly->save) {
2399                 alloc_table (table, table->rows + 1);
2400                 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2401                 values [MONO_METHODSPEC_METHOD] = mtoken;
2402                 values [MONO_METHODSPEC_SIGNATURE] = sig;
2403         }
2404
2405         token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2406         table->next_idx ++;
2407
2408         return token;
2409 }
2410
2411 static guint32
2412 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *m)
2413 {
2414         MonoMethodInflated *imethod;
2415         guint32 token;
2416         
2417         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, m));
2418         if (token)
2419                 return token;
2420
2421         g_assert (m->signature->is_inflated);
2422         imethod = (MonoMethodInflated *) m;
2423
2424         if (imethod->declaring->signature->generic_param_count)
2425                 token = method_encode_methodspec (assembly, m);
2426         else {
2427                 guint32 sig = method_encode_signature (
2428                         assembly, imethod->declaring->signature);
2429                 token = mono_image_get_memberref_token (
2430                         assembly, &m->klass->byval_arg, m->name, sig);
2431         }
2432
2433         g_hash_table_insert (assembly->handleref, m, GUINT_TO_POINTER(token));
2434         return token;
2435 }
2436
2437 static guint32
2438 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
2439 {
2440         MonoDynamicTable *table;
2441         MonoClass *klass;
2442         guint32 *values;
2443         guint32 token;
2444         char sig [128];
2445         char *p = sig;
2446         char blob_size [6];
2447         char *b = blob_size;
2448         int count, i;
2449
2450         /*
2451          * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2452          * ie. what we'd normally use as the generic type in a TypeSpec signature.
2453          * Because of this, we must not insert it into the `typeref' hash table.
2454          */
2455
2456         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, tb->type.type));
2457         if (token)
2458                 return token;
2459
2460         g_assert (tb->generic_params);
2461         klass = mono_class_from_mono_type (tb->type.type);
2462
2463         mono_metadata_encode_value (MONO_TYPE_GENERICINST, p, &p);
2464         encode_type (assembly, &klass->byval_arg, p, &p);
2465
2466         count = mono_array_length (tb->generic_params);
2467         mono_metadata_encode_value (count, p, &p);
2468         for (i = 0; i < count; i++) {
2469                 MonoReflectionGenericParam *gparam;
2470
2471                 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
2472
2473                 encode_type (assembly, gparam->type.type, p, &p);
2474         }
2475
2476         table = &assembly->tables [MONO_TABLE_TYPESPEC];
2477         if (assembly->save) {
2478                 g_assert (p-sig < 128);
2479                 mono_metadata_encode_value (p-sig, b, &b);
2480                 token = add_to_blob_cached (assembly, blob_size, b-blob_size, sig, p-sig);
2481                 alloc_table (table, table->rows + 1);
2482                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2483                 values [MONO_TYPESPEC_SIGNATURE] = token;
2484         }
2485
2486         token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
2487         g_hash_table_insert (assembly->typespec, tb->type.type, GUINT_TO_POINTER(token));
2488         table->next_idx ++;
2489         return token;
2490 }
2491
2492 static guint32
2493 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
2494 {
2495         MonoDynamicTable *table;
2496         MonoClass *klass;
2497         guint32 *values;
2498         guint32 token, pclass, parent, sig;
2499         gchar *name;
2500
2501         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, fb));
2502         if (token)
2503                 return token;
2504
2505         klass = mono_class_from_mono_type (fb->typeb->type);
2506         name = mono_string_to_utf8 (fb->name);
2507
2508         sig = fieldref_encode_signature (assembly, fb->type->type);
2509
2510         parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
2511         g_assert ((parent & TYPEDEFORREF_MASK) == TYPEDEFORREF_TYPESPEC);
2512         
2513         pclass = MEMBERREF_PARENT_TYPESPEC;
2514         parent >>= TYPEDEFORREF_BITS;
2515
2516         table = &assembly->tables [MONO_TABLE_MEMBERREF];
2517
2518         if (assembly->save) {
2519                 alloc_table (table, table->rows + 1);
2520                 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2521                 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
2522                 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2523                 values [MONO_MEMBERREF_SIGNATURE] = sig;
2524         }
2525
2526         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2527         table->next_idx ++;
2528         g_hash_table_insert (assembly->handleref, fb, GUINT_TO_POINTER(token));
2529         return token;
2530 }
2531
2532 static guint32
2533 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2534 {
2535         char *buf;
2536         char *p;
2537         guint32 nargs;
2538         guint32 size;
2539         guint32 i, idx;
2540         char blob_size [6];
2541         char *b = blob_size;
2542
2543         if (!assembly->save)
2544                 return 0;
2545
2546         /* FIXME: */
2547         g_assert (helper->type == 2);
2548
2549         if (helper->arguments)
2550                 nargs = mono_array_length (helper->arguments);
2551         else
2552                 nargs = 0;
2553
2554         size = 10 + (nargs * 10);
2555         
2556         p = buf = g_malloc (size);
2557
2558         /* Encode calling convention */
2559         /* Change Any to Standard */
2560         if ((helper->call_conv & 0x03) == 0x03)
2561                 helper->call_conv = 0x01;
2562         /* explicit_this implies has_this */
2563         if (helper->call_conv & 0x40)
2564                 helper->call_conv &= 0x20;
2565
2566         if (helper->call_conv == 0) /* Unmanaged */
2567                 *p = helper->unmanaged_call_conv - 1;
2568         else {
2569                 /* Managed */
2570                 *p = helper->call_conv & 0x60; /* has_this + explicit_this */
2571                 if (helper->call_conv & 0x02) /* varargs */
2572                         *p += 0x05;
2573         }
2574
2575         p++;
2576         mono_metadata_encode_value (nargs, p, &p);
2577         encode_reflection_type (assembly, helper->return_type, p, &p);
2578         for (i = 0; i < nargs; ++i) {
2579                 MonoReflectionType *pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
2580                 encode_reflection_type (assembly, pt, p, &p);
2581         }
2582         /* store length */
2583         g_assert (p - buf < size);
2584         mono_metadata_encode_value (p-buf, b, &b);
2585         idx = add_to_blob_cached (assembly, blob_size, b-blob_size, buf, p-buf);
2586         g_free (buf);
2587
2588         return idx;
2589 }
2590         
2591 static guint32 
2592 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
2593 {
2594         guint32 idx;
2595         MonoDynamicTable *table;
2596         guint32 *values;
2597
2598         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
2599         idx = table->next_idx ++;
2600         table->rows ++;
2601         alloc_table (table, table->rows);
2602         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
2603
2604         values [MONO_STAND_ALONE_SIGNATURE] =
2605                 mono_reflection_encode_sighelper (assembly, helper);
2606
2607         return idx;
2608 }
2609
2610 static int
2611 reflection_cc_to_file (int call_conv) {
2612         switch (call_conv & 0x3) {
2613         case 0:
2614         case 1: return MONO_CALL_DEFAULT;
2615         case 2: return MONO_CALL_VARARG;
2616         default:
2617                 g_assert_not_reached ();
2618         }
2619         return 0;
2620 }
2621
2622 typedef struct {
2623         MonoType *parent;
2624         MonoMethodSignature *sig;
2625         char *name;
2626         guint32 token;
2627 } ArrayMethod;
2628
2629 static guint32
2630 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
2631 {
2632         guint32 nparams, i;
2633         GList *tmp;
2634         char *name;
2635         MonoMethodSignature *sig;
2636         ArrayMethod *am;
2637         
2638         name = mono_string_to_utf8 (m->name);
2639         nparams = mono_array_length (m->parameters);
2640         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * nparams);
2641         sig->hasthis = 1;
2642         sig->call_convention = reflection_cc_to_file (m->call_conv);
2643         sig->param_count = nparams;
2644         sig->ret = m->ret? m->ret->type: &mono_defaults.void_class->byval_arg;
2645         for (i = 0; i < nparams; ++i) {
2646                 MonoReflectionType *t = mono_array_get (m->parameters, gpointer, i);
2647                 sig->params [i] = t->type;
2648         }
2649
2650         for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
2651                 am = tmp->data;
2652                 if (strcmp (name, am->name) == 0 && 
2653                                 mono_metadata_type_equal (am->parent, m->parent->type) &&
2654                                 mono_metadata_signature_equal (am->sig, sig)) {
2655                         g_free (name);
2656                         g_free (sig);
2657                         m->table_idx = am->token & 0xffffff;
2658                         return am->token;
2659                 }
2660         }
2661         am = g_new0 (ArrayMethod, 1);
2662         am->name = name;
2663         am->sig = sig;
2664         am->parent = m->parent->type;
2665         am->token = mono_image_get_memberref_token (assembly, am->parent,
2666                         name,  method_encode_signature (assembly, sig));
2667         assembly->array_methods = g_list_prepend (assembly->array_methods, am);
2668         m->table_idx = am->token & 0xffffff;
2669         return am->token;
2670 }
2671
2672 /*
2673  * Insert into the metadata tables all the info about the TypeBuilder tb.
2674  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
2675  */
2676 static void
2677 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
2678 {
2679         MonoDynamicTable *table;
2680         guint *values;
2681         int i, is_object = 0, is_system = 0;
2682         char *n;
2683
2684         table = &assembly->tables [MONO_TABLE_TYPEDEF];
2685         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
2686         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
2687         n = mono_string_to_utf8 (tb->name);
2688         if (strcmp (n, "Object") == 0)
2689                 is_object++;
2690         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
2691         g_free (n);
2692         n = mono_string_to_utf8 (tb->nspace);
2693         if (strcmp (n, "System") == 0)
2694                 is_system++;
2695         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
2696         g_free (n);
2697         if (tb->parent && !(is_system && is_object) && 
2698                 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
2699                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
2700         } else
2701                 values [MONO_TYPEDEF_EXTENDS] = 0;
2702         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
2703         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
2704
2705         /*
2706          * if we have explicitlayout or sequentiallayouts, output data in the
2707          * ClassLayout table.
2708          */
2709         if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) && (tb->class_size != -1)) {
2710                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
2711                 table->rows++;
2712                 alloc_table (table, table->rows);
2713                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
2714                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
2715                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
2716                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
2717         }
2718
2719         /* handle interfaces */
2720         if (tb->interfaces) {
2721                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
2722                 i = table->rows;
2723                 table->rows += mono_array_length (tb->interfaces);
2724                 alloc_table (table, table->rows);
2725                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
2726                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
2727                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
2728                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
2729                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
2730                         values += MONO_INTERFACEIMPL_SIZE;
2731                 }
2732         }
2733
2734         /* handle generic parameters */
2735         if (tb->generic_params) {
2736                 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2737                 table->rows += mono_array_length (tb->generic_params);
2738                 alloc_table (table, table->rows);
2739                 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
2740                         guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
2741
2742                         mono_image_get_generic_param_info (
2743                                 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
2744                 }
2745         }
2746
2747         /* handle fields */
2748         if (tb->fields) {
2749                 table = &assembly->tables [MONO_TABLE_FIELD];
2750                 table->rows += tb->num_fields;
2751                 alloc_table (table, table->rows);
2752                 for (i = 0; i < tb->num_fields; ++i)
2753                         mono_image_get_field_info (
2754                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
2755         }
2756
2757         /* handle constructors */
2758         if (tb->ctors) {
2759                 table = &assembly->tables [MONO_TABLE_METHOD];
2760                 table->rows += mono_array_length (tb->ctors);
2761                 alloc_table (table, table->rows);
2762                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
2763                         mono_image_get_ctor_info (domain,
2764                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
2765         }
2766
2767         /* handle methods */
2768         if (tb->methods) {
2769                 table = &assembly->tables [MONO_TABLE_METHOD];
2770                 table->rows += tb->num_methods;
2771                 alloc_table (table, table->rows);
2772                 for (i = 0; i < tb->num_methods; ++i)
2773                         mono_image_get_method_info (
2774                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
2775         }
2776
2777         /* Do the same with properties etc.. */
2778         if (tb->events && mono_array_length (tb->events)) {
2779                 table = &assembly->tables [MONO_TABLE_EVENT];
2780                 table->rows += mono_array_length (tb->events);
2781                 alloc_table (table, table->rows);
2782                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
2783                 table->rows ++;
2784                 alloc_table (table, table->rows);
2785                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
2786                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
2787                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
2788                 for (i = 0; i < mono_array_length (tb->events); ++i)
2789                         mono_image_get_event_info (
2790                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
2791         }
2792         if (tb->properties && mono_array_length (tb->properties)) {
2793                 table = &assembly->tables [MONO_TABLE_PROPERTY];
2794                 table->rows += mono_array_length (tb->properties);
2795                 alloc_table (table, table->rows);
2796                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
2797                 table->rows ++;
2798                 alloc_table (table, table->rows);
2799                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
2800                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
2801                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
2802                 for (i = 0; i < mono_array_length (tb->properties); ++i)
2803                         mono_image_get_property_info (
2804                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
2805         }
2806
2807         mono_image_add_decl_security (assembly, 
2808                                                                   mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx),
2809                                                                   tb->permissions);
2810
2811         if (tb->subtypes) {
2812                 MonoDynamicTable *ntable;
2813                 
2814                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
2815                 ntable->rows += mono_array_length (tb->subtypes);
2816                 alloc_table (ntable, ntable->rows);
2817                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
2818
2819                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
2820                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
2821
2822                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
2823                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
2824                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
2825                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
2826                                 mono_string_to_utf8 (tb->name), tb->table_idx,
2827                                 ntable->next_idx, ntable->rows);*/
2828                         values += MONO_NESTED_CLASS_SIZE;
2829                         ntable->next_idx++;
2830                 }
2831         }
2832 }
2833
2834 static void
2835 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
2836 {
2837         int i;
2838
2839         g_ptr_array_add (types, type);
2840
2841         if (!type->subtypes)
2842                 return;
2843
2844         for (i = 0; i < mono_array_length (type->subtypes); ++i) {
2845                 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
2846                 collect_types (types, subtype);
2847         }
2848 }
2849
2850 static gint
2851 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, 
2852                                                         MonoReflectionTypeBuilder **type2)
2853 {
2854         if ((*type1)->table_idx < (*type2)->table_idx)
2855                 return -1;
2856         else
2857                 if ((*type1)->table_idx > (*type2)->table_idx)
2858                         return 1;
2859         else
2860                 return 0;
2861 }
2862
2863 static void
2864 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
2865         int i;
2866
2867         if (!pinfo)
2868                 return;
2869         for (i = 0; i < mono_array_length (pinfo); ++i) {
2870                 MonoReflectionParamBuilder *pb;
2871                 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
2872                 if (!pb)
2873                         continue;
2874                 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
2875         }
2876 }
2877
2878 static void
2879 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
2880         int i;
2881         
2882         mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
2883         if (tb->fields) {
2884                 for (i = 0; i < tb->num_fields; ++i) {
2885                         MonoReflectionFieldBuilder* fb;
2886                         fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
2887                         mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
2888                 }
2889         }
2890         if (tb->events) {
2891                 for (i = 0; i < mono_array_length (tb->events); ++i) {
2892                         MonoReflectionEventBuilder* eb;
2893                         eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
2894                         mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
2895                 }
2896         }
2897         if (tb->properties) {
2898                 for (i = 0; i < mono_array_length (tb->properties); ++i) {
2899                         MonoReflectionPropertyBuilder* pb;
2900                         pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
2901                         mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
2902                 }
2903         }
2904         if (tb->ctors) {
2905                 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
2906                         MonoReflectionCtorBuilder* cb;
2907                         cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
2908                         mono_image_add_cattrs (assembly, cb->table_idx, CUSTOM_ATTR_METHODDEF, cb->cattrs);
2909                         params_add_cattrs (assembly, cb->pinfo);
2910                 }
2911         }
2912
2913         if (tb->methods) {
2914                 for (i = 0; i < tb->num_methods; ++i) {
2915                         MonoReflectionMethodBuilder* mb;
2916                         mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
2917                         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
2918                         params_add_cattrs (assembly, mb->pinfo);
2919                 }
2920         }
2921
2922         if (tb->subtypes) {
2923                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
2924                         type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
2925         }
2926 }
2927
2928 static void
2929 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *mb) {
2930         int i;
2931         
2932         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
2933         
2934         /* no types in the module */
2935         if (!mb->types)
2936                 return;
2937         
2938         for (i = 0; i < mb->num_types; ++i)
2939                 type_add_cattrs (assembly, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i));
2940 }
2941
2942 static void
2943 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module,
2944                                                         MonoDynamicImage *assembly)
2945 {
2946         MonoDynamicTable *table;
2947         guint32 *values;
2948         char blob_size [6];
2949         guchar hash [20];
2950         char *b = blob_size;
2951         char *dir, *path;
2952
2953         table = &assembly->tables [MONO_TABLE_FILE];
2954         table->rows++;
2955         alloc_table (table, table->rows);
2956         values = table->values + table->next_idx * MONO_FILE_SIZE;
2957         values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
2958         values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
2959         if (module->image->dynamic) {
2960                 /* This depends on the fact that the main module is emitted last */
2961                 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
2962                 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
2963         }
2964         else {
2965                 dir = NULL;
2966                 path = g_strdup (module->image->name);
2967         }
2968         mono_sha1_get_digest_from_file (path, hash);
2969         g_free (dir);
2970         g_free (path);
2971         mono_metadata_encode_value (20, b, &b);
2972         values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
2973         mono_image_add_stream_data (&assembly->blob, hash, 20);
2974         table->next_idx ++;
2975 }
2976
2977 static void
2978 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
2979 {
2980         MonoDynamicTable *table;
2981         int i;
2982         char *name;
2983
2984         table = &assembly->tables [MONO_TABLE_MODULE];
2985         mb->table_idx = table->next_idx ++;
2986         name = mono_string_to_utf8 (mb->module.name);
2987         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
2988         g_free (name);
2989         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
2990         i /= 16;
2991         ++i;
2992         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
2993         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
2994         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
2995 }
2996
2997 static guint32
2998 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
2999                                                                                  guint32 module_index, guint32 parent_index, 
3000                                                                                  MonoDynamicImage *assembly)
3001 {
3002         MonoDynamicTable *table;
3003         guint32 *values;
3004         guint32 visib, res;
3005
3006         visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3007         if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3008                 return 0;
3009
3010         table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3011         table->rows++;
3012         alloc_table (table, table->rows);
3013         values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3014
3015         values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3016         values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3017         if (klass->nested_in)
3018                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_EXP_TYPE;
3019         else
3020                 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << IMPLEMENTATION_BITS) + IMPLEMENTATION_FILE;
3021         values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3022         values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3023
3024         res = table->next_idx;
3025
3026         table->next_idx ++;
3027
3028         /* Emit nested types */
3029         if (klass->nested_classes) {
3030                 GList *tmp;
3031
3032                 for (tmp = klass->nested_classes; tmp; tmp = tmp->next)
3033                         mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3034         }
3035
3036         return res;
3037 }
3038
3039 static void
3040 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3041                                                           guint32 module_index, guint32 parent_index, 
3042                                                           MonoDynamicImage *assembly)
3043 {
3044         MonoClass *klass;
3045         guint32 idx, i;
3046
3047         klass = mono_class_from_mono_type (tb->type.type);
3048
3049         klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3050
3051         idx = mono_image_fill_export_table_from_class (domain, klass, module_index, 
3052                                                                                                    parent_index, assembly);
3053
3054         /* 
3055          * Emit nested types
3056          * We need to do this ourselves since klass->nested_classes is not set up.
3057          */
3058         if (tb->subtypes) {
3059                 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3060                         mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3061         }
3062 }
3063
3064 static void
3065 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3066                                                                                   guint32 module_index,
3067                                                                                   MonoDynamicImage *assembly)
3068 {
3069         MonoImage *image = module->image;
3070         MonoTableInfo  *t;
3071         guint32 i;
3072
3073         t = &image->tables [MONO_TABLE_TYPEDEF];
3074
3075         for (i = 0; i < t->rows; ++i) {
3076                 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3077
3078                 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3079                         mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3080         }
3081 }
3082
3083 #define align_pointer(base,p)\
3084         do {\
3085                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3086                 if (__diff & 3)\
3087                         (p) += 4 - (__diff & 3);\
3088         } while (0)
3089
3090 static int
3091 compare_semantics (const void *a, const void *b)
3092 {
3093         const guint32 *a_values = a;
3094         const guint32 *b_values = b;
3095         int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3096         if (assoc)
3097                 return assoc;
3098         return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3099 }
3100
3101 static int
3102 compare_custom_attrs (const void *a, const void *b)
3103 {
3104         const guint32 *a_values = a;
3105         const guint32 *b_values = b;
3106
3107         return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3108 }
3109
3110 static int
3111 compare_field_marshal (const void *a, const void *b)
3112 {
3113         const guint32 *a_values = a;
3114         const guint32 *b_values = b;
3115
3116         return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3117 }
3118
3119 static int
3120 compare_nested (const void *a, const void *b)
3121 {
3122         const guint32 *a_values = a;
3123         const guint32 *b_values = b;
3124
3125         return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3126 }
3127
3128 /*
3129  * build_compressed_metadata() fills in the blob of data that represents the 
3130  * raw metadata as it will be saved in the PE file. The five streams are output 
3131  * and the metadata tables are comnpressed from the guint32 array representation, 
3132  * to the compressed on-disk format.
3133  */
3134 static void
3135 build_compressed_metadata (MonoDynamicImage *assembly)
3136 {
3137         MonoDynamicTable *table;
3138         int i;
3139         guint64 valid_mask = 0;
3140         guint64 sorted_mask;
3141         guint32 heapt_size = 0;
3142         guint32 meta_size = 256; /* allow for header and other stuff */
3143         guint32 table_offset;
3144         guint32 ntables = 0;
3145         guint64 *int64val;
3146         guint32 *int32val;
3147         guint16 *int16val;
3148         MonoImage *meta;
3149         unsigned char *p;
3150
3151         struct StreamDesc {
3152                 const char *name;
3153                 MonoDynamicStream *stream;
3154         } stream_desc [5];
3155
3156         stream_desc[0].name  = "#~"; stream_desc[0].stream = &assembly->tstream;
3157         stream_desc[1].name  = "#Strings"; stream_desc[1].stream = &assembly->sheap;
3158         stream_desc[2].name  = "#US"; stream_desc[2].stream = &assembly->us;
3159         stream_desc[3].name  = "#Blob"; stream_desc[3].stream = &assembly->blob;
3160         stream_desc[4].name  = "#GUID"; stream_desc[4].stream = &assembly->guid;
3161         
3162         /* tables that are sorted */
3163         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3164                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3165                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3166                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3167                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3168                 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
3169         
3170         /* Compute table sizes */
3171         /* the MonoImage has already been created in mono_image_basic_init() */
3172         meta = &assembly->image;
3173         
3174         /* Setup the info used by compute_sizes () */
3175         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3176         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3177         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3178
3179         meta_size += assembly->blob.index;
3180         meta_size += assembly->guid.index;
3181         meta_size += assembly->sheap.index;
3182         meta_size += assembly->us.index;
3183
3184         for (i=0; i < 64; ++i)
3185                 meta->tables [i].rows = assembly->tables [i].rows;
3186         
3187         for (i = 0; i < 64; i++){
3188                 if (meta->tables [i].rows == 0)
3189                         continue;
3190                 valid_mask |= (guint64)1 << i;
3191                 ntables ++;
3192                 meta->tables [i].row_size = mono_metadata_compute_size (
3193                         meta, i, &meta->tables [i].size_bitfield);
3194                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
3195         }
3196         heapt_size += 24; /* #~ header size */
3197         heapt_size += ntables * 4;
3198         meta_size += heapt_size;
3199         meta->raw_metadata = g_malloc0 (meta_size);
3200         p = meta->raw_metadata;
3201         /* the metadata signature */
3202         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
3203         /* version numbers and 4 bytes reserved */
3204         int16val = (guint16*)p;
3205         *int16val++ = GUINT16_TO_LE (1);
3206         *int16val = GUINT16_TO_LE (1);
3207         p += 8;
3208         /* version string */
3209         int32val = (guint32*)p;
3210         *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
3211         p += 4;
3212         memcpy (p, meta->version, GUINT32_FROM_LE (*int32val));
3213         p += GUINT32_FROM_LE (*int32val);
3214         align_pointer (meta->raw_metadata, p);
3215         int16val = (guint16*)p;
3216         *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
3217         *int16val = GUINT16_TO_LE (5); /* number of streams */
3218         p += 4;
3219
3220         /*
3221          * write the stream info.
3222          */
3223         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
3224         table_offset += 3; table_offset &= ~3;
3225
3226         assembly->tstream.index = heapt_size;
3227         for (i = 0; i < 5; ++i) {
3228                 int32val = (guint32*)p;
3229                 stream_desc [i].stream->offset = table_offset;
3230                 *int32val++ = GUINT32_TO_LE (table_offset);
3231                 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
3232                 table_offset += GUINT32_FROM_LE (*int32val);
3233                 table_offset += 3; table_offset &= ~3;
3234                 p += 8;
3235                 strcpy (p, stream_desc [i].name);
3236                 p += strlen (stream_desc [i].name) + 1;
3237                 align_pointer (meta->raw_metadata, p);
3238         }
3239         /* 
3240          * now copy the data, the table stream header and contents goes first.
3241          */
3242         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
3243         p = meta->raw_metadata + assembly->tstream.offset;
3244         int32val = (guint32*)p;
3245         *int32val = GUINT32_TO_LE (0); /* reserved */
3246         p += 4;
3247
3248         if ((assembly->tables [MONO_TABLE_GENERICPARAM].rows > 0) ||
3249             (assembly->tables [MONO_TABLE_METHODSPEC].rows > 0) ||
3250             (assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT].rows > 0)) {
3251                 *p++ = 1; /* version */
3252                 *p++ = 1;
3253         } else {
3254                 *p++ = 1; /* version */
3255                 *p++ = 0;
3256         }
3257
3258         if (meta->idx_string_wide)
3259                 *p |= 0x01;
3260         if (meta->idx_guid_wide)
3261                 *p |= 0x02;
3262         if (meta->idx_blob_wide)
3263                 *p |= 0x04;
3264         ++p;
3265         *p++ = 0; /* reserved */
3266         int64val = (guint64*)p;
3267         *int64val++ = GUINT64_TO_LE (valid_mask);
3268         *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables  */
3269         p += 16;
3270         int32val = (guint32*)p;
3271         for (i = 0; i < 64; i++){
3272                 if (meta->tables [i].rows == 0)
3273                         continue;
3274                 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
3275         }
3276         p = (unsigned char*)int32val;
3277
3278         /* sort the tables that still need sorting */
3279         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
3280         if (table->rows)
3281                 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
3282         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3283         if (table->rows)
3284                 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
3285         table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
3286         if (table->rows)
3287                 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
3288         table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3289         if (table->rows)
3290                 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
3291
3292         /* compress the tables */
3293         for (i = 0; i < 64; i++){
3294                 int row, col;
3295                 guint32 *values;
3296                 guint32 bitfield = meta->tables [i].size_bitfield;
3297                 if (!meta->tables [i].rows)
3298                         continue;
3299                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
3300                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
3301                 meta->tables [i].base = p;
3302                 for (row = 1; row <= meta->tables [i].rows; ++row) {
3303                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
3304                         for (col = 0; col < assembly->tables [i].columns; ++col) {
3305                                 switch (mono_metadata_table_size (bitfield, col)) {
3306                                 case 1:
3307                                         *p++ = values [col];
3308                                         break;
3309                                 case 2:
3310                                         *p++ = values [col] & 0xff;
3311                                         *p++ = (values [col] >> 8) & 0xff;
3312                                         break;
3313                                 case 4:
3314                                         *p++ = values [col] & 0xff;
3315                                         *p++ = (values [col] >> 8) & 0xff;
3316                                         *p++ = (values [col] >> 16) & 0xff;
3317                                         *p++ = (values [col] >> 24) & 0xff;
3318                                         break;
3319                                 default:
3320                                         g_assert_not_reached ();
3321                                 }
3322                         }
3323                 }
3324                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
3325         }
3326         
3327         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
3328         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
3329         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
3330         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
3331         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
3332
3333         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
3334 }
3335
3336 /*
3337  * Some tables in metadata need to be sorted according to some criteria, but
3338  * when methods and fields are first created with reflection, they may be assigned a token
3339  * that doesn't correspond to the final token they will get assigned after the sorting.
3340  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3341  * with the reflection objects that represent them. Once all the tables are set up, the 
3342  * reflection objects will contains the correct table index. fixup_method() will fixup the
3343  * tokens for the method with ILGenerator @ilgen.
3344  */
3345 static void
3346 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly) {
3347         guint32 code_idx = GPOINTER_TO_UINT (value);
3348         MonoReflectionILTokenInfo *iltoken;
3349         MonoReflectionFieldBuilder *field;
3350         MonoReflectionCtorBuilder *ctor;
3351         MonoReflectionMethodBuilder *method;
3352         MonoReflectionTypeBuilder *tb;
3353         MonoReflectionArrayMethod *am;
3354         guint32 i, idx = 0;
3355         unsigned char *target;
3356
3357         for (i = 0; i < ilgen->num_token_fixups; ++i) {
3358                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
3359                 target = assembly->code.data + code_idx + iltoken->code_pos;
3360                 switch (target [3]) {
3361                 case MONO_TABLE_FIELD:
3362                         if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3363                                 field = (MonoReflectionFieldBuilder *)iltoken->member;
3364                                 idx = field->table_idx;
3365                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3366                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3367                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->field_to_table_idx, f));
3368                         } else {
3369                                 g_assert_not_reached ();
3370                         }
3371                         break;
3372                 case MONO_TABLE_METHOD:
3373                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
3374                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
3375                                 idx = method->table_idx;
3376                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
3377                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
3378                                 idx = ctor->table_idx;
3379                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") || 
3380                                            !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3381                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3382                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3383                         } else {
3384                                 g_assert_not_reached ();
3385                         }
3386                         break;
3387                 case MONO_TABLE_TYPEDEF:
3388                         if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
3389                                 g_assert_not_reached ();
3390                         tb = (MonoReflectionTypeBuilder *)iltoken->member;
3391                         idx = tb->table_idx;
3392                         break;
3393                 case MONO_TABLE_MEMBERREF:
3394                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
3395                                 am = (MonoReflectionArrayMethod*)iltoken->member;
3396                                 idx = am->table_idx;
3397                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
3398                                    !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
3399                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3400                                 g_assert (m->klass->generic_inst);
3401                                 continue;
3402                         } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
3403                                 continue;
3404                         } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
3405                                 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
3406                                 g_assert (f->generic_type);
3407                                 continue;
3408                         } else {
3409                                 g_assert_not_reached ();
3410                         }
3411                         break;
3412                 case MONO_TABLE_METHODSPEC:
3413                         if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod")) {
3414                                 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
3415                                 g_assert (m->signature->generic_param_count);
3416                                 continue;
3417                         } else {
3418                                 g_assert_not_reached ();
3419                         }
3420                         break;
3421                 default:
3422                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
3423                 }
3424                 target [0] = idx & 0xff;
3425                 target [1] = (idx >> 8) & 0xff;
3426                 target [2] = (idx >> 16) & 0xff;
3427         }
3428 }
3429
3430 /*
3431  * fixup_cattrs:
3432  *
3433  *   The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
3434  * value is not known when the table is emitted.
3435  */
3436 static void
3437 fixup_cattrs (MonoDynamicImage *assembly)
3438 {
3439         MonoDynamicTable *table;
3440         guint32 *values;
3441         guint32 type, i, idx, token;
3442         MonoObject *ctor;
3443
3444         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
3445
3446         for (i = 0; i < table->rows; ++i) {
3447                 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
3448
3449                 type = values [MONO_CUSTOM_ATTR_TYPE];
3450                 if ((type & CUSTOM_ATTR_TYPE_MASK) == CUSTOM_ATTR_TYPE_METHODDEF) {
3451                         idx = type >> CUSTOM_ATTR_TYPE_BITS;
3452                         token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
3453                         ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
3454                         g_assert (ctor);
3455
3456                         if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
3457                                 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
3458                                 idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, m));
3459                                 values [MONO_CUSTOM_ATTR_TYPE] = (idx << CUSTOM_ATTR_TYPE_BITS) | CUSTOM_ATTR_TYPE_METHODDEF;
3460                         }
3461                 }
3462         }
3463 }
3464
3465 static void
3466 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
3467 {
3468         MonoDynamicTable *table;
3469         guint32 *values;
3470         char *name;
3471
3472         table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
3473         table->rows++;
3474         alloc_table (table, table->rows);
3475         values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
3476         values [MONO_MANIFEST_OFFSET] = rsrc->offset;
3477         values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
3478         name = mono_string_to_utf8 (rsrc->name);
3479         values [MONO_MANIFEST_NAME] = string_heap_insert (&assembly->sheap, name);
3480         g_free (name);
3481         values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
3482         table->next_idx++;
3483 }
3484
3485 static void
3486 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
3487 {
3488         MonoDynamicTable *table;
3489         guint32 *values;
3490         char blob_size [6];
3491         guchar hash [20];
3492         char *b = blob_size;
3493         char *name, *sname;
3494         guint32 idx, offset;
3495
3496         if (rsrc->filename) {
3497                 name = mono_string_to_utf8 (rsrc->filename);
3498                 sname = g_path_get_basename (name);
3499         
3500                 table = &assembly->tables [MONO_TABLE_FILE];
3501                 table->rows++;
3502                 alloc_table (table, table->rows);
3503                 values = table->values + table->next_idx * MONO_FILE_SIZE;
3504                 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
3505                 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
3506                 g_free (sname);
3507
3508                 mono_sha1_get_digest_from_file (name, hash);
3509                 mono_metadata_encode_value (20, b, &b);
3510                 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3511                 mono_image_add_stream_data (&assembly->blob, hash, 20);
3512                 g_free (name);
3513                 idx = table->next_idx++;
3514                 rsrc->offset = 0;
3515                 idx = IMPLEMENTATION_FILE | (idx << IMPLEMENTATION_BITS);
3516         } else {
3517                 char sizebuf [4];
3518                 offset = mono_array_length (rsrc->data);
3519                 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
3520                 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
3521                 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
3522                 mono_image_add_stream_data (&assembly->resources, mono_array_addr (rsrc->data, char, 0), mono_array_length (rsrc->data));
3523
3524                 if (!mb->is_main)
3525                         /* 
3526                          * The entry should be emitted into the MANIFESTRESOURCE table of 
3527                          * the main module, but that needs to reference the FILE table
3528                          * which isn't emitted yet.
3529                          */
3530                         return;
3531                 else
3532                         idx = 0;
3533         }
3534
3535         assembly_add_resource_manifest (mb, assembly, rsrc, idx);
3536 }
3537
3538 static void
3539 set_version_from_string (MonoString *version, guint32 *values)
3540 {
3541         gchar *ver, *p, *str;
3542         guint32 i;
3543         
3544         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
3545         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
3546         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
3547         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
3548         if (!version)
3549                 return;
3550         ver = str = mono_string_to_utf8 (version);
3551         for (i = 0; i < 4; ++i) {
3552                 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
3553                 switch (*p) {
3554                 case '.':
3555                         p++;
3556                         break;
3557                 case '*':
3558                         /* handle Revision and Build */
3559                         p++;
3560                         break;
3561                 }
3562                 ver = p;
3563         }
3564         g_free (str);
3565 }
3566
3567 static guint32
3568 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
3569         gsize len;
3570         guint32 token = 0;
3571         char blob_size [6];
3572         char *b = blob_size;
3573
3574         if (!pkey)
3575                 return token;
3576
3577         len = mono_array_length (pkey);
3578         mono_metadata_encode_value (len, b, &b);
3579         token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
3580         mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, guint8, 0), len);
3581
3582         /* need to get the actual value from the key type... */
3583         assembly->strong_name_size = 128;
3584         assembly->strong_name = g_malloc0 (assembly->strong_name_size);
3585
3586         return token;
3587 }
3588
3589 static void
3590 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
3591 {
3592         MonoDynamicTable *table;
3593         MonoDynamicImage *assembly;
3594         MonoReflectionAssemblyBuilder *assemblyb;
3595         MonoDomain *domain;
3596         guint32 *values;
3597         char *name;
3598         int i;
3599         guint32 module_index;
3600
3601         assemblyb = moduleb->assemblyb;
3602         assembly = moduleb->dynamic_image;
3603         domain = mono_object_domain (assemblyb);
3604
3605         /* Emit ASSEMBLY table */
3606         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
3607         alloc_table (table, 1);
3608         values = table->values + MONO_ASSEMBLY_SIZE;
3609         values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
3610         name = mono_string_to_utf8 (assemblyb->name);
3611         values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
3612         g_free (name);
3613         if (assemblyb->culture) {
3614                 name = mono_string_to_utf8 (assemblyb->culture);
3615                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, name);
3616                 g_free (name);
3617         } else {
3618                 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
3619         }
3620         values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
3621         values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
3622         set_version_from_string (assemblyb->version, values);
3623
3624         /* Emit FILE + EXPORTED_TYPE table */
3625         module_index = 0;
3626         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3627                 int j;
3628                 MonoReflectionModuleBuilder *file_module = 
3629                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3630                 if (file_module != moduleb) {
3631                         mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
3632                         module_index ++;
3633                         if (file_module->types) {
3634                                 for (j = 0; j < file_module->num_types; ++j) {
3635                                         MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
3636                                         mono_image_fill_export_table (domain, tb, module_index, 0,
3637                                                                                                   assembly);
3638                                 }
3639                         }
3640                 }
3641         }
3642         if (assemblyb->loaded_modules) {
3643                 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
3644                         MonoReflectionModule *file_module = 
3645                                 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
3646                         mono_image_fill_file_table (domain, file_module, assembly);
3647                         module_index ++;
3648                         mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
3649                 }
3650         }
3651
3652         /* Emit MANIFESTRESOURCE table */
3653         module_index = 0;
3654         for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
3655                 int j;
3656                 MonoReflectionModuleBuilder *file_module = 
3657                         mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
3658                 /* The table for the main module is emitted later */
3659                 if (file_module != moduleb) {
3660                         module_index ++;
3661                         if (file_module->resources) {
3662                                 int len = mono_array_length (file_module->resources);
3663                                 for (j = 0; j < len; ++j) {
3664                                         MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
3665                                         assembly_add_resource_manifest (file_module, assembly, res, IMPLEMENTATION_FILE | (module_index << IMPLEMENTATION_BITS));
3666                                 }
3667                         }
3668                 }
3669         }               
3670 }
3671
3672 /*
3673  * mono_image_build_metadata() will fill the info in all the needed metadata tables
3674  * for the modulebuilder @moduleb.
3675  * At the end of the process, method and field tokens are fixed up and the 
3676  * on-disk compressed metadata representation is created.
3677  */
3678 void
3679 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
3680 {
3681         MonoDynamicTable *table;
3682         MonoDynamicImage *assembly;
3683         MonoReflectionAssemblyBuilder *assemblyb;
3684         MonoDomain *domain;
3685         guint32 *values;
3686         int i;
3687
3688         assemblyb = moduleb->assemblyb;
3689         assembly = moduleb->dynamic_image;
3690         domain = mono_object_domain (assemblyb);
3691
3692         if (assembly->text_rva)
3693                 return;
3694
3695         assembly->text_rva = START_TEXT_RVA;
3696
3697         if (moduleb->is_main) {
3698                 mono_image_emit_manifest (moduleb);
3699         }
3700
3701         table = &assembly->tables [MONO_TABLE_TYPEDEF];
3702         table->rows = 1; /* .<Module> */
3703         table->next_idx++;
3704         alloc_table (table, table->rows);
3705         /*
3706          * Set the first entry.
3707          */
3708         values = table->values + table->columns;
3709         values [MONO_TYPEDEF_FLAGS] = 0;
3710         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
3711         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
3712         values [MONO_TYPEDEF_EXTENDS] = 0;
3713         values [MONO_TYPEDEF_FIELD_LIST] = 1;
3714         values [MONO_TYPEDEF_METHOD_LIST] = 1;
3715
3716         /* 
3717          * handle global methods 
3718          * FIXME: test what to do when global methods are defined in multiple modules.
3719          */
3720         if (moduleb->global_methods) {
3721                 table = &assembly->tables [MONO_TABLE_METHOD];
3722                 table->rows += mono_array_length (moduleb->global_methods);
3723                 alloc_table (table, table->rows);
3724                 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
3725                         mono_image_get_method_info (
3726                                                                                 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
3727         }
3728         if (moduleb->global_fields) {
3729                 table = &assembly->tables [MONO_TABLE_FIELD];
3730                 table->rows += mono_array_length (moduleb->global_fields);
3731                 alloc_table (table, table->rows);
3732                 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
3733                         mono_image_get_field_info (
3734                                                                            mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
3735         }
3736
3737         table = &assembly->tables [MONO_TABLE_MODULE];
3738         alloc_table (table, 1);
3739         mono_image_fill_module_table (domain, moduleb, assembly);
3740
3741         /* Emit types */
3742         {
3743                 /* Collect all types into a list sorted by their table_idx */
3744                 GPtrArray *types = g_ptr_array_new ();
3745
3746                 if (moduleb->types)
3747                         for (i = 0; i < moduleb->num_types; ++i) {
3748                                 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
3749                                 collect_types (types, type);
3750                         }
3751
3752                 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
3753                 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3754                 table->rows += types->len;
3755                 alloc_table (table, table->rows);
3756
3757                 for (i = 0; i < types->len; ++i) {
3758                         MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
3759                         mono_image_get_type_info (domain, type, assembly);
3760                 }
3761                 g_ptr_array_free (types, TRUE);
3762         }
3763
3764         /* 
3765          * table->rows is already set above and in mono_image_fill_module_table.
3766          */
3767         /* add all the custom attributes at the end, once all the indexes are stable */
3768         mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
3769
3770         module_add_cattrs (assembly, moduleb);
3771
3772         /* fixup tokens */
3773         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
3774         fixup_cattrs (assembly);
3775 }
3776
3777 /*
3778  * mono_image_insert_string:
3779  * @module: module builder object
3780  * @str: a string
3781  *
3782  * Insert @str into the user string stream of @module.
3783  */
3784 guint32
3785 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
3786 {
3787         MonoDynamicImage *assembly;
3788         guint32 idx;
3789         char buf [16];
3790         char *b = buf;
3791         
3792         MONO_ARCH_SAVE_REGS;
3793
3794         if (!module->dynamic_image)
3795                 mono_image_module_basic_init (module);
3796
3797         assembly = module->dynamic_image;
3798         
3799         if (assembly->save) {
3800                 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
3801                 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
3802 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
3803         {
3804                 char *swapped = g_malloc (2 * mono_string_length (str));
3805                 const char *p = (const char*)mono_string_chars (str);
3806
3807                 swap_with_size (swapped, p, 2, mono_string_length (str));
3808                 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
3809                 g_free (swapped);
3810         }
3811 #else
3812         mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
3813 #endif
3814         mono_image_add_stream_data (&assembly->us, "", 1);
3815         }
3816         else
3817                 idx = assembly->us.index ++;
3818
3819         mono_g_hash_table_insert (assembly->tokens, 
3820                                                           GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
3821
3822         return MONO_TOKEN_STRING | idx;
3823 }
3824
3825 /*
3826  * mono_image_create_token:
3827  * @assembly: a dynamic assembly
3828  * @obj:
3829  *
3830  * Get a token to insert in the IL code stream for the given MemberInfo.
3831  * @obj can be one of:
3832  *      ConstructorBuilder
3833  *      MethodBuilder
3834  *      FieldBuilder
3835  *      MonoCMethod
3836  *      MonoMethod
3837  *      MonoField
3838  *      MonoType
3839  *      TypeBuilder
3840  */
3841 guint32
3842 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj)
3843 {
3844         MonoClass *klass;
3845         guint32 token = 0;
3846
3847         klass = obj->vtable->klass;
3848         if (strcmp (klass->name, "MethodBuilder") == 0) {
3849                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
3850
3851                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3852                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3853                 else
3854                         token = mono_image_get_methodbuilder_token (assembly, mb);
3855                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3856         }
3857         else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
3858                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
3859
3860                 if (((MonoReflectionTypeBuilder*)mb->type)->module->dynamic_image == assembly)
3861                         token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
3862                 else
3863                         token = mono_image_get_ctorbuilder_token (assembly, mb);
3864                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
3865         }
3866         else if (strcmp (klass->name, "FieldBuilder") == 0) {
3867                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
3868                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
3869                 if (tb->generic_params) {
3870                         token = mono_image_get_generic_field_token (assembly, fb);
3871                 } else {
3872                         token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
3873                 }
3874         }
3875         else if (strcmp (klass->name, "TypeBuilder") == 0) {
3876                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
3877                 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
3878         }
3879         else if (strcmp (klass->name, "MonoType") == 0 ||
3880                  strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
3881                 MonoReflectionType *tb = (MonoReflectionType *)obj;
3882                 token = mono_metadata_token_from_dor (
3883                         mono_image_typedef_or_ref (assembly, tb->type));
3884         }
3885         else if (strcmp (klass->name, "MonoGenericInst") == 0) {
3886                 MonoReflectionType *tb = (MonoReflectionType *)obj;
3887                 token = mono_metadata_token_from_dor (
3888                         mono_image_typedef_or_ref (assembly, tb->type));
3889         }
3890         else if (strcmp (klass->name, "MonoCMethod") == 0 ||
3891                         strcmp (klass->name, "MonoMethod") == 0) {
3892                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
3893                 if (m->method->signature->is_inflated) {
3894                         token = mono_image_get_methodspec_token (assembly, m->method);
3895                 } else if (m->method->signature->generic_param_count) {
3896                         g_assert_not_reached ();
3897                 } else if ((m->method->klass->image == &assembly->image) &&
3898                          !m->method->klass->generic_inst) {
3899                         static guint32 method_table_idx = 0xffffff;
3900                         /*
3901                          * Each token should have a unique index, but the indexes are
3902                          * assigned by managed code, so we don't know about them. An
3903                          * easy solution is to count backwards...
3904                          */
3905                         method_table_idx --;
3906                         token = MONO_TOKEN_METHOD_DEF | method_table_idx;
3907                 } else
3908                         token = mono_image_get_methodref_token (assembly, m->method);
3909                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
3910         }
3911         else if (strcmp (klass->name, "MonoField") == 0) {
3912                 MonoReflectionField *f = (MonoReflectionField *)obj;
3913                 if ((f->klass->image == &assembly->image) && !f->field->generic_type) {
3914                         static guint32 field_table_idx = 0xffffff;
3915                         field_table_idx --;
3916                         token = MONO_TOKEN_FIELD_DEF | field_table_idx;
3917                 } else
3918                         token = mono_image_get_fieldref_token (assembly, f);
3919                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
3920         }
3921         else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
3922                 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
3923                 token = mono_image_get_array_token (assembly, m);
3924         }
3925         else if (strcmp (klass->name, "SignatureHelper") == 0) {
3926                 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
3927                 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
3928         }
3929         else
3930                 g_error ("requested token for %s\n", klass->name);
3931
3932         mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token),
3933                                                           obj);
3934
3935         return token;
3936 }
3937
3938 typedef struct {
3939         guint32 import_lookup_table;
3940         guint32 timestamp;
3941         guint32 forwarder;
3942         guint32 name_rva;
3943         guint32 import_address_table_rva;
3944 } MonoIDT;
3945
3946 typedef struct {
3947         guint32 name_rva;
3948         guint32 flags;
3949 } MonoILT;
3950
3951 static void register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
3952
3953 static MonoDynamicImage*
3954 create_dynamic_mono_image (MonoDynamicAssembly *assembly, 
3955                                                    char *assembly_name, char *module_name)
3956 {
3957         static const guchar entrycode [16] = {0xff, 0x25, 0};
3958         MonoDynamicImage *image;
3959         int i;
3960
3961         /*
3962          * We need to use the current ms version or the ms runtime it won't find
3963          * the support dlls. D'oh!
3964          * const char *version = "mono-" VERSION;
3965          */
3966         const char *version = "v1.0.3705";
3967
3968 #if HAVE_BOEHM_GC
3969         image = GC_MALLOC (sizeof (MonoDynamicImage));
3970 #else
3971         image = g_new0 (MonoDynamicImage, 1);
3972 #endif
3973
3974         /* keep in sync with image.c */
3975         image->image.name = assembly_name;
3976         image->image.assembly_name = image->image.name; /* they may be different */
3977         image->image.module_name = module_name;
3978         image->image.version = g_strdup (version);
3979         image->image.dynamic = TRUE;
3980
3981         image->image.references = g_new0 (MonoAssembly*, 1);
3982         image->image.references [0] = NULL;
3983
3984         mono_image_init (&image->image);
3985
3986         image->token_fixups = mono_g_hash_table_new (NULL, NULL);
3987         image->method_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3988         image->field_to_table_idx = mono_g_hash_table_new (NULL, NULL);
3989         image->method_aux_hash = mono_g_hash_table_new (NULL, NULL);
3990         image->handleref = g_hash_table_new (NULL, NULL);
3991         image->tokens = mono_g_hash_table_new (NULL, NULL);
3992         image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3993         image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
3994         image->blob_cache = mono_g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
3995
3996         string_heap_init (&image->sheap);
3997         mono_image_add_stream_data (&image->us, "", 1);
3998         add_to_blob_cached (image, (char*) "", 1, NULL, 0);
3999         /* import tables... */
4000         mono_image_add_stream_data (&image->code, entrycode, sizeof (entrycode));
4001         image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
4002         image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
4003         mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
4004         image->imp_names_offset = mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
4005         mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
4006         image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
4007         stream_data_align (&image->code);
4008
4009         image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
4010
4011         for (i=0; i < 64; ++i) {
4012                 image->tables [i].next_idx = 1;
4013                 image->tables [i].columns = table_sizes [i];
4014         }
4015
4016         image->image.assembly = (MonoAssembly*)assembly;
4017         image->run = assembly->run;
4018         image->save = assembly->save;
4019
4020         return image;
4021 }
4022
4023 /*
4024  * mono_image_basic_init:
4025  * @assembly: an assembly builder object
4026  *
4027  * Create the MonoImage that represents the assembly builder and setup some
4028  * of the helper hash table and the basic metadata streams.
4029  */
4030 void
4031 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4032 {
4033         MonoDynamicAssembly *assembly;
4034         MonoDynamicImage *image;
4035         
4036         MONO_ARCH_SAVE_REGS;
4037
4038         if (assemblyb->dynamic_assembly)
4039                 return;
4040
4041 #if HAVE_BOEHM_GC
4042         assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
4043 #else
4044         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicImage, 1);
4045 #endif
4046
4047         assembly->assembly.dynamic = TRUE;
4048         assemblyb->assembly.assembly = (MonoAssembly*)assembly;
4049         assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
4050         if (assemblyb->culture)
4051                 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
4052         else
4053                 assembly->assembly.aname.culture = g_strdup ("");
4054
4055         assembly->run = assemblyb->access != 2;
4056         assembly->save = assemblyb->access != 1;
4057
4058         image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4059         assembly->assembly.aname.name = image->image.name;
4060         assembly->assembly.image = &image->image;
4061
4062         register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
4063         mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
4064 }
4065
4066 static int
4067 calc_section_size (MonoDynamicImage *assembly)
4068 {
4069         int nsections = 0;
4070
4071         /* alignment constraints */
4072         assembly->code.index += 3;
4073         assembly->code.index &= ~3;
4074         assembly->meta_size += 3;
4075         assembly->meta_size &= ~3;
4076         assembly->resources.index += 3;
4077         assembly->resources.index &= ~3;
4078
4079         assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
4080         assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
4081         nsections++;
4082
4083         if (assembly->win32_res) {
4084                 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
4085
4086                 assembly->sections [MONO_SECTION_RSRC].size = res_size;
4087                 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
4088                 nsections++;
4089         }
4090
4091         assembly->sections [MONO_SECTION_RELOC].size = 12;
4092         assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
4093         nsections++;
4094
4095         return nsections;
4096 }
4097
4098 typedef struct {
4099         guint32 id;
4100         guint32 offset;
4101         GSList *children;
4102         MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
4103 } ResTreeNode;
4104
4105 static int
4106 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
4107 {
4108         ResTreeNode *t1 = (ResTreeNode*)a;
4109         ResTreeNode *t2 = (ResTreeNode*)b;
4110
4111         return t1->id - t2->id;
4112 }
4113
4114 /*
4115  * resource_tree_create:
4116  *
4117  *  Organize the resources into a resource tree.
4118  */
4119 static ResTreeNode *
4120 resource_tree_create (MonoArray *win32_resources)
4121 {
4122         ResTreeNode *tree, *res_node, *type_node, *lang_node;
4123         GSList *l;
4124         int i;
4125
4126         tree = g_new0 (ResTreeNode, 1);
4127         
4128         for (i = 0; i < mono_array_length (win32_resources); ++i) {
4129                 MonoReflectionWin32Resource *win32_res =
4130                         (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
4131
4132                 /* Create node */
4133
4134                 lang_node = g_new0 (ResTreeNode, 1);
4135                 lang_node->id = win32_res->lang_id;
4136                 lang_node->win32_res = win32_res;
4137
4138                 /* Create type node if neccesary */
4139                 type_node = NULL;
4140                 for (l = tree->children; l; l = l->next)
4141                         if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
4142                                 type_node = (ResTreeNode*)l->data;
4143                                 break;
4144                         }
4145
4146                 if (!type_node) {
4147                         type_node = g_new0 (ResTreeNode, 1);
4148                         type_node->id = win32_res->res_type;
4149
4150                         /* 
4151                          * The resource types have to be sorted otherwise
4152                          * Windows Explorer can't display the version information.
4153                          */
4154                         tree->children = g_slist_insert_sorted (tree->children, type_node, 
4155                                                                                                         resource_tree_compare_by_id);
4156                 }
4157
4158                 /* Create res node if neccesary */
4159                 res_node = NULL;
4160                 for (l = type_node->children; l; l = l->next)
4161                         if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
4162                                 res_node = (ResTreeNode*)l->data;
4163                                 break;
4164                         }
4165
4166                 if (!res_node) {
4167                         res_node = g_new0 (ResTreeNode, 1);
4168                         res_node->id = win32_res->res_id;
4169                         type_node->children = g_slist_append (type_node->children, res_node);
4170                 }
4171
4172                 res_node->children = g_slist_append (res_node->children, lang_node);
4173         }
4174
4175         return tree;
4176 }
4177
4178 /*
4179  * resource_tree_encode:
4180  * 
4181  *   Encode the resource tree into the format used in the PE file.
4182  */
4183 static void
4184 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
4185 {
4186         char *entries;
4187         MonoPEResourceDir dir;
4188         MonoPEResourceDirEntry dir_entry;
4189         MonoPEResourceDataEntry data_entry;
4190         GSList *l;
4191
4192         /*
4193          * For the format of the resource directory, see the article
4194          * "An In-Depth Look into the Win32 Portable Executable File Format" by
4195          * Matt Pietrek
4196          */
4197
4198         memset (&dir, 0, sizeof (dir));
4199         memset (&dir_entry, 0, sizeof (dir_entry));
4200         memset (&data_entry, 0, sizeof (data_entry));
4201
4202         g_assert (sizeof (dir) == 16);
4203         g_assert (sizeof (dir_entry) == 8);
4204         g_assert (sizeof (data_entry) == 16);
4205
4206         node->offset = p - begin;
4207
4208         /* IMAGE_RESOURCE_DIRECTORY */
4209         dir.res_id_entries = GUINT32_TO_LE (g_slist_length (node->children));
4210
4211         memcpy (p, &dir, sizeof (dir));
4212         p += sizeof (dir);
4213
4214         /* Reserve space for entries */
4215         entries = p;
4216         p += sizeof (dir_entry) * dir.res_id_entries;
4217
4218         /* Write children */
4219         for (l = node->children; l; l = l->next) {
4220                 ResTreeNode *child = (ResTreeNode*)l->data;
4221
4222                 if (child->win32_res) {
4223
4224                         child->offset = p - begin;
4225
4226                         /* IMAGE_RESOURCE_DATA_ENTRY */
4227                         data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
4228                         data_entry.rde_size = mono_array_length (child->win32_res->res_data);
4229
4230                         memcpy (p, &data_entry, sizeof (data_entry));
4231                         p += sizeof (data_entry);
4232
4233                         memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), data_entry.rde_size);
4234                         p += data_entry.rde_size;
4235                 }
4236                 else
4237                         resource_tree_encode (child, begin, p, &p);
4238         }
4239
4240         /* IMAGE_RESOURCE_ENTRY */
4241         for (l = node->children; l; l = l->next) {
4242                 ResTreeNode *child = (ResTreeNode*)l->data;
4243                 dir_entry.name_offset = GUINT32_TO_LE (child->id);
4244
4245                 dir_entry.is_dir = child->win32_res ? 0 : 1;
4246                 dir_entry.dir_offset = GUINT32_TO_LE (child->offset);
4247
4248                 memcpy (entries, &dir_entry, sizeof (dir_entry));
4249                 entries += sizeof (dir_entry);
4250         }
4251
4252         *endbuf = p;
4253 }
4254
4255 static void
4256 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
4257 {
4258         char *buf;
4259         char *p;
4260         guint32 size, i;
4261         MonoReflectionWin32Resource *win32_res;
4262         ResTreeNode *tree;
4263
4264         if (!assemblyb->win32_resources)
4265                 return;
4266
4267         /*
4268          * Resources are stored in a three level tree inside the PE file.
4269          * - level one contains a node for each type of resource
4270          * - level two contains a node for each resource
4271          * - level three contains a node for each instance of a resource for a
4272          *   specific language.
4273          */
4274
4275         tree = resource_tree_create (assemblyb->win32_resources);
4276
4277         /* Estimate the size of the encoded tree */
4278         size = 0;
4279         for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
4280                 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
4281                 size += mono_array_length (win32_res->res_data);
4282         }
4283         /* Directory structure */
4284         size += mono_array_length (assemblyb->win32_resources) * 256;
4285         p = buf = g_malloc (size);
4286
4287         resource_tree_encode (tree, p, p, &p);
4288
4289         g_assert (p - buf < size);
4290
4291         assembly->win32_res = g_malloc (p - buf);
4292         assembly->win32_res_size = p - buf;
4293         memcpy (assembly->win32_res, buf, p - buf);
4294
4295         g_free (buf);
4296 }
4297
4298 static void
4299 fixup_resource_directory (char *res_section, char *p, guint32 rva)
4300 {
4301         MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
4302         int i;
4303
4304         p += sizeof (MonoPEResourceDir);
4305         for (i = 0; i < dir->res_named_entries + dir->res_id_entries; ++i) {
4306                 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
4307                 char *child = res_section + (GUINT32_FROM_LE (dir_entry->dir_offset));
4308                 if (dir_entry->is_dir)
4309                         fixup_resource_directory (res_section, child, rva);
4310                 else {
4311                         MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
4312                         data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
4313                 }
4314
4315                 p += sizeof (MonoPEResourceDirEntry);
4316         }
4317 }
4318
4319 /*
4320  * mono_image_create_pefile:
4321  * @mb: a module builder object
4322  * 
4323  * This function creates the PE-COFF header, the image sections, the CLI header  * etc. all the data is written in
4324  * assembly->pefile where it can be easily retrieved later in chunks.
4325  */
4326 void
4327 mono_image_create_pefile (MonoReflectionModuleBuilder *mb) {
4328         MonoMSDOSHeader *msdos;
4329         MonoDotNetHeader *header;
4330         MonoSectionTable *section;
4331         MonoCLIHeader *cli_header;
4332         guint32 size, image_size, virtual_base, text_offset;
4333         guint32 header_start, section_start, file_offset, virtual_offset;
4334         MonoDynamicImage *assembly;
4335         MonoReflectionAssemblyBuilder *assemblyb;
4336         MonoDynamicStream *pefile;
4337         int i, nsections;
4338         guint32 *rva, value;
4339         guint16 *data16;
4340         guchar *p;
4341         static const unsigned char msheader[] = {
4342                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
4343                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4344                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
4345                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
4346                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
4347                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
4348                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
4349                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
4350         };
4351
4352         assemblyb = mb->assemblyb;
4353
4354         mono_image_basic_init (assemblyb);
4355         assembly = mb->dynamic_image;
4356
4357         /* already created */
4358         if (assembly->pefile.index)
4359                 return;
4360         
4361         mono_image_build_metadata (mb);
4362
4363         if (mb->is_main && assemblyb->resources) {
4364                 int len = mono_array_length (assemblyb->resources);
4365                 for (i = 0; i < len; ++i)
4366                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
4367         }
4368
4369         if (mb->resources) {
4370                 int len = mono_array_length (mb->resources);
4371                 for (i = 0; i < len; ++i)
4372                         assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
4373         }
4374
4375         build_compressed_metadata (assembly);
4376
4377         if (mb->is_main)
4378                 assembly_add_win32_resources (assembly, assemblyb);
4379
4380         nsections = calc_section_size (assembly);
4381
4382         pefile = &assembly->pefile;
4383
4384         /* The DOS header and stub */
4385         g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
4386         mono_image_add_stream_data (pefile, msheader, sizeof (msheader));
4387
4388         /* the dotnet header */
4389         header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
4390
4391         /* the section tables */
4392         section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
4393
4394         file_offset = section_start + sizeof (MonoSectionTable) * nsections;
4395         virtual_offset = VIRT_ALIGN;
4396         image_size = 0;
4397
4398         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4399                 if (!assembly->sections [i].size)
4400                         continue;
4401                 /* align offsets */
4402                 file_offset += FILE_ALIGN - 1;
4403                 file_offset &= ~(FILE_ALIGN - 1);
4404                 virtual_offset += VIRT_ALIGN - 1;
4405                 virtual_offset &= ~(VIRT_ALIGN - 1);
4406
4407                 assembly->sections [i].offset = file_offset;
4408                 assembly->sections [i].rva = virtual_offset;
4409
4410                 file_offset += assembly->sections [i].size;
4411                 virtual_offset += assembly->sections [i].size;
4412                 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
4413         }
4414
4415         file_offset += FILE_ALIGN - 1;
4416         file_offset &= ~(FILE_ALIGN - 1);
4417         mono_image_add_stream_zero (pefile, file_offset - pefile->index);
4418
4419         image_size += section_start + sizeof (MonoSectionTable) * nsections;
4420
4421         /* back-patch info */
4422         msdos = (MonoMSDOSHeader*)pefile->data;
4423         msdos->nlast_page = GUINT16_FROM_LE (file_offset & (512 - 1));
4424         msdos->npages = GUINT16_FROM_LE ((file_offset + (512 - 1)) / 512);
4425         msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
4426
4427         header = (MonoDotNetHeader*)(pefile->data + header_start);
4428         header->pesig [0] = 'P';
4429         header->pesig [1] = 'E';
4430         
4431         header->coff.coff_machine = GUINT16_FROM_LE (0x14c);
4432         header->coff.coff_sections = GUINT16_FROM_LE (nsections);
4433         header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
4434         header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
4435         if (assemblyb->pekind == 1) {
4436                 /* it's a dll */
4437                 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
4438         } else {
4439                 /* it's an exe */
4440                 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
4441         }
4442
4443         virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
4444
4445         header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
4446         header->pe.pe_major = 6;
4447         header->pe.pe_minor = 0;
4448         size = assembly->sections [MONO_SECTION_TEXT].size;
4449         size += FILE_ALIGN - 1;
4450         size &= ~(FILE_ALIGN - 1);
4451         header->pe.pe_code_size = GUINT32_FROM_LE(size);
4452         size = assembly->sections [MONO_SECTION_RSRC].size;
4453         size += FILE_ALIGN - 1;
4454         size &= ~(FILE_ALIGN - 1);
4455         header->pe.pe_data_size = GUINT32_FROM_LE(size);
4456         g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
4457         header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4458         header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4459         /* pe_rva_entry_point always at the beginning of the text section */
4460         header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
4461
4462         header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
4463         header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
4464         header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
4465         header->nt.pe_os_major = GUINT16_FROM_LE (4);
4466         header->nt.pe_os_minor = GUINT16_FROM_LE (0);
4467         header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
4468         size = section_start;
4469         size += FILE_ALIGN - 1;
4470         size &= ~(FILE_ALIGN - 1);
4471         header->nt.pe_header_size = GUINT32_FROM_LE (size);
4472         size = image_size;
4473         size += VIRT_ALIGN - 1;
4474         size &= ~(VIRT_ALIGN - 1);
4475         header->nt.pe_image_size = GUINT32_FROM_LE (size);
4476
4477         //
4478         // Translate the PEFileKind value to the value expected by the Windows loader
4479         //
4480         {
4481                 short kind = assemblyb->pekind;
4482
4483                 //
4484                 // PEFileKinds.ConsoleApplication == 2
4485                 // PEFileKinds.WindowApplication == 3
4486                 //
4487                 // need to get:
4488                 //     IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
4489                 //     IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
4490                 if (kind == 2)
4491                         kind = 3;
4492                 else if (kind == 3)
4493                         kind = 2;
4494                 
4495                 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
4496         }    
4497         header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
4498         header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
4499         header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
4500         header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
4501         header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
4502         header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
4503
4504         /* fill data directory entries */
4505
4506         header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
4507         header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
4508
4509         header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
4510         header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
4511
4512         header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
4513         header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
4514         header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
4515         header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4516         /* patch imported function RVA name */
4517         rva = (guint32*)(assembly->code.data + assembly->iat_offset);
4518         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
4519
4520         /* the import table */
4521         header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
4522         header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
4523         /* patch imported dll RVA name and other entries in the dir */
4524         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
4525         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 12); /* 12 is strlen+1 of func name */
4526         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
4527         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
4528         rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
4529         *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
4530
4531         p = (assembly->code.data + assembly->ilt_offset);
4532         value = (assembly->text_rva + assembly->imp_names_offset - 2);
4533         *p++ = (value) & 0xff;
4534         *p++ = (value >> 8) & (0xff);
4535         *p++ = (value >> 16) & (0xff);
4536         *p++ = (value >> 24) & (0xff);
4537
4538         /* the CLI header info */
4539         cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
4540         cli_header->ch_size = GUINT32_FROM_LE (72);
4541         cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
4542         cli_header->ch_flags = GUINT32_FROM_LE (CLI_FLAGS_ILONLY);
4543         if (assemblyb->entry_point) {
4544                 guint32 table_idx = 0;
4545                 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
4546                         MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
4547                         table_idx = methodb->table_idx;
4548                 }
4549                 else
4550                         table_idx = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
4551                 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
4552         }                       
4553         else
4554                 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
4555         /* The embedded managed resources */
4556         text_offset = assembly->text_rva + assembly->code.index;
4557         cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
4558         cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
4559         text_offset += assembly->resources.index;
4560         cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
4561         cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
4562         text_offset += assembly->meta_size;
4563         if (assembly->strong_name_size) {
4564                 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
4565                 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
4566                 text_offset += assembly->strong_name_size;
4567         }
4568
4569         /* write the section tables and section content */
4570         section = (MonoSectionTable*)(pefile->data + section_start);
4571         for (i = 0; i < MONO_SECTION_MAX; ++i) {
4572                 static const char *section_names [] = {
4573                         ".text", ".rsrc", ".reloc"
4574                 };
4575                 if (!assembly->sections [i].size)
4576                         continue;
4577                 strcpy (section->st_name, section_names [i]);
4578                 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
4579                 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
4580                 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
4581                 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
4582                 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
4583                 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
4584                 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
4585                 switch (i) {
4586                 case MONO_SECTION_TEXT:
4587                         /* patch entry point */
4588                         p = (assembly->code.data + 2);
4589                         value = (virtual_base + assembly->text_rva + assembly->iat_offset);
4590                         *p++ = (value) & 0xff;
4591                         *p++ = (value >> 8) & 0xff;
4592                         *p++ = (value >> 16) & 0xff;
4593                         *p++ = (value >> 24) & 0xff;
4594
4595                         text_offset = assembly->sections [i].offset;
4596                         memcpy (pefile->data + text_offset, assembly->code.data, assembly->code.index);
4597                         text_offset += assembly->code.index;
4598                         memcpy (pefile->data + text_offset, assembly->resources.data, assembly->resources.index);
4599                         text_offset += assembly->resources.index;
4600                         memcpy (pefile->data + text_offset, assembly->image.raw_metadata, assembly->meta_size);
4601                         text_offset += assembly->meta_size;
4602                         memcpy (pefile->data + text_offset, assembly->strong_name, assembly->strong_name_size);
4603
4604                         g_free (assembly->image.raw_metadata);
4605                         break;
4606                 case MONO_SECTION_RELOC:
4607                         rva = (guint32*)(pefile->data + assembly->sections [i].offset);
4608                         *rva = GUINT32_FROM_LE (assembly->text_rva);
4609                         ++rva;
4610                         *rva = GUINT32_FROM_LE (12);
4611                         ++rva;
4612                         data16 = (guint16*)rva;
4613                         /* 
4614                          * the entrypoint is always at the start of the text section 
4615                          * 3 is IMAGE_REL_BASED_HIGHLOW
4616                          * 2 is patch_size_rva - text_rva
4617                          */
4618                         *data16 = GUINT16_FROM_LE ((3 << 12) + (2));
4619                         data16++;
4620                         *data16 = 0; /* terminate */
4621                         break;
4622                 case MONO_SECTION_RSRC:
4623                         if (assembly->win32_res) {
4624                                 text_offset = assembly->sections [i].offset;
4625
4626                                 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
4627                                 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
4628
4629                                 memcpy (pefile->data + text_offset, assembly->win32_res, assembly->win32_res_size);
4630                         }
4631                         break;
4632                 default:
4633                         g_assert_not_reached ();
4634                 }
4635                 section++;
4636         }
4637         
4638         /* check that the file is properly padded */
4639 #if 0
4640         {
4641                 FILE *f = fopen ("mypetest.exe", "w");
4642                 fwrite (pefile->data, pefile->index, 1, f);
4643                 fclose (f);
4644         }
4645 #endif
4646 }
4647
4648 MonoReflectionModule *
4649 mono_image_load_module (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
4650 {
4651         char *name;
4652         MonoImage *image;
4653         MonoImageOpenStatus status;
4654         MonoDynamicAssembly *assembly;
4655         
4656         name = mono_string_to_utf8 (fileName);
4657
4658         image = mono_image_open (name, &status);
4659         if (status) {
4660                 MonoException *exc;
4661                 if (status == MONO_IMAGE_ERROR_ERRNO)
4662                         exc = mono_get_exception_file_not_found (fileName);
4663                 else
4664                         exc = mono_get_exception_bad_image_format (name);
4665                 g_free (name);
4666                 mono_raise_exception (exc);
4667         }
4668
4669         g_free (name);
4670
4671         assembly = ab->dynamic_assembly;
4672         image->assembly = (MonoAssembly*)assembly;
4673
4674         mono_assembly_load_references (image, &status);
4675         if (status) {
4676                 mono_image_close (image);
4677                 mono_raise_exception (mono_get_exception_file_not_found (fileName));
4678         }
4679
4680         return mono_module_get_object (mono_domain_get (), image);
4681 }
4682
4683 /*
4684  * We need to return always the same object for MethodInfo, FieldInfo etc..
4685  * but we need to consider the reflected type.
4686  * type uses a different hash, since it uses custom hash/equal functions.
4687  */
4688
4689 typedef struct {
4690         gpointer item;
4691         MonoClass *refclass;
4692 } ReflectedEntry;
4693
4694 static gboolean
4695 reflected_equal (gconstpointer a, gconstpointer b) {
4696         const ReflectedEntry *ea = a;
4697         const ReflectedEntry *eb = b;
4698
4699         return (ea->item == eb->item) && (ea->refclass == eb->refclass);
4700 }
4701
4702 static guint
4703 reflected_hash (gconstpointer a) {
4704         const ReflectedEntry *ea = a;
4705         return GPOINTER_TO_UINT (ea->item);
4706 }
4707
4708 #define CHECK_OBJECT(t,p,k)     \
4709         do {    \
4710                 t _obj; \
4711                 ReflectedEntry e;       \
4712                 e.item = (p);   \
4713                 e.refclass = (k);       \
4714                 mono_domain_lock (domain);      \
4715                 if (!domain->refobject_hash)    \
4716                         domain->refobject_hash = mono_g_hash_table_new (reflected_hash, reflected_equal);       \
4717                 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) {   \
4718                         mono_domain_unlock (domain);    \
4719                         return _obj;    \
4720                 }       \
4721         } while (0)
4722
4723 #if HAVE_BOEHM_GC
4724 #define ALLOC_REFENTRY GC_MALLOC (sizeof (ReflectedEntry))
4725 #else
4726 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
4727 #endif
4728
4729 #define CACHE_OBJECT(p,o,k)     \
4730         do {    \
4731                 ReflectedEntry *e = ALLOC_REFENTRY;     \
4732                 e->item = (p);  \
4733                 e->refclass = (k);      \
4734                 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
4735                 mono_domain_unlock (domain);    \
4736         } while (0)
4737
4738 static void 
4739 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
4740 {
4741         /* this is done only once */
4742         mono_domain_lock (domain);
4743         CACHE_OBJECT (assembly, res, NULL);
4744 }
4745
4746 static void
4747 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
4748 {
4749         /* this is done only once */
4750         mono_domain_lock (domain);
4751         CACHE_OBJECT (module, res, NULL);
4752 }
4753
4754 void
4755 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
4756 {
4757         MonoDynamicImage *image = moduleb->dynamic_image;
4758         MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
4759         if (!image) {
4760                 /*
4761                  * FIXME: we already created an image in mono_image_basic_init (), but
4762                  * we don't know which module it belongs to, since that is only 
4763                  * determined at assembly save time.
4764                  */
4765                 //image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image;
4766                 image = create_dynamic_mono_image (ab->dynamic_assembly, mono_string_to_utf8 (ab->name), mono_string_to_utf8 (moduleb->module.fqname));
4767
4768                 moduleb->module.image = &image->image;
4769                 moduleb->dynamic_image = image;
4770                 register_module (mono_object_domain (moduleb), moduleb, image);
4771         }
4772 }
4773
4774 /*
4775  * mono_assembly_get_object:
4776  * @domain: an app domain
4777  * @assembly: an assembly
4778  *
4779  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
4780  */
4781 MonoReflectionAssembly*
4782 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
4783 {
4784         static MonoClass *System_Reflection_Assembly;
4785         MonoReflectionAssembly *res;
4786         
4787         CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
4788         if (!System_Reflection_Assembly)
4789                 System_Reflection_Assembly = mono_class_from_name (
4790                         mono_defaults.corlib, "System.Reflection", "Assembly");
4791         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
4792         res->assembly = assembly;
4793         CACHE_OBJECT (assembly, res, NULL);
4794         return res;
4795 }
4796
4797
4798
4799 MonoReflectionModule*   
4800 mono_module_get_object   (MonoDomain *domain, MonoImage *image)
4801 {
4802         static MonoClass *System_Reflection_Module;
4803         MonoReflectionModule *res;
4804         
4805         CHECK_OBJECT (MonoReflectionModule *, image, NULL);
4806         if (!System_Reflection_Module)
4807                 System_Reflection_Module = mono_class_from_name (
4808                         mono_defaults.corlib, "System.Reflection", "Module");
4809         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4810
4811         res->image = image;
4812         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4813
4814         res->fqname    = mono_string_new (domain, image->name);
4815         res->name      = mono_string_new (domain, g_path_get_basename (image->name));
4816         res->scopename = mono_string_new (domain, image->module_name);
4817
4818         mono_image_addref (image);
4819
4820         CACHE_OBJECT (image, res, NULL);
4821         return res;
4822 }
4823
4824 MonoReflectionModule*   
4825 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
4826 {
4827         static MonoClass *System_Reflection_Module;
4828         MonoReflectionModule *res;
4829         MonoTableInfo *table;
4830         guint32 cols [MONO_FILE_SIZE];
4831         const char *name;
4832         guint32 i, name_idx;
4833         const char *val;
4834         
4835         if (!System_Reflection_Module)
4836                 System_Reflection_Module = mono_class_from_name (
4837                         mono_defaults.corlib, "System.Reflection", "Module");
4838         res = (MonoReflectionModule *)mono_object_new (domain, System_Reflection_Module);
4839
4840         table = &image->tables [MONO_TABLE_FILE];
4841         g_assert (table_index < table->rows);
4842         mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
4843
4844         res->image = 0;
4845         res->assembly = (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly);
4846         name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4847
4848         // Check whenever the row has a corresponding row in the moduleref table
4849         table = &image->tables [MONO_TABLE_MODULEREF];
4850         for (i = 0; i < table->rows; ++i) {
4851                 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
4852                 val = mono_metadata_string_heap (image, name_idx);
4853                 if (strcmp (val, name) == 0)
4854                         res->image = image->modules [i];
4855         }
4856
4857         res->fqname    = mono_string_new (domain, name);
4858         res->name      = mono_string_new (domain, name);
4859         res->scopename = mono_string_new (domain, name);
4860         res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
4861
4862         return res;
4863 }
4864
4865 static gboolean
4866 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
4867 {
4868         if ((t1->type != t2->type) ||
4869             (t1->byref != t2->byref))
4870                 return FALSE;
4871
4872         switch (t1->type) {
4873         case MONO_TYPE_VOID:
4874         case MONO_TYPE_BOOLEAN:
4875         case MONO_TYPE_CHAR:
4876         case MONO_TYPE_I1:
4877         case MONO_TYPE_U1:
4878         case MONO_TYPE_I2:
4879         case MONO_TYPE_U2:
4880         case MONO_TYPE_I4:
4881         case MONO_TYPE_U4:
4882         case MONO_TYPE_I8:
4883         case MONO_TYPE_U8:
4884         case MONO_TYPE_R4:
4885         case MONO_TYPE_R8:
4886         case MONO_TYPE_STRING:
4887         case MONO_TYPE_I:
4888         case MONO_TYPE_U:
4889         case MONO_TYPE_OBJECT:
4890         case MONO_TYPE_TYPEDBYREF:
4891                 return TRUE;
4892         case MONO_TYPE_VALUETYPE:
4893         case MONO_TYPE_CLASS:
4894         case MONO_TYPE_SZARRAY:
4895                 return t1->data.klass == t2->data.klass;
4896         case MONO_TYPE_PTR:
4897                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
4898         case MONO_TYPE_ARRAY:
4899                 if (t1->data.array->rank != t2->data.array->rank)
4900                         return FALSE;
4901                 return t1->data.array->eklass == t2->data.array->eklass;
4902         case MONO_TYPE_GENERICINST: {
4903                 int i;
4904                 if (t1->data.generic_inst->type_argc != t2->data.generic_inst->type_argc)
4905                         return FALSE;
4906                 if (!mono_metadata_type_equal (t1->data.generic_inst->generic_type, t2->data.generic_inst->generic_type))
4907                         return FALSE;
4908                 for (i = 0; i < t1->data.generic_inst->type_argc; ++i) {
4909                         if (!mono_metadata_type_equal (t1->data.generic_inst->type_argv [i], t2->data.generic_inst->type_argv [i]))
4910                                 return FALSE;
4911                 }
4912                 return TRUE;
4913         }
4914         case MONO_TYPE_VAR:
4915         case MONO_TYPE_MVAR:
4916                 return t1->data.generic_param == t2->data.generic_param;
4917         default:
4918                 g_error ("implement type compare for %0x!", t1->type);
4919                 return FALSE;
4920         }
4921
4922         return FALSE;
4923 }
4924
4925 static guint
4926 mymono_metadata_type_hash (MonoType *t1)
4927 {
4928         guint hash;
4929
4930         hash = t1->type;
4931
4932         hash |= t1->byref << 6; /* do not collide with t1->type values */
4933         switch (t1->type) {
4934         case MONO_TYPE_VALUETYPE:
4935         case MONO_TYPE_CLASS:
4936         case MONO_TYPE_SZARRAY:
4937                 /* check if the distribution is good enough */
4938                 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
4939         case MONO_TYPE_PTR:
4940                 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
4941         }
4942         return hash;
4943 }
4944
4945 static MonoReflectionGenericInst*
4946 mono_generic_inst_get_object (MonoDomain *domain, MonoType *geninst)
4947 {
4948         static MonoClass *System_Reflection_MonoGenericInst;
4949         MonoReflectionGenericInst *res;
4950         MonoGenericInst *ginst;
4951         MonoClass *gklass;
4952
4953         if (!System_Reflection_MonoGenericInst) {
4954                 System_Reflection_MonoGenericInst = mono_class_from_name (
4955                         mono_defaults.corlib, "System.Reflection", "MonoGenericInst");
4956                 g_assert (System_Reflection_MonoGenericInst);
4957         }
4958
4959         ginst = geninst->data.generic_inst;
4960         gklass = mono_class_from_mono_type (ginst->generic_type);
4961
4962         mono_class_init (ginst->klass);
4963
4964         res = (MonoReflectionGenericInst *) mono_object_new (domain, System_Reflection_MonoGenericInst);
4965
4966         res->type.type = geninst;
4967         if (gklass->wastypebuilder && gklass->reflection_info)
4968                 res->generic_type = gklass->reflection_info;
4969         else
4970                 res->generic_type = mono_type_get_object (domain, ginst->generic_type);
4971
4972         return res;
4973 }
4974
4975 /*
4976  * mono_type_get_object:
4977  * @domain: an app domain
4978  * @type: a type
4979  *
4980  * Return an System.MonoType object representing the type @type.
4981  */
4982 MonoReflectionType*
4983 mono_type_get_object (MonoDomain *domain, MonoType *type)
4984 {
4985         MonoReflectionType *res;
4986         MonoClass *klass = mono_class_from_mono_type (type);
4987
4988         mono_domain_lock (domain);
4989         if (!domain->type_hash)
4990                 domain->type_hash = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
4991                                 (GCompareFunc)mymono_metadata_type_equal);
4992         if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
4993                 mono_domain_unlock (domain);
4994                 return res;
4995         }
4996         if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_inst->is_dynamic) {
4997                 res = (MonoReflectionType *)mono_generic_inst_get_object (domain, type);
4998                 mono_g_hash_table_insert (domain->type_hash, type, res);
4999                 mono_domain_unlock (domain);
5000                 return res;
5001         }
5002         if (klass->reflection_info && !klass->wastypebuilder) {
5003                 //g_assert_not_reached ();
5004                 /* should this be considered an error condition? */
5005                 if (!type->byref) {
5006                         mono_domain_unlock (domain);
5007                         return klass->reflection_info;
5008                 }
5009         }
5010         mono_class_init (klass);
5011         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
5012         res->type = type;
5013         mono_g_hash_table_insert (domain->type_hash, type, res);
5014         mono_domain_unlock (domain);
5015         return res;
5016 }
5017
5018 /*
5019  * mono_method_get_object:
5020  * @domain: an app domain
5021  * @method: a method
5022  * @refclass: the reflected type (can be NULL)
5023  *
5024  * Return an System.Reflection.MonoMethod object representing the method @method.
5025  */
5026 MonoReflectionMethod*
5027 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
5028 {
5029         /*
5030          * We use the same C representation for methods and constructors, but the type 
5031          * name in C# is different.
5032          */
5033         const char *cname;
5034         MonoClass *klass;
5035         MonoReflectionMethod *ret;
5036
5037         if (!refclass)
5038                 refclass = method->klass;
5039
5040         CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
5041         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
5042                 cname = "MonoCMethod";
5043         else
5044                 cname = "MonoMethod";
5045         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
5046
5047         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
5048         ret->method = method;
5049         ret->name = mono_string_new (domain, method->name);
5050         ret->reftype = mono_type_get_object (domain, &refclass->byval_arg);
5051         CACHE_OBJECT (method, ret, refclass);
5052         return ret;
5053 }
5054
5055 /*
5056  * mono_field_get_object:
5057  * @domain: an app domain
5058  * @klass: a type
5059  * @field: a field
5060  *
5061  * Return an System.Reflection.MonoField object representing the field @field
5062  * in class @klass.
5063  */
5064 MonoReflectionField*
5065 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
5066 {
5067         MonoReflectionField *res;
5068         MonoClass *oklass;
5069
5070         CHECK_OBJECT (MonoReflectionField *, field, klass);
5071         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
5072         res = (MonoReflectionField *)mono_object_new (domain, oklass);
5073         res->klass = klass;
5074         res->field = field;
5075         res->name = mono_string_new (domain, field->name);
5076         res->attrs = field->type->attrs;
5077         res->type = mono_type_get_object (domain, field->type);
5078         CACHE_OBJECT (field, res, klass);
5079         return res;
5080 }
5081
5082 /*
5083  * mono_property_get_object:
5084  * @domain: an app domain
5085  * @klass: a type
5086  * @property: a property
5087  *
5088  * Return an System.Reflection.MonoProperty object representing the property @property
5089  * in class @klass.
5090  */
5091 MonoReflectionProperty*
5092 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
5093 {
5094         MonoReflectionProperty *res;
5095         MonoClass *oklass;
5096
5097         CHECK_OBJECT (MonoReflectionProperty *, property, klass);
5098         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
5099         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
5100         res->klass = klass;
5101         res->property = property;
5102         CACHE_OBJECT (property, res, klass);
5103         return res;
5104 }
5105
5106 /*
5107  * mono_event_get_object:
5108  * @domain: an app domain
5109  * @klass: a type
5110  * @event: a event
5111  *
5112  * Return an System.Reflection.MonoEvent object representing the event @event
5113  * in class @klass.
5114  */
5115 MonoReflectionEvent*
5116 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
5117 {
5118         MonoReflectionEvent *res;
5119         MonoClass *oklass;
5120
5121         CHECK_OBJECT (MonoReflectionEvent *, event, klass);
5122         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
5123         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
5124         res->klass = klass;
5125         res->event = event;
5126         CACHE_OBJECT (event, res, klass);
5127         return res;
5128 }
5129
5130 /*
5131  * mono_param_get_objects:
5132  * @domain: an app domain
5133  * @method: a method
5134  *
5135  * Return an System.Reflection.ParameterInfo array object representing the parameters
5136  * in the method @method.
5137  */
5138 MonoArray*
5139 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
5140 {
5141         static MonoClass *System_Reflection_ParameterInfo;
5142         MonoArray *res = NULL;
5143         MonoReflectionMethod *member = NULL;
5144         MonoReflectionParameter *param = NULL;
5145         char **names;
5146         int i;
5147
5148         if (!System_Reflection_ParameterInfo)
5149                 System_Reflection_ParameterInfo = mono_class_from_name (
5150                         mono_defaults.corlib, "System.Reflection", "ParameterInfo");
5151         
5152         if (!method->signature->param_count)
5153                 return mono_array_new (domain, System_Reflection_ParameterInfo, 0);
5154
5155         /* Note: the cache is based on the address of the signature into the method
5156          * since we already cache MethodInfos with the method as keys.
5157          */
5158         CHECK_OBJECT (MonoArray*, &(method->signature), NULL);
5159
5160         member = mono_method_get_object (domain, method, NULL);
5161         names = g_new (char *, method->signature->param_count);
5162         mono_method_get_param_names (method, (const char **) names);
5163
5164         res = mono_array_new (domain, System_Reflection_ParameterInfo, method->signature->param_count);
5165         for (i = 0; i < method->signature->param_count; ++i) {
5166                 param = (MonoReflectionParameter *)mono_object_new (domain, 
5167                                                                                                                         System_Reflection_ParameterInfo);
5168                 param->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
5169                 param->DefaultValueImpl = NULL; /* FIXME */
5170                 param->MemberImpl = (MonoObject*)member;
5171                 param->NameImpl = mono_string_new (domain, names [i]);
5172                 param->PositionImpl = i;
5173                 param->AttrsImpl = method->signature->params [i]->attrs;
5174                 mono_array_set (res, gpointer, i, param);
5175         }
5176         g_free (names);
5177         CACHE_OBJECT (&(method->signature), res, NULL);
5178         return res;
5179 }
5180
5181 static int
5182 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
5183         int found_sep;
5184         char *s;
5185
5186         memset (assembly, 0, sizeof (MonoAssemblyName));
5187         assembly->name = p;
5188         assembly->culture = "";
5189         
5190         while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
5191                 p++;
5192         found_sep = 0;
5193         while (*p == ' ' || *p == ',') {
5194                 *p++ = 0;
5195                 found_sep = 1;
5196                 continue;
5197         }
5198         /* failed */
5199         if (!found_sep)
5200                 return 1;
5201         while (*p) {
5202                 if (*p == 'V' && strncmp (p, "Version=", 8) == 0) {
5203                         p += 8;
5204                         assembly->major = strtoul (p, &s, 10);
5205                         if (s == p || *s != '.')
5206                                 return 1;
5207                         p = ++s;
5208                         assembly->minor = strtoul (p, &s, 10);
5209                         if (s == p || *s != '.')
5210                                 return 1;
5211                         p = ++s;
5212                         assembly->build = strtoul (p, &s, 10);
5213                         if (s == p || *s != '.')
5214                                 return 1;
5215                         p = ++s;
5216                         assembly->revision = strtoul (p, &s, 10);
5217                         if (s == p)
5218                                 return 1;
5219                 } else if (*p == 'C' && strncmp (p, "Culture=", 8) == 0) {
5220                         p += 8;
5221                         if (strncmp (p, "neutral", 7) == 0) {
5222                                 assembly->culture = "";
5223                                 p += 7;
5224                         } else {
5225                                 assembly->culture = p;
5226                                 while (*p && *p != ',') {
5227                                         p++;
5228                                 }
5229                         }
5230                 } else if (*p == 'P' && strncmp (p, "PublicKeyToken=", 15) == 0) {
5231                         p += 15;
5232                         s = p;
5233                         while (*s && isxdigit (*s)) {
5234                                 *s = tolower (*s);
5235                                 s++;
5236                         }
5237                         assembly->hash_len = s - p;
5238                         if (!(s-p) || ((s-p) & 1))
5239                                 return 1;
5240                         assembly->hash_value = s = p;
5241                         while (*s && isxdigit (*s)) {
5242                                 int val;
5243                                 val = *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5244                                 s++;
5245                                 *p = val << 4;
5246                                 *p |= *s >= '0' && *s <= '9'? *s - '0': *s - 'a' + 10;
5247                                 p++;
5248                         }
5249                         p = s;
5250                 } else {
5251                         while (*p && *p != ',')
5252                                 p++;
5253                 }
5254                 found_sep = 0;
5255                 while (*p == ' ' || *p == ',') {
5256                         *p++ = 0;
5257                         found_sep = 1;
5258                         continue;
5259                 }
5260                 /* failed */
5261                 if (!found_sep)
5262                         return 1;
5263         }
5264
5265         return 0;
5266 }
5267
5268 /*
5269  * mono_reflection_parse_type:
5270  * @name: type name
5271  *
5272  * Parse a type name as accepted by the GetType () method and output the info
5273  * extracted in the info structure.
5274  * the name param will be mangled, so, make a copy before passing it to this function.
5275  * The fields in info will be valid until the memory pointed to by name is valid.
5276  * Returns 0 on parse error.
5277  * See also mono_type_get_name () below.
5278  */
5279 int
5280 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
5281
5282         char *start, *p, *w, *last_point, *startn;
5283         int in_modifiers = 0;
5284         int isbyref = 0, rank;
5285
5286         start = p = w = name;
5287
5288         memset (&info->assembly, 0, sizeof (MonoAssemblyName));
5289         info->name = info->name_space = NULL;
5290         info->nested = NULL;
5291         info->modifiers = NULL;
5292
5293         /* last_point separates the namespace from the name */
5294         last_point = NULL;
5295
5296         while (*p) {
5297                 switch (*p) {
5298                 case '+':
5299                         *p = 0; /* NULL terminate the name */
5300                         startn = p + 1;
5301                         info->nested = g_list_append (info->nested, startn);
5302                         /* we have parsed the nesting namespace + name */
5303                         if (info->name)
5304                                 break;
5305                         if (last_point) {
5306                                 info->name_space = start;
5307                                 *last_point = 0;
5308                                 info->name = last_point + 1;
5309                         } else {
5310                                 info->name_space = (char *)"";
5311                                 info->name = start;
5312                         }
5313                         break;
5314                 case '.':
5315                         last_point = w;
5316                         break;
5317                 case '\\':
5318                         ++p;
5319                         break;
5320                 case '&':
5321                 case '*':
5322                 case '[':
5323                 case ',':
5324                         in_modifiers = 1;
5325                         break;
5326                 default:
5327                         break;
5328                 }
5329                 if (in_modifiers)
5330                         break;
5331                 *w++ = *p++;
5332         }
5333         
5334         if (!info->name) {
5335                 if (last_point) {
5336                         info->name_space = start;
5337                         *last_point = 0;
5338                         info->name = last_point + 1;
5339                 } else {
5340                         info->name_space = (char *)"";
5341                         info->name = start;
5342                 }
5343         }
5344         while (*p) {
5345                 switch (*p) {
5346                 case '&':
5347                         if (isbyref) /* only one level allowed by the spec */
5348                                 return 0;
5349                         isbyref = 1;
5350                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
5351                         *p++ = 0;
5352                         break;
5353                 case '*':
5354                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
5355                         *p++ = 0;
5356                         break;
5357                 case '[':
5358                         rank = 1;
5359                         *p++ = 0;
5360                         while (*p) {
5361                                 if (*p == ']')
5362                                         break;
5363                                 if (*p == ',')
5364                                         rank++;
5365                                 else if (*p != '*') /* '*' means unknown lower bound */
5366                                         return 0;
5367                                 ++p;
5368                         }
5369                         if (*p++ != ']')
5370                                 return 0;
5371                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
5372                         break;
5373                 case ',':
5374                         *p++ = 0;
5375                         while (*p) {
5376                                 if (*p == ' ') {
5377                                         ++p;
5378                                         continue;
5379                                 }
5380                                 break;
5381                         }
5382                         if (!*p)
5383                                 return 0; /* missing assembly name */
5384                         if (!assembly_name_to_aname (&info->assembly, p))
5385                                 return 0;
5386                         break;
5387                 default:
5388                         return 0;
5389                         break;
5390                 }
5391                 if (info->assembly.name)
5392                         break;
5393         }
5394         *w = 0; /* terminate class name */
5395         if (!info->name || !*info->name)
5396                 return 0;
5397         /* add other consistency checks */
5398         return 1;
5399 }
5400
5401 static MonoType*
5402 mono_reflection_get_type_internal (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5403 {
5404         MonoClass *klass;
5405         GList *mod;
5406         int modval;
5407         
5408         if (!image)
5409                 image = mono_defaults.corlib;
5410
5411         if (ignorecase)
5412                 klass = mono_class_from_name_case (image, info->name_space, info->name);
5413         else
5414                 klass = mono_class_from_name (image, info->name_space, info->name);
5415         if (!klass)
5416                 return NULL;
5417         for (mod = info->nested; mod; mod = mod->next) {
5418                 GList *nested;
5419
5420                 mono_class_init (klass);
5421                 nested = klass->nested_classes;
5422                 klass = NULL;
5423                 while (nested) {
5424                         klass = nested->data;
5425                         if (ignorecase) {
5426                                 if (g_strcasecmp (klass->name, mod->data) == 0)
5427                                         break;
5428                         } else {
5429                                 if (strcmp (klass->name, mod->data) == 0)
5430                                         break;
5431                         }
5432                         klass = NULL;
5433                         nested = nested->next;
5434                 }
5435                 if (!klass)
5436                         break;
5437         }
5438         if (!klass)
5439                 return NULL;
5440         mono_class_init (klass);
5441         for (mod = info->modifiers; mod; mod = mod->next) {
5442                 modval = GPOINTER_TO_UINT (mod->data);
5443                 if (!modval) { /* byref: must be last modifier */
5444                         return &klass->this_arg;
5445                 } else if (modval == -1) {
5446                         klass = mono_ptr_class_get (&klass->byval_arg);
5447                 } else { /* array rank */
5448                         klass = mono_array_class_get (klass, modval);
5449                 }
5450                 mono_class_init (klass);
5451         }
5452
5453         return &klass->byval_arg;
5454 }
5455
5456 /*
5457  * mono_reflection_get_type:
5458  * @image: a metadata context
5459  * @info: type description structure
5460  * @ignorecase: flag for case-insensitive string compares
5461  *
5462  * Build a MonoType from the type description in @info.
5463  * 
5464  */
5465
5466 MonoType*
5467 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
5468 {
5469         MonoType *type;
5470         MonoReflectionAssembly *assembly;
5471         GString *fullName;
5472         GList *mod;
5473
5474         type = mono_reflection_get_type_internal (image, info, ignorecase);
5475         if (type)
5476                 return type;
5477         if (!mono_domain_has_type_resolve (mono_domain_get ()))
5478                 return NULL;
5479         
5480         // Reconstruct the type name
5481         fullName = g_string_new ("");
5482         if (info->name_space && (info->name_space [0] != '\0'))
5483                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5484         else
5485                 g_string_printf (fullName, info->name);
5486         for (mod = info->nested; mod; mod = mod->next)
5487                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5488
5489         assembly = 
5490                 mono_domain_try_type_resolve (
5491                         mono_domain_get (), fullName->str, NULL);
5492         if (assembly && (!image || (assembly->assembly->image == image)))
5493                 type = mono_reflection_get_type_internal (assembly->assembly->image, 
5494                                                                                  info, ignorecase);
5495         g_string_free (fullName, TRUE);
5496         return type;
5497 }
5498
5499 /*
5500  * mono_reflection_type_from_name:
5501  * @name: type name.
5502  * @image: a metadata context (can be NULL).
5503  *
5504  * Retrieves a MonoType from its @name. If the name is not fully qualified,
5505  * it defaults to get the type from @image or, if @image is NULL or loading
5506  * from it fails, uses corlib.
5507  * 
5508  */
5509 MonoType*
5510 mono_reflection_type_from_name (char *name, MonoImage *image)
5511 {
5512         MonoType *type;
5513         MonoTypeNameParse info;
5514         MonoAssembly *assembly;
5515         
5516         /*g_print ("requested type %s\n", str);*/
5517         if (!mono_reflection_parse_type (name, &info)) {
5518                 g_list_free (info.modifiers);
5519                 g_list_free (info.nested);
5520                 return NULL;
5521         }
5522
5523         if (info.assembly.name) {
5524                 assembly = mono_assembly_loaded (&info.assembly);
5525                 /* do we need to load if it's not already loaded? */
5526                 if (!assembly) {
5527                         g_list_free (info.modifiers);
5528                         g_list_free (info.nested);
5529                         return NULL;
5530                 }
5531                 else
5532                         image = assembly->image;
5533         } else if (image == NULL) {
5534                 image = mono_defaults.corlib;
5535         }
5536
5537         type = mono_reflection_get_type (image, &info, FALSE);
5538         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5539                 image = mono_defaults.corlib;
5540                 type = mono_reflection_get_type (image, &info, FALSE);
5541         }
5542         
5543         g_list_free (info.modifiers);
5544         g_list_free (info.nested);
5545         return type;
5546 }
5547
5548 static void*
5549 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5550 {
5551         int slen, type = t->type;
5552 handle_enum:
5553         switch (type) {
5554         case MONO_TYPE_U1:
5555         case MONO_TYPE_I1:
5556         case MONO_TYPE_BOOLEAN: {
5557                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5558                 *bval = *p;
5559                 *end = p + 1;
5560                 return bval;
5561         }
5562         case MONO_TYPE_CHAR:
5563         case MONO_TYPE_U2:
5564         case MONO_TYPE_I2: {
5565                 guint16 *val = g_malloc (sizeof (guint16));
5566                 *val = read16 (p);
5567                 *end = p + 2;
5568                 return val;
5569         }
5570 #if SIZEOF_VOID_P == 4
5571         case MONO_TYPE_U:
5572         case MONO_TYPE_I:
5573 #endif
5574         case MONO_TYPE_R4:
5575         case MONO_TYPE_U4:
5576         case MONO_TYPE_I4: {
5577                 guint32 *val = g_malloc (sizeof (guint32));
5578                 *val = read32 (p);
5579                 *end = p + 4;
5580                 return val;
5581         }
5582 #if SIZEOF_VOID_P == 8
5583         case MONO_TYPE_U: /* error out instead? this should probably not happen */
5584         case MONO_TYPE_I:
5585 #endif
5586         case MONO_TYPE_R8:
5587         case MONO_TYPE_U8:
5588         case MONO_TYPE_I8: {
5589                 guint64 *val = g_malloc (sizeof (guint64));
5590                 *val = read64 (p);
5591                 *end = p + 8;
5592                 return val;
5593         }
5594         case MONO_TYPE_VALUETYPE:
5595                 if (t->data.klass->enumtype) {
5596                         type = t->data.klass->enum_basetype->type;
5597                         goto handle_enum;
5598                 } else {
5599                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5600                 }
5601                 break;
5602         case MONO_TYPE_STRING:
5603                 if (*p == (char)0xFF) {
5604                         *end = p + 1;
5605                         return NULL;
5606                 }
5607                 slen = mono_metadata_decode_value (p, &p);
5608                 *end = p + slen;
5609                 return mono_string_new_len (mono_domain_get (), p, slen);
5610         case MONO_TYPE_CLASS: {
5611                 char *n;
5612                 MonoType *t;
5613                 if (*p == (char)0xFF) {
5614                         *end = p + 1;
5615                         return NULL;
5616                 }
5617 handle_type:
5618                 slen = mono_metadata_decode_value (p, &p);
5619                 n = g_memdup (p, slen + 1);
5620                 n [slen] = 0;
5621                 t = mono_reflection_type_from_name (n, image);
5622                 if (!t)
5623                         g_warning ("Cannot load type '%s'", n);
5624                 g_free (n);
5625                 *end = p + slen;
5626                 if (t)
5627                         return mono_type_get_object (mono_domain_get (), t);
5628                 else
5629                         return NULL;
5630         }
5631         case MONO_TYPE_OBJECT: {
5632                 char subt = *p++;
5633                 MonoObject *obj;
5634                 MonoClass *subc = NULL;
5635                 void *val;
5636
5637                 if (subt == 0x50) {
5638                         goto handle_type;
5639                 } else if (subt == 0x0E) {
5640                         type = MONO_TYPE_STRING;
5641                         goto handle_enum;
5642                 } else if (subt == 0x55) {
5643                         char *n;
5644                         MonoType *t;
5645                         slen = mono_metadata_decode_value (p, &p);
5646                         n = g_memdup (p, slen + 1);
5647                         n [slen] = 0;
5648                         t = mono_reflection_type_from_name (n, image);
5649                         if (!t)
5650                                 g_warning ("Cannot load type '%s'", n);
5651                         g_free (n);
5652                         p += slen;
5653                         subc = mono_class_from_mono_type (t);
5654                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5655                         MonoType simple_type = {{0}};
5656                         simple_type.type = subt;
5657                         subc = mono_class_from_mono_type (&simple_type);
5658                 } else {
5659                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5660                 }
5661                 val = load_cattr_value (image, &subc->byval_arg, p, end);
5662                 obj = mono_object_new (mono_domain_get (), subc);
5663                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5664                 g_free (val);
5665                 return obj;
5666         }
5667         case MONO_TYPE_SZARRAY:
5668         {
5669                 MonoArray *arr;
5670                 guint32 i, alen, basetype;
5671                 alen = read32 (p);
5672                 p += 4;
5673                 if (alen == 0xffffffff) {
5674                         *end = p;
5675                         return NULL;
5676                 }
5677                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5678                 basetype = t->data.klass->byval_arg.type;
5679                 switch (basetype)
5680                 {
5681                         case MONO_TYPE_U1:
5682                         case MONO_TYPE_I1:
5683                         case MONO_TYPE_BOOLEAN:
5684                                 for (i=0;i<alen;i++)
5685                                 {
5686                                         MonoBoolean val=*p++;
5687                                         mono_array_set(arr,MonoBoolean,i,val);
5688                                 }
5689                                 break;
5690                         case MONO_TYPE_CHAR:
5691                         case MONO_TYPE_U2:
5692                         case MONO_TYPE_I2:
5693                                 for (i=0;i<alen;i++)
5694                                 {
5695                                         guint16 val=read16(p);
5696                                         mono_array_set(arr,guint16,i,val);
5697                                         p+=2;
5698                                 }
5699                                 break;
5700                         case MONO_TYPE_R4:
5701                         case MONO_TYPE_U4:
5702                         case MONO_TYPE_I4:
5703                                 for (i=0;i<alen;i++)
5704                                 {
5705                                         guint32 val=read32(p);
5706                                         mono_array_set(arr,guint32,i,val);
5707                                         p+=4;
5708                                 }
5709                                 break;
5710                         case MONO_TYPE_R8:
5711                         case MONO_TYPE_U8:
5712                         case MONO_TYPE_I8:
5713                                 for (i=0;i<alen;i++)
5714                                 {
5715                                         guint64 val=read64(p);
5716                                         mono_array_set(arr,guint64,i,val);
5717                                         p+=8;
5718                                 }
5719                                 break;
5720                         case MONO_TYPE_CLASS:
5721                         case MONO_TYPE_STRING:
5722                                 for (i = 0; i < alen; i++) {
5723                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5724                                         mono_array_set (arr, gpointer, i, item);
5725                                 }
5726                                 break;
5727                         default:
5728                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5729                 }
5730                 *end=p;
5731                 return arr;
5732         }
5733         default:
5734                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5735         }
5736         return NULL;
5737 }
5738
5739 static gboolean
5740 type_is_reference (MonoType *type)
5741 {
5742         switch (type->type) {
5743         case MONO_TYPE_BOOLEAN:
5744         case MONO_TYPE_CHAR:
5745         case MONO_TYPE_U:
5746         case MONO_TYPE_I:
5747         case MONO_TYPE_U1:
5748         case MONO_TYPE_I1:
5749         case MONO_TYPE_U2:
5750         case MONO_TYPE_I2:
5751         case MONO_TYPE_U4:
5752         case MONO_TYPE_I4:
5753         case MONO_TYPE_U8:
5754         case MONO_TYPE_I8:
5755         case MONO_TYPE_R8:
5756         case MONO_TYPE_R4:
5757         case MONO_TYPE_VALUETYPE:
5758                 return FALSE;
5759         default:
5760                 return TRUE;
5761         }
5762 }
5763
5764 static void
5765 free_param_data (MonoMethodSignature *sig, void **params) {
5766         int i;
5767         for (i = 0; i < sig->param_count; ++i) {
5768                 if (!type_is_reference (sig->params [i]))
5769                         g_free (params [i]);
5770         }
5771 }
5772
5773 /*
5774  * Find the method index in the metadata methodDef table.
5775  * Later put these three helper methods in metadata and export them.
5776  */
5777 static guint32
5778 find_method_index (MonoMethod *method) {
5779         MonoClass *klass = method->klass;
5780         int i;
5781
5782         for (i = 0; i < klass->method.count; ++i) {
5783                 if (method == klass->methods [i])
5784                         return klass->method.first + 1 + i;
5785         }
5786         return 0;
5787 }
5788
5789 /*
5790  * Find the field index in the metadata FieldDef table.
5791  */
5792 static guint32
5793 find_field_index (MonoClass *klass, MonoClassField *field) {
5794         int i;
5795
5796         for (i = 0; i < klass->field.count; ++i) {
5797                 if (field == &klass->fields [i])
5798                         return klass->field.first + 1 + i;
5799         }
5800         return 0;
5801 }
5802
5803 /*
5804  * Find the property index in the metadata Property table.
5805  */
5806 static guint32
5807 find_property_index (MonoClass *klass, MonoProperty *property) {
5808         int i;
5809
5810         for (i = 0; i < klass->property.count; ++i) {
5811                 if (property == &klass->properties [i])
5812                         return klass->property.first + 1 + i;
5813         }
5814         return 0;
5815 }
5816
5817 /*
5818  * Find the event index in the metadata Event table.
5819  */
5820 static guint32
5821 find_event_index (MonoClass *klass, MonoEvent *event) {
5822         int i;
5823
5824         for (i = 0; i < klass->event.count; ++i) {
5825                 if (event == &klass->events [i])
5826                         return klass->event.first + 1 + i;
5827         }
5828         return 0;
5829 }
5830
5831 static MonoObject*
5832 create_custom_attr (MonoImage *image, MonoMethod *method, 
5833                                         const char *data, guint32 len)
5834 {
5835         const char *p = data;
5836         const char *named;
5837         guint32 i, j, num_named;
5838         MonoObject *attr;
5839         void **params;
5840
5841         mono_class_init (method->klass);
5842
5843         if (len == 0) {
5844                 attr = mono_object_new (mono_domain_get (), method->klass);
5845                 mono_runtime_invoke (method, attr, NULL, NULL);
5846                 return attr;
5847         }
5848
5849         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
5850                 return NULL;
5851
5852         /*g_print ("got attr %s\n", method->klass->name);*/
5853         
5854         params = g_new (void*, method->signature->param_count);
5855
5856         /* skip prolog */
5857         p += 2;
5858         for (i = 0; i < method->signature->param_count; ++i) {
5859                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
5860         }
5861
5862         named = p;
5863         attr = mono_object_new (mono_domain_get (), method->klass);
5864         mono_runtime_invoke (method, attr, params, NULL);
5865         free_param_data (method->signature, params);
5866         g_free (params);
5867         num_named = read16 (named);
5868         named += 2;
5869         for (j = 0; j < num_named; j++) {
5870                 gint name_len;
5871                 char *name, named_type, data_type;
5872                 named_type = *named++;
5873                 data_type = *named++; /* type of data */
5874                 if (data_type == 0x55) {
5875                         gint type_len;
5876                         char *type_name;
5877                         type_len = mono_metadata_decode_blob_size (named, &named);
5878                         type_name = g_malloc (type_len + 1);
5879                         memcpy (type_name, named, type_len);
5880                         type_name [type_len] = 0;
5881                         named += type_len;
5882                         /* FIXME: lookup the type and check type consistency */
5883                 }
5884                 else
5885                         if (data_type == MONO_TYPE_SZARRAY)
5886                                 /* The spec does not mention this */
5887                                 named ++;
5888                 name_len = mono_metadata_decode_blob_size (named, &named);
5889                 name = g_malloc (name_len + 1);
5890                 memcpy (name, named, name_len);
5891                 name [name_len] = 0;
5892                 named += name_len;
5893                 if (named_type == 0x53) {
5894                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
5895                         void *val = load_cattr_value (image, field->type, named, &named);
5896                                 mono_field_set_value (attr, field, val);
5897                                 if (!type_is_reference (field->type))
5898                                         g_free (val);
5899                 } else if (named_type == 0x54) {
5900                         MonoProperty *prop;
5901                         void *pparams [1];
5902                         MonoType *prop_type;
5903
5904                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
5905                         /* can we have more that 1 arg in a custom attr named property? */
5906                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
5907                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
5908                         mono_property_set_value (prop, attr, pparams, NULL);
5909                         if (!type_is_reference (prop_type))
5910                                 g_free (pparams [0]);
5911                 }
5912                 g_free (name);
5913         }
5914
5915         return attr;
5916 }
5917
5918 MonoArray*
5919 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
5920 {
5921         MonoArray *result;
5922         MonoClass *klass;
5923         MonoObject *attr;
5924         int i;
5925
5926         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
5927         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
5928         for (i = 0; i < cinfo->num_attrs; ++i) {
5929                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
5930                 mono_array_set (result, gpointer, i, attr);
5931         }
5932         return result;
5933 }
5934
5935 MonoCustomAttrInfo*
5936 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
5937 {
5938         guint32 mtoken, i, len;
5939         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
5940         MonoTableInfo *ca;
5941         MonoCustomAttrInfo *ainfo;
5942         GList *tmp, *list = NULL;
5943         const char *data;
5944
5945         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
5946
5947         i = mono_metadata_custom_attrs_from_index (image, idx);
5948         if (!i)
5949                 return NULL;
5950         i --;
5951         while (i < ca->rows) {
5952                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
5953                         break;
5954                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
5955                 ++i;
5956         }
5957         len = g_list_length (list);
5958         if (!len)
5959                 return NULL;
5960         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
5961         ainfo->num_attrs = len;
5962         ainfo->image = image;
5963         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
5964                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
5965                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
5966                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
5967                 case CUSTOM_ATTR_TYPE_METHODDEF:
5968                         mtoken |= MONO_TOKEN_METHOD_DEF;
5969                         break;
5970                 case CUSTOM_ATTR_TYPE_MEMBERREF:
5971                         mtoken |= MONO_TOKEN_MEMBER_REF;
5972                         break;
5973                 default:
5974                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
5975                         break;
5976                 }
5977                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
5978                 if (!ainfo->attrs [i].ctor)
5979                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
5980                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
5981                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
5982                 ainfo->attrs [i].data = data;
5983         }
5984         g_list_free (list);
5985
5986         return ainfo;
5987 }
5988
5989 MonoCustomAttrInfo*
5990 mono_custom_attrs_from_method (MonoMethod *method)
5991 {
5992         MonoCustomAttrInfo *cinfo;
5993         guint32 idx;
5994         
5995         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
5996                 return cinfo;
5997         idx = find_method_index (method);
5998         idx <<= CUSTOM_ATTR_BITS;
5999         idx |= CUSTOM_ATTR_METHODDEF;
6000         return mono_custom_attrs_from_index (method->klass->image, idx);
6001 }
6002
6003 MonoCustomAttrInfo*
6004 mono_custom_attrs_from_class (MonoClass *klass)
6005 {
6006         MonoCustomAttrInfo *cinfo;
6007         guint32 idx;
6008         
6009         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6010                 return cinfo;
6011         idx = mono_metadata_token_index (klass->type_token);
6012         idx <<= CUSTOM_ATTR_BITS;
6013         idx |= CUSTOM_ATTR_TYPEDEF;
6014         return mono_custom_attrs_from_index (klass->image, idx);
6015 }
6016
6017 MonoCustomAttrInfo*
6018 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6019 {
6020         MonoCustomAttrInfo *cinfo;
6021         guint32 idx;
6022         
6023         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6024                 return cinfo;
6025         idx = 1; /* there is only one assembly */
6026         idx <<= CUSTOM_ATTR_BITS;
6027         idx |= CUSTOM_ATTR_ASSEMBLY;
6028         return mono_custom_attrs_from_index (assembly->image, idx);
6029 }
6030
6031 static MonoCustomAttrInfo*
6032 mono_custom_attrs_from_module (MonoImage *image)
6033 {
6034         MonoCustomAttrInfo *cinfo;
6035         guint32 idx;
6036         
6037         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6038                 return cinfo;
6039         idx = 1; /* there is only one module */
6040         idx <<= CUSTOM_ATTR_BITS;
6041         idx |= CUSTOM_ATTR_MODULE;
6042         return mono_custom_attrs_from_index (image, idx);
6043 }
6044
6045 MonoCustomAttrInfo*
6046 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6047 {
6048         MonoCustomAttrInfo *cinfo;
6049         guint32 idx;
6050         
6051         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6052                 return cinfo;
6053         idx = find_property_index (klass, property);
6054         idx <<= CUSTOM_ATTR_BITS;
6055         idx |= CUSTOM_ATTR_PROPERTY;
6056         return mono_custom_attrs_from_index (klass->image, idx);
6057 }
6058
6059 MonoCustomAttrInfo*
6060 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6061 {
6062         MonoCustomAttrInfo *cinfo;
6063         guint32 idx;
6064         
6065         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6066                 return cinfo;
6067         idx = find_event_index (klass, event);
6068         idx <<= CUSTOM_ATTR_BITS;
6069         idx |= CUSTOM_ATTR_EVENT;
6070         return mono_custom_attrs_from_index (klass->image, idx);
6071 }
6072
6073 MonoCustomAttrInfo*
6074 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6075 {
6076         MonoCustomAttrInfo *cinfo;
6077         guint32 idx;
6078         
6079         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6080                 return cinfo;
6081         idx = find_field_index (klass, field);
6082         idx <<= CUSTOM_ATTR_BITS;
6083         idx |= CUSTOM_ATTR_FIELDDEF;
6084         return mono_custom_attrs_from_index (klass->image, idx);
6085 }
6086
6087 MonoCustomAttrInfo*
6088 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6089 {
6090         MonoTableInfo *ca;
6091         guint32 i, idx, method_index;
6092         guint32 param_list, param_last, param_pos, found;
6093         MonoImage *image;
6094         MonoReflectionMethodAux *aux;
6095
6096         if (method->klass->image->dynamic) {
6097                 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6098                 if (!aux || !aux->param_cattr)
6099                         return NULL;
6100                 return aux->param_cattr [param];
6101         }
6102
6103         image = method->klass->image;
6104         method_index = find_method_index (method);
6105         ca = &image->tables [MONO_TABLE_METHOD];
6106
6107         if (method->klass->generic_inst || method->klass->gen_params ||
6108             method->signature->generic_param_count) {
6109                 // FIXME FIXME FIXME
6110                 return NULL;
6111         }
6112
6113         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6114         if (method_index == ca->rows) {
6115                 ca = &image->tables [MONO_TABLE_PARAM];
6116                 param_last = ca->rows + 1;
6117         } else {
6118                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6119                 ca = &image->tables [MONO_TABLE_PARAM];
6120         }
6121         found = FALSE;
6122         for (i = param_list; i < param_last; ++i) {
6123                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6124                 if (param_pos == param) {
6125                         found = TRUE;
6126                         break;
6127                 }
6128         }
6129         if (!found)
6130                 return NULL;
6131         idx = i;
6132         idx <<= CUSTOM_ATTR_BITS;
6133         idx |= CUSTOM_ATTR_PARAMDEF;
6134         return mono_custom_attrs_from_index (image, idx);
6135 }
6136
6137 /*
6138  * mono_reflection_get_custom_attrs:
6139  * @obj: a reflection object handle
6140  *
6141  * Return an array with all the custom attributes defined of the
6142  * reflection handle @obj. The objects are fully build.
6143  */
6144 MonoArray*
6145 mono_reflection_get_custom_attrs (MonoObject *obj)
6146 {
6147         MonoClass *klass;
6148         MonoArray *result;
6149         MonoCustomAttrInfo *cinfo = NULL;
6150         
6151         MONO_ARCH_SAVE_REGS;
6152
6153         klass = obj->vtable->klass;
6154         /* FIXME: need to handle: Module */
6155         if (klass == mono_defaults.monotype_class) {
6156                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6157                 klass = mono_class_from_mono_type (rtype->type);
6158                 cinfo = mono_custom_attrs_from_class (klass);
6159         } else if (strcmp ("Assembly", klass->name) == 0) {
6160                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6161                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6162         } else if (strcmp ("Module", klass->name) == 0) {
6163                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6164                 cinfo = mono_custom_attrs_from_module (module->image);
6165         } else if (strcmp ("MonoProperty", klass->name) == 0) {
6166                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6167                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6168         } else if (strcmp ("MonoEvent", klass->name) == 0) {
6169                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6170                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6171         } else if (strcmp ("MonoField", klass->name) == 0) {
6172                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6173                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6174         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6175                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6176                 cinfo = mono_custom_attrs_from_method (rmethod->method);
6177         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6178                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6179                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6180                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6181         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6182                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6183                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6184         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6185                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6186                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6187         } else { /* handle other types here... */
6188                 g_error ("get custom attrs not yet supported for %s", klass->name);
6189         }
6190
6191         if (cinfo) {
6192                 result = mono_custom_attrs_construct (cinfo);
6193         } else {
6194                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6195                 result = mono_array_new (mono_domain_get (), klass, 0);
6196         }
6197
6198         return result;
6199 }
6200
6201 static MonoMethodSignature*
6202 parameters_to_signature (MonoArray *parameters) {
6203         MonoMethodSignature *sig;
6204         int count, i;
6205
6206         count = parameters? mono_array_length (parameters): 0;
6207
6208         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6209         sig->param_count = count;
6210         sig->sentinelpos = -1; /* FIXME */
6211         for (i = 0; i < count; ++i) {
6212                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6213                 sig->params [i] = pt->type;
6214         }
6215         return sig;
6216 }
6217
6218 static MonoMethodSignature*
6219 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6220         MonoMethodSignature *sig;
6221
6222         sig = parameters_to_signature (ctor->parameters);
6223         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6224         sig->ret = &mono_defaults.void_class->byval_arg;
6225         return sig;
6226 }
6227
6228 static MonoMethodSignature*
6229 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6230         MonoMethodSignature *sig;
6231
6232         sig = parameters_to_signature (method->parameters);
6233         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6234         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6235         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6236         return sig;
6237 }
6238
6239 static MonoMethodSignature*
6240 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6241         MonoMethodSignature *sig;
6242
6243         sig = parameters_to_signature (method->parameters);
6244         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6245         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6246         sig->generic_param_count = 0;
6247         return sig;
6248 }
6249
6250 static void
6251 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6252 {
6253         MonoClass *klass = mono_object_class (prop);
6254         if (strcmp (klass->name, "PropertyBuilder") == 0) {
6255                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6256                 *name = mono_string_to_utf8 (pb->name);
6257                 *type = pb->type->type;
6258         } else {
6259                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6260                 *name = g_strdup (p->property->name);
6261                 if (p->property->get)
6262                         *type = p->property->get->signature->ret;
6263                 else
6264                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6265         }
6266 }
6267
6268 static void
6269 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6270 {
6271         MonoClass *klass = mono_object_class (field);
6272         if (strcmp (klass->name, "FieldBuilder") == 0) {
6273                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6274                 *name = mono_string_to_utf8 (fb->name);
6275                 *type = fb->type->type;
6276         } else {
6277                 MonoReflectionField *f = (MonoReflectionField *)field;
6278                 *name = g_strdup (f->field->name);
6279                 *type = f->field->type;
6280         }
6281 }
6282
6283 static void
6284 encode_cattr_value (char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg)
6285 {
6286         char *argval;
6287         MonoTypeEnum simple_type;
6288         
6289         if ((p-buffer) + 10 >= *buflen) {
6290                 char *newbuf;
6291                 *buflen *= 2;
6292                 newbuf = g_realloc (buffer, *buflen);
6293                 p = newbuf + (p-buffer);
6294                 buffer = newbuf;
6295         }
6296         argval = ((char*)arg + sizeof (MonoObject));
6297         simple_type = type->type;
6298 handle_enum:
6299         switch (simple_type) {
6300         case MONO_TYPE_BOOLEAN:
6301         case MONO_TYPE_U1:
6302         case MONO_TYPE_I1:
6303                 *p++ = *argval;
6304                 break;
6305         case MONO_TYPE_CHAR:
6306         case MONO_TYPE_U2:
6307         case MONO_TYPE_I2:
6308                 swap_with_size (p, argval, 2, 1);
6309                 p += 2;
6310                 break;
6311         case MONO_TYPE_U4:
6312         case MONO_TYPE_I4:
6313         case MONO_TYPE_R4:
6314                 swap_with_size (p, argval, 4, 1);
6315                 p += 4;
6316                 break;
6317         case MONO_TYPE_U8:
6318         case MONO_TYPE_I8:
6319         case MONO_TYPE_R8:
6320                 swap_with_size (p, argval, 8, 1);
6321                 p += 8;
6322                 break;
6323         case MONO_TYPE_VALUETYPE:
6324                 if (type->data.klass->enumtype) {
6325                         simple_type = type->data.klass->enum_basetype->type;
6326                         goto handle_enum;
6327                 } else {
6328                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6329                 }
6330                 break;
6331         case MONO_TYPE_STRING: {
6332                 char *str;
6333                 guint32 slen;
6334                 if (!arg) {
6335                         *p++ = 0xFF;
6336                         break;
6337                 }
6338                 str = mono_string_to_utf8 ((MonoString*)arg);
6339                 slen = strlen (str);
6340                 if ((p-buffer) + 10 + slen >= *buflen) {
6341                         char *newbuf;
6342                         *buflen *= 2;
6343                         *buflen += slen;
6344                         newbuf = g_realloc (buffer, *buflen);
6345                         p = newbuf + (p-buffer);
6346                         buffer = newbuf;
6347                 }
6348                 mono_metadata_encode_value (slen, p, &p);
6349                 memcpy (p, str, slen);
6350                 p += slen;
6351                 g_free (str);
6352                 break;
6353         }
6354         case MONO_TYPE_CLASS: {
6355                 char *str;
6356                 guint32 slen;
6357                 MonoClass *k;
6358                 if (!arg) {
6359                         *p++ = 0xFF;
6360                         break;
6361                 }
6362                 k = mono_object_class (arg);
6363                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6364                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6365                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6366 handle_type:
6367                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6368                 slen = strlen (str);
6369                 if ((p-buffer) + 10 + slen >= *buflen) {
6370                         char *newbuf;
6371                         *buflen *= 2;
6372                         *buflen += slen;
6373                         newbuf = g_realloc (buffer, *buflen);
6374                         p = newbuf + (p-buffer);
6375                         buffer = newbuf;
6376                 }
6377                 mono_metadata_encode_value (slen, p, &p);
6378                 memcpy (p, str, slen);
6379                 p += slen;
6380                 g_free (str);
6381                 break;
6382         }
6383         case MONO_TYPE_SZARRAY: {
6384                 int len, i;
6385                 MonoClass *eclass;
6386
6387                 if (!arg) {
6388                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6389                         break;
6390                 }
6391                 len = mono_array_length ((MonoArray*)arg);
6392                 *p++ = len & 0xff;
6393                 *p++ = (len >> 8) & 0xff;
6394                 *p++ = (len >> 16) & 0xff;
6395                 *p++ = (len >> 24) & 0xff;
6396                 *retp = p;
6397                 *retbuffer = buffer;
6398                 eclass = type->data.klass;
6399                 for (i = 0; i < len; ++i) {
6400                         encode_cattr_value (buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i));
6401                 }
6402                 break;
6403         }
6404         /* it may be a boxed value or a Type */
6405         case MONO_TYPE_OBJECT: {
6406                 MonoClass *klass = mono_object_class (arg);
6407                 char *str;
6408                 guint32 slen;
6409                 
6410                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6411                         *p++ = 0x50;
6412                         goto handle_type;
6413                 } else if (klass->enumtype) {
6414                         *p++ = 0x55;
6415                 } else if (klass == mono_defaults.string_class) {
6416                         simple_type = MONO_TYPE_STRING;
6417                         *p++ = 0x0E;
6418                         goto handle_enum;
6419                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6420                         *p++ = simple_type = klass->byval_arg.type;
6421                         goto handle_enum;
6422                 } else {
6423                         g_error ("unhandled type in custom attr");
6424                 }
6425                 str = type_get_qualified_name (klass->enum_basetype, NULL);
6426                 slen = strlen (str);
6427                 if ((p-buffer) + 10 + slen >= *buflen) {
6428                         char *newbuf;
6429                         *buflen *= 2;
6430                         *buflen += slen;
6431                         newbuf = g_realloc (buffer, *buflen);
6432                         p = newbuf + (p-buffer);
6433                         buffer = newbuf;
6434                 }
6435                 mono_metadata_encode_value (slen, p, &p);
6436                 memcpy (p, str, slen);
6437                 p += slen;
6438                 g_free (str);
6439                 simple_type = klass->enum_basetype->type;
6440                 goto handle_enum;
6441         }
6442         default:
6443                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6444         }
6445         *retp = p;
6446         *retbuffer = buffer;
6447 }
6448
6449 /*
6450  * mono_reflection_get_custom_attrs_blob:
6451  * @ctor: custom attribute constructor
6452  * @ctorArgs: arguments o the constructor
6453  * @properties:
6454  * @propValues:
6455  * @fields:
6456  * @fieldValues:
6457  * 
6458  * Creates the blob of data that needs to be saved in the metadata and that represents
6459  * the custom attributed described by @ctor, @ctorArgs etc.
6460  * Returns: a Byte array representing the blob of data.
6461  */
6462 MonoArray*
6463 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
6464 {
6465         MonoArray *result;
6466         MonoMethodSignature *sig;
6467         MonoObject *arg;
6468         char *buffer, *p;
6469         guint32 buflen, i;
6470
6471         MONO_ARCH_SAVE_REGS;
6472
6473         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6474                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6475         } else {
6476                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6477         }
6478         g_assert (mono_array_length (ctorArgs) == sig->param_count);
6479         buflen = 256;
6480         p = buffer = g_malloc (buflen);
6481         /* write the prolog */
6482         *p++ = 1;
6483         *p++ = 0;
6484         for (i = 0; i < sig->param_count; ++i) {
6485                 arg = mono_array_get (ctorArgs, MonoObject*, i);
6486                 encode_cattr_value (buffer, p, &buffer, &p, &buflen, sig->params [i], arg);
6487         }
6488         i = 0;
6489         if (properties)
6490                 i += mono_array_length (properties);
6491         if (fields)
6492                 i += mono_array_length (fields);
6493         *p++ = i & 0xff;
6494         *p++ = (i >> 8) & 0xff;
6495         if (properties) {
6496                 MonoObject *prop;
6497                 for (i = 0; i < mono_array_length (properties); ++i) {
6498                         MonoType *ptype;
6499                         char *pname;
6500                         int len;
6501                         
6502                         prop = mono_array_get (properties, gpointer, i);
6503                         get_prop_name_and_type (prop, &pname, &ptype);
6504                         *p++ = 0x54; /* PROPERTY signature */
6505
6506                         /* Preallocate a large enough buffer */
6507                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6508                                 char *str = type_get_qualified_name (ptype, NULL);
6509                                 len = strlen (str);
6510                                 g_free (str);
6511                         }
6512                         else
6513                                 len = 0;
6514                         len += strlen (pname);
6515
6516                         if ((p-buffer) + 20 + len >= buflen) {
6517                                 char *newbuf;
6518                                 buflen *= 2;
6519                                 buflen += len;
6520                                 newbuf = g_realloc (buffer, buflen);
6521                                 p = newbuf + (p-buffer);
6522                                 buffer = newbuf;
6523                         }
6524
6525                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6526                                 char *str = type_get_qualified_name (ptype, NULL);
6527                                 int slen = strlen (str);
6528
6529                                 *p++ = 0x55;
6530                                 /*
6531                                  * This seems to be optional...
6532                                  * *p++ = 0x80;
6533                                  */
6534                                 mono_metadata_encode_value (slen, p, &p);
6535                                 memcpy (p, str, slen);
6536                                 p += slen;
6537                                 g_free (str);
6538                         } else {
6539                                 mono_metadata_encode_value (ptype->type, p, &p);
6540                                 if (ptype->type == MONO_TYPE_SZARRAY)
6541                                         mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6542                         }
6543                         len = strlen (pname);
6544                         mono_metadata_encode_value (len, p, &p);
6545                         memcpy (p, pname, len);
6546                         p += len;
6547                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i));
6548                         g_free (pname);
6549                 }
6550         }
6551
6552         if (fields) {
6553                 MonoObject *field;
6554                 for (i = 0; i < mono_array_length (fields); ++i) {
6555                         MonoType *ftype;
6556                         char *fname;
6557                         int len;
6558                         
6559                         field = mono_array_get (fields, gpointer, i);
6560                         get_field_name_and_type (field, &fname, &ftype);
6561                         *p++ = 0x53; /* FIELD signature */
6562                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6563                                 char *str = type_get_qualified_name (ftype, NULL);
6564                                 int slen = strlen (str);
6565                                 if ((p-buffer) + 10 + slen >= buflen) {
6566                                         char *newbuf;
6567                                         buflen *= 2;
6568                                         buflen += slen;
6569                                         newbuf = g_realloc (buffer, buflen);
6570                                         p = newbuf + (p-buffer);
6571                                         buffer = newbuf;
6572                                 }
6573                                 *p++ = 0x55;
6574                                 /*
6575                                  * This seems to be optional...
6576                                  * *p++ = 0x80;
6577                                  */
6578                                 mono_metadata_encode_value (slen, p, &p);
6579                                 memcpy (p, str, slen);
6580                                 p += slen;
6581                                 g_free (str);
6582                         } else {
6583                                 mono_metadata_encode_value (ftype->type, p, &p);
6584                         }
6585                         len = strlen (fname);
6586                         mono_metadata_encode_value (len, p, &p);
6587                         memcpy (p, fname, len);
6588                         p += len;
6589                         encode_cattr_value (buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
6590                         g_free (fname);
6591                 }
6592         }
6593
6594         g_assert (p - buffer <= buflen);
6595         buflen = p - buffer;
6596         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6597         p = mono_array_addr (result, char, 0);
6598         memcpy (p, buffer, buflen);
6599         g_free (buffer);
6600         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6601                 g_free (sig);
6602         return result;
6603 }
6604
6605 /*
6606  * mono_reflection_setup_internal_class:
6607  * @tb: a TypeBuilder object
6608  *
6609  * Creates a MonoClass that represents the TypeBuilder.
6610  * This is a trick that lets us simplify a lot of reflection code
6611  * (and will allow us to support Build and Run assemblies easier).
6612  */
6613 void
6614 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6615 {
6616         MonoClass *klass, *parent;
6617
6618         MONO_ARCH_SAVE_REGS;
6619
6620         klass = g_new0 (MonoClass, 1);
6621
6622         klass->image = &tb->module->dynamic_image->image;
6623
6624         if (tb->parent) {
6625                 /* check so we can compile corlib correctly */
6626                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6627                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6628                         parent = tb->parent->type->data.klass;
6629                 } else 
6630                         parent = my_mono_class_from_mono_type (tb->parent->type);
6631         } else
6632                 parent = NULL;
6633         
6634         klass->inited = 1; /* we lie to the runtime */
6635         klass->name = mono_string_to_utf8 (tb->name);
6636         klass->name_space = mono_string_to_utf8 (tb->nspace);
6637         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6638         klass->flags = tb->attrs;
6639
6640         klass->element_class = klass;
6641         klass->reflection_info = tb; /* need to pin. */
6642
6643         /* Put into cache so mono_class_get () will find it */
6644         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6645                                                                   tb->table_idx);
6646
6647         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6648                                                           GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6649                                                           tb);
6650
6651         if (parent != NULL)
6652                 mono_class_setup_parent (klass, parent);
6653         else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6654                 const char *old_n = klass->name;
6655                 /* trick to get relative numbering right when compiling corlib */
6656                 klass->name = "BuildingObject";
6657                 mono_class_setup_parent (klass, mono_defaults.object_class);
6658                 klass->name = old_n;
6659         }
6660         mono_class_setup_mono_type (klass);
6661
6662         mono_class_setup_supertypes (klass);
6663
6664         /*
6665          * FIXME: handle interfaces.
6666          */
6667
6668         tb->type.type = &klass->byval_arg;
6669
6670         if (tb->nesting_type) {
6671                 g_assert (tb->nesting_type->type);
6672                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6673         }
6674
6675         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6676 }
6677
6678 /*
6679  * mono_reflection_setup_generic_class:
6680  * @tb: a TypeBuilder object
6681  *
6682  * Setup the generic class after all generic parameters have been added.
6683  */
6684 void
6685 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6686 {
6687         MonoClass *klass;
6688         int count, i;
6689
6690         MONO_ARCH_SAVE_REGS;
6691
6692         klass = my_mono_class_from_mono_type (tb->type.type);
6693
6694         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6695
6696         if (klass->gen_params || (count == 0))
6697                 return;
6698
6699         klass->num_gen_params = count;
6700         klass->gen_params = g_new0 (MonoGenericParam, count);
6701
6702         for (i = 0; i < count; i++) {
6703                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6704                 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6705         }
6706 }
6707
6708 /*
6709  * mono_reflection_create_internal_class:
6710  * @tb: a TypeBuilder object
6711  *
6712  * Actually create the MonoClass that is associated with the TypeBuilder.
6713  */
6714 void
6715 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6716 {
6717         MonoClass *klass;
6718
6719         MONO_ARCH_SAVE_REGS;
6720
6721         klass = my_mono_class_from_mono_type (tb->type.type);
6722
6723         if (klass->enumtype && klass->enum_basetype == NULL) {
6724                 MonoReflectionFieldBuilder *fb;
6725
6726                 g_assert (tb->fields != NULL);
6727                 g_assert (mono_array_length (tb->fields) >= 1);
6728
6729                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
6730
6731                 klass->enum_basetype = fb->type->type;
6732                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
6733                 if (!klass->element_class)
6734                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
6735                 klass->instance_size = klass->element_class->instance_size;
6736                 klass->size_inited = 1;
6737                 /* 
6738                  * this is almost safe to do with enums and it's needed to be able
6739                  * to create objects of the enum type (for use in SetConstant).
6740                  */
6741                 /* FIXME: Does this mean enums can't have method overrides ? */
6742                 mono_class_setup_vtable (klass, NULL, 0);
6743         }
6744 }
6745
6746 static MonoMarshalSpec*
6747 mono_marshal_spec_from_builder (MonoAssembly *assembly,
6748                                                                 MonoReflectionMarshal *minfo)
6749 {
6750         MonoMarshalSpec *res;
6751
6752         res = g_new0 (MonoMarshalSpec, 1);
6753         res->native = minfo->type;
6754
6755         switch (minfo->type) {
6756         case MONO_NATIVE_LPARRAY:
6757                 res->data.array_data.elem_type = minfo->eltype;
6758                 res->data.array_data.param_num = 0; /* Not yet */
6759                 res->data.array_data.num_elem = minfo->count;
6760                 break;
6761
6762         case MONO_NATIVE_BYVALTSTR:
6763         case MONO_NATIVE_BYVALARRAY:
6764                 res->data.array_data.num_elem = minfo->count;
6765                 break;
6766
6767         case MONO_NATIVE_CUSTOM:
6768                 if (minfo->marshaltyperef)
6769                         res->data.custom_data.custom_name =
6770                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
6771                 if (minfo->mcookie)
6772                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
6773                 break;
6774
6775         default:
6776                 break;
6777         }
6778
6779         return res;
6780 }
6781
6782 static MonoMethod*
6783 reflection_methodbuilder_to_mono_method (MonoClass *klass,
6784                                          ReflectionMethodBuilder *rmb,
6785                                          MonoMethodSignature *sig)
6786 {
6787         MonoMethod *m;
6788         MonoMethodNormal *pm;
6789         MonoMarshalSpec **specs;
6790         MonoReflectionMethodAux *method_aux;
6791         int i;
6792
6793         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6794             (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
6795                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
6796         else 
6797                 if (rmb->refs)
6798                         m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
6799         else
6800                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
6801
6802         pm = (MonoMethodNormal*)m;
6803
6804         m->slot = -1;
6805         m->flags = rmb->attrs;
6806         m->iflags = rmb->iattrs;
6807         m->name = mono_string_to_utf8 (rmb->name);
6808         m->klass = klass;
6809         m->signature = sig;
6810         if (rmb->table_idx)
6811                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
6812
6813         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
6814                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
6815                         m->string_ctor = 1;
6816
6817                 m->signature->pinvoke = 1;
6818         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
6819                 /* TODO */
6820                 m->signature->pinvoke = 1;
6821                 return m;
6822         } else if (!m->klass->dummy && 
6823                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
6824                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
6825                 MonoMethodHeader *header;
6826                 guint32 code_size;
6827                 gint32 max_stack, i;
6828                 gint32 num_locals = 0;
6829                 gint32 num_clauses = 0;
6830                 guint8 *code;
6831
6832                 if (rmb->ilgen) {
6833                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
6834                         code_size = rmb->ilgen->code_len;
6835                         max_stack = rmb->ilgen->max_stack;
6836                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
6837                         if (rmb->ilgen->ex_handlers)
6838                                 num_clauses = method_count_clauses (rmb->ilgen);
6839                 } else {
6840                         if (rmb->code) {
6841                                 code = mono_array_addr (rmb->code, guint8, 0);
6842                                 code_size = mono_array_length (rmb->code);
6843                                 /* we probably need to run a verifier on the code... */
6844                                 max_stack = 8; 
6845                         }
6846                         else {
6847                                 code = NULL;
6848                                 code_size = 0;
6849                                 max_stack = 8;
6850                         }
6851                 }
6852
6853                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
6854                                                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
6855                 header->code_size = code_size;
6856                 header->code = g_malloc (code_size);
6857                 memcpy ((char*)header->code, code, code_size);
6858                 header->max_stack = max_stack;
6859                 header->init_locals = rmb->init_locals;
6860                 header->num_locals = num_locals;
6861
6862                 for (i = 0; i < num_locals; ++i) {
6863                         MonoReflectionLocalBuilder *lb = 
6864                                 mono_array_get (rmb->ilgen->locals, 
6865                                                                 MonoReflectionLocalBuilder*, i);
6866
6867                         header->locals [i] = g_new0 (MonoType, 1);
6868                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
6869                 }
6870
6871                 header->num_clauses = num_clauses;
6872                 if (num_clauses) {
6873                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
6874                                                                  rmb->ilgen,
6875                                                                  num_clauses);
6876                 }
6877
6878                 if (rmb->generic_params) {
6879                         int count = mono_array_length (rmb->generic_params);
6880                         header->gen_params = g_new0 (MonoGenericParam, count);
6881                         for (i = 0; i < count; i++) {
6882                                 MonoReflectionGenericParam *gp =
6883                                         mono_array_get (rmb->generic_params,
6884                                                         MonoReflectionGenericParam*, i);
6885
6886                                 header->gen_params [i] = *gp->type.type->data.generic_param;
6887                         }
6888                 }
6889
6890                 pm->header = header;
6891         }
6892
6893         if (rmb->refs) {
6894                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
6895                 int i;
6896
6897                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
6898
6899                 for (i = 0; i < rmb->nrefs; ++i)
6900                         mw->data = g_list_append (mw->data, rmb->refs [i]);
6901         }
6902
6903         method_aux = NULL;
6904
6905         /* Parameter names */
6906         if (rmb->pinfo) {
6907                 if (!method_aux)
6908                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
6909                 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
6910                 for (i = 0; i <= m->signature->param_count; ++i) {
6911                         MonoReflectionParamBuilder *pb;
6912                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6913                                 if (pb->name)
6914                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
6915                                 if (pb->cattrs) {
6916                                         if (!method_aux->param_cattr)
6917                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
6918                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
6919                                 }
6920                         }
6921                 }
6922         }
6923
6924         /* Parameter marshalling */
6925         specs = NULL;
6926         if (rmb->pinfo)         
6927                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
6928                         MonoReflectionParamBuilder *pb;
6929                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
6930                                 if (pb->marshal_info) {
6931                                         if (specs == NULL)
6932                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
6933                                         specs [pb->position] = 
6934                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
6935                                 }
6936                         }
6937                 }
6938         if (specs != NULL) {
6939                 if (!method_aux)
6940                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
6941                 method_aux->param_marshall = specs;
6942         }
6943
6944         if (klass->image->dynamic && method_aux)
6945                 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
6946
6947         return m;
6948 }       
6949
6950 static MonoMethod*
6951 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
6952 {
6953         ReflectionMethodBuilder rmb;
6954         MonoMethodSignature *sig;
6955
6956         sig = ctor_builder_to_signature (mb);
6957
6958         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
6959
6960         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6961         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6962
6963         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6964                 /* ilgen is no longer needed */
6965                 mb->ilgen = NULL;
6966         }
6967
6968         return mb->mhandle;
6969 }
6970
6971 static MonoMethod*
6972 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
6973 {
6974         ReflectionMethodBuilder rmb;
6975         MonoMethodSignature *sig;
6976
6977         sig = method_builder_to_signature (mb);
6978
6979         reflection_methodbuilder_from_method_builder (&rmb, mb);
6980
6981         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
6982         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
6983
6984         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
6985                 /* ilgen is no longer needed */
6986                 mb->ilgen = NULL;
6987         }
6988         return mb->mhandle;
6989 }
6990
6991 static MonoClassField*
6992 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
6993 {
6994         MonoClassField *field;
6995         const char *p, *p2;
6996         guint32 len, idx;
6997
6998         if (fb->handle)
6999                 return fb->handle;
7000
7001         field = g_new0 (MonoClassField, 1);
7002
7003         field->name = mono_string_to_utf8 (fb->name);
7004         if (fb->attrs) {
7005                 /* FIXME: handle type modifiers */
7006                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7007                 field->type->attrs = fb->attrs;
7008         } else {
7009                 field->type = fb->type->type;
7010         }
7011         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7012                 field->data = mono_array_addr (fb->rva_data, char, 0);
7013         if (fb->offset != -1)
7014                 field->offset = fb->offset;
7015         field->parent = klass;
7016         fb->handle = field;
7017         mono_save_custom_attrs (klass->image, field, fb->cattrs);
7018
7019         if (fb->def_value) {
7020                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7021                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7022                 field->def_value = g_new0 (MonoConstant, 1);
7023                 idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7024                 /* Copy the data from the blob since it might get realloc-ed */
7025                 p = assembly->blob.data + idx;
7026                 len = mono_metadata_decode_blob_size (p, &p2);
7027                 len += p2 - p;
7028                 field->def_value->value = g_malloc (len);
7029                 memcpy (field->def_value->value, p, len);
7030         }
7031
7032         return field;
7033 }
7034
7035 static MonoType*
7036 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7037                                             MonoType **types)
7038 {
7039         MonoClass *klass;
7040         MonoReflectionTypeBuilder *tb = NULL;
7041         MonoGenericInst *ginst;
7042         MonoDomain *domain;
7043         MonoType *geninst;
7044         int icount, i;
7045
7046         klass = mono_class_from_mono_type (type->type);
7047         if (!klass->gen_params && !klass->generic_inst &&
7048             !(klass->nested_in && klass->nested_in->gen_params))
7049                 return NULL;
7050
7051         mono_loader_lock ();
7052
7053         domain = mono_object_domain (type);
7054
7055         ginst = g_new0 (MonoGenericInst, 1);
7056
7057         if (!klass->generic_inst) {
7058                 ginst->type_argc = type_argc;
7059                 ginst->type_argv = types;
7060
7061                 for (i = 0; i < ginst->type_argc; ++i) {
7062                         if (!ginst->is_open)
7063                                 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7064                 }
7065
7066                 ginst->generic_type = &klass->byval_arg;
7067         } else {
7068                 MonoGenericInst *kginst = klass->generic_inst;
7069
7070                 ginst->type_argc = kginst->type_argc;
7071                 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7072
7073                 for (i = 0; i < ginst->type_argc; i++) {
7074                         MonoType *t = kginst->type_argv [i];
7075
7076                         if (t->type == MONO_TYPE_VAR)
7077                                 t = types [t->data.generic_param->num];
7078
7079                         if (!ginst->is_open)
7080                                 ginst->is_open = mono_class_is_open_constructed_type (t);
7081
7082                         ginst->type_argv [i] = t;
7083                 }
7084
7085                 ginst->generic_type = kginst->generic_type;
7086         }
7087
7088         geninst = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7089         if (geninst) {
7090                 g_free (ginst);
7091                 mono_loader_unlock ();
7092                 return geninst;
7093         }
7094
7095         ginst->context = g_new0 (MonoGenericContext, 1);
7096         ginst->context->ginst = ginst;
7097
7098         geninst = g_new0 (MonoType, 1);
7099         geninst->type = MONO_TYPE_GENERICINST;
7100         geninst->data.generic_inst = ginst;
7101
7102         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7103                 tb = (MonoReflectionTypeBuilder *) type;
7104
7105                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7106                 ginst->is_dynamic = TRUE;
7107         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7108                 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7109                 MonoReflectionType *rgt = rgi->generic_type;
7110
7111                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7112                 tb = (MonoReflectionTypeBuilder *) rgt;
7113
7114                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7115                 ginst->is_dynamic = TRUE;
7116         } else
7117                 icount = klass->interface_count;
7118
7119         ginst->ifaces = g_new0 (MonoType *, icount);
7120         ginst->count_ifaces = icount;
7121
7122         for (i = 0; i < icount; i++) {
7123                 MonoReflectionType *itype;
7124
7125                 if (tb)
7126                         itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7127                 else
7128                         itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7129                 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7130                 if (!ginst->ifaces [i])
7131                         ginst->ifaces [i] = itype->type;
7132         }
7133
7134         mono_class_create_generic (ginst);
7135
7136         g_hash_table_insert (klass->image->generic_inst_cache, ginst, geninst);
7137
7138         mono_loader_unlock ();
7139
7140         return geninst;
7141 }
7142
7143 MonoType*
7144 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7145 {
7146         MonoClass *klass, *pklass = NULL;
7147         MonoReflectionType *parent = NULL;
7148         MonoType *geninst;
7149         MonoReflectionTypeBuilder *tb = NULL;
7150         MonoGenericInst *ginst;
7151         MonoDomain *domain;
7152
7153         domain = mono_object_domain (type);
7154         klass = mono_class_from_mono_type (type->type);
7155
7156         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7157                 tb = (MonoReflectionTypeBuilder *) type;
7158
7159                 if (tb->parent) {
7160                         parent = tb->parent;
7161                         pklass = mono_class_from_mono_type (parent->type);
7162                 }
7163         } else {
7164                 pklass = klass->parent;
7165                 if (pklass)
7166                         parent = mono_type_get_object (domain, &pklass->byval_arg);
7167         }
7168
7169         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7170         if (!geninst)
7171                 return NULL;
7172
7173         ginst = geninst->data.generic_inst;
7174
7175         if (pklass && pklass->generic_inst)
7176                 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7177
7178         return geninst;
7179 }
7180
7181 MonoReflectionMethod*
7182 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7183 {
7184         MonoMethod *method, *inflated;
7185         MonoReflectionMethodBuilder *mb = NULL;
7186         MonoGenericMethod *gmethod;
7187         MonoGenericContext *context;
7188         int count, i;
7189
7190         MONO_ARCH_SAVE_REGS;
7191         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7192                 MonoReflectionTypeBuilder *tb;
7193                 MonoClass *klass;
7194
7195                 mb = (MonoReflectionMethodBuilder *) rmethod;
7196                 tb = (MonoReflectionTypeBuilder *) mb->type;
7197                 klass = mono_class_from_mono_type (tb->type.type);
7198
7199                 method = methodbuilder_to_mono_method (klass, mb);
7200         } else
7201                 method = rmethod->method;
7202
7203         count = method->signature->generic_param_count;
7204         if (count != mono_array_length (types))
7205                 return NULL;
7206
7207         gmethod = g_new0 (MonoGenericMethod, 1);
7208         gmethod->mtype_argc = count;
7209         gmethod->mtype_argv = g_new0 (MonoType *, count);
7210         for (i = 0; i < count; i++) {
7211                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7212                 gmethod->mtype_argv [i] = garg->type;
7213         }
7214
7215         context = g_new0 (MonoGenericContext, 1);
7216         context->ginst = method->klass->generic_inst;
7217         context->gmethod = gmethod;
7218
7219         inflated = mono_class_inflate_generic_method (method, context, NULL);
7220
7221         return mono_method_get_object (
7222                 mono_object_domain (rmethod), inflated, NULL);
7223 }
7224
7225 static MonoMethod *
7226 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7227 {
7228         MonoGenericMethod *gmethod;
7229         MonoGenericInst *ginst;
7230         MonoGenericContext *context;
7231         int i;
7232
7233         ginst = type->type.type->data.generic_inst;
7234
7235         gmethod = g_new0 (MonoGenericMethod, 1);
7236         gmethod->reflection_info = obj;
7237
7238         gmethod->mtype_argc = method->signature->generic_param_count;
7239         gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7240
7241         for (i = 0; i < gmethod->mtype_argc; i++) {
7242                 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7243                 MonoGenericParam *gparam = &mn->header->gen_params [i];
7244
7245                 g_assert (gparam->pklass);
7246                 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7247         }
7248
7249         context = g_new0 (MonoGenericContext, 1);
7250         context->ginst = ginst;
7251         context->gmethod = gmethod;
7252
7253         return mono_class_inflate_generic_method (method, context, ginst->klass);
7254 }
7255
7256 static MonoMethod *
7257 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7258 {
7259         MonoMethod *method;
7260         MonoClass *klass;
7261
7262         klass = mono_class_from_mono_type (type->type.type);
7263
7264         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7265                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7266         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7267                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7268         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7269                  !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7270                 method = ((MonoReflectionMethod *) obj)->method;
7271         else {
7272                 method = NULL; /* prevent compiler warning */
7273                 g_assert_not_reached ();
7274         }
7275
7276         return inflate_mono_method (type, method, obj);
7277 }
7278
7279 void
7280 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7281                                          MonoArray *methods, MonoArray *ctors,
7282                                          MonoArray *fields, MonoArray *properties,
7283                                          MonoArray *events)
7284 {
7285         MonoGenericInst *ginst;
7286         MonoDynamicGenericInst *dginst;
7287         MonoClass *klass, *gklass, *pklass;
7288         int i;
7289
7290         MONO_ARCH_SAVE_REGS;
7291
7292         klass = mono_class_from_mono_type (type->type.type);
7293         ginst = type->type.type->data.generic_inst;
7294
7295         if (ginst->initialized)
7296                 return;
7297
7298         dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7299
7300         gklass = mono_class_from_mono_type (ginst->generic_type);
7301         mono_class_init (gklass);
7302
7303         if (ginst->parent)
7304                 pklass = mono_class_from_mono_type (ginst->parent);
7305         else
7306                 pklass = gklass->parent;
7307
7308         mono_class_setup_parent (klass, pklass);
7309
7310         dginst->count_methods = methods ? mono_array_length (methods) : 0;
7311         dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7312         dginst->count_fields = fields ? mono_array_length (fields) : 0;
7313         dginst->count_properties = properties ? mono_array_length (properties) : 0;
7314         dginst->count_events = events ? mono_array_length (events) : 0;
7315
7316         dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7317         dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7318         dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7319         dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7320         dginst->events = g_new0 (MonoEvent, dginst->count_events);
7321
7322         for (i = 0; i < dginst->count_methods; i++) {
7323                 MonoObject *obj = mono_array_get (methods, gpointer, i);
7324
7325                 dginst->methods [i] = inflate_method (type, obj);
7326         }
7327
7328         for (i = 0; i < dginst->count_ctors; i++) {
7329                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7330
7331                 dginst->ctors [i] = inflate_method (type, obj);
7332         }
7333
7334         for (i = 0; i < dginst->count_fields; i++) {
7335                 MonoObject *obj = mono_array_get (fields, gpointer, i);
7336                 MonoClassField *field;
7337
7338                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7339                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7340                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7341                         field = ((MonoReflectionField *) obj)->field;
7342                 else {
7343                         field = NULL; /* prevent compiler warning */
7344                         g_assert_not_reached ();
7345                 }
7346
7347                 dginst->fields [i] = *field;
7348                 dginst->fields [i].generic_type = field->type;
7349                 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7350         }
7351
7352         for (i = 0; i < dginst->count_properties; i++) {
7353                 MonoObject *obj = mono_array_get (properties, gpointer, i);
7354                 MonoProperty *property = &dginst->properties [i];
7355
7356                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7357                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7358
7359                         property->parent = klass;
7360                         property->attrs = pb->attrs;
7361                         property->name = mono_string_to_utf8 (pb->name);
7362                         if (pb->get_method)
7363                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7364                         if (pb->set_method)
7365                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7366                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7367                         *property = *((MonoReflectionProperty *) obj)->property;
7368
7369                         if (property->get)
7370                                 property->get = inflate_mono_method (type, property->get, NULL);
7371                         if (property->set)
7372                                 property->set = inflate_mono_method (type, property->set, NULL);
7373                 } else
7374                         g_assert_not_reached ();
7375         }
7376
7377         for (i = 0; i < dginst->count_events; i++) {
7378                 MonoObject *obj = mono_array_get (events, gpointer, i);
7379                 MonoEvent *event = &dginst->events [i];
7380
7381                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7382                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7383
7384                         event->parent = klass;
7385                         event->attrs = eb->attrs;
7386                         event->name = mono_string_to_utf8 (eb->name);
7387                         if (eb->add_method)
7388                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7389                         if (eb->remove_method)
7390                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7391                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7392                         *event = *((MonoReflectionEvent *) obj)->event;
7393
7394                         if (event->add)
7395                                 event->add = inflate_mono_method (type, event->add, NULL);
7396                         if (event->remove)
7397                                 event->remove = inflate_mono_method (type, event->remove, NULL);
7398                 } else
7399                         g_assert_not_reached ();
7400         }
7401
7402         ginst->initialized = TRUE;
7403 }
7404
7405 static void
7406 ensure_runtime_vtable (MonoClass *klass)
7407 {
7408         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7409         int i, num, j, onum;
7410         MonoMethod **overrides;
7411
7412         if (!tb || klass->wastypebuilder)
7413                 return;
7414         if (klass->parent)
7415                 ensure_runtime_vtable (klass->parent);
7416
7417         num = tb->ctors? mono_array_length (tb->ctors): 0;
7418         num += tb->num_methods;
7419         klass->method.count = num;
7420         klass->methods = g_new (MonoMethod*, num);
7421         num = tb->ctors? mono_array_length (tb->ctors): 0;
7422         for (i = 0; i < num; ++i)
7423                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7424         num = tb->num_methods;
7425         j = i;
7426         for (i = 0; i < num; ++i)
7427                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7428
7429         klass->wastypebuilder = TRUE;
7430         if (tb->interfaces) {
7431                 klass->interface_count = mono_array_length (tb->interfaces);
7432                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7433                 for (i = 0; i < klass->interface_count; ++i) {
7434                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7435                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7436                 }
7437         }
7438
7439         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7440                 for (i = 0; i < klass->method.count; ++i)
7441                         klass->methods [i]->slot = i;
7442
7443         /* Overrides */
7444         onum = 0;
7445         if (tb->methods) {
7446                 for (i = 0; i < tb->num_methods; ++i) {
7447                         MonoReflectionMethodBuilder *mb = 
7448                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7449                         if (mb->override_method)
7450                                 onum ++;
7451                 }
7452         }
7453
7454         overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7455
7456         if (tb->methods) {
7457                 onum = 0;
7458                 for (i = 0; i < tb->num_methods; ++i) {
7459                         MonoReflectionMethodBuilder *mb = 
7460                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7461                         if (mb->override_method) {
7462                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7463                                 overrides [onum * 2] = 
7464                                         mb->override_method->method;
7465                                 overrides [onum * 2 + 1] =
7466                                         mb->mhandle;
7467
7468                                 g_assert (mb->mhandle);
7469
7470                                 onum ++;
7471                         }
7472                 }
7473         }
7474
7475         mono_class_setup_vtable (klass, overrides, onum);
7476 }
7477
7478 static void
7479 typebuilder_setup_fields (MonoClass *klass)
7480 {
7481         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7482         MonoReflectionFieldBuilder *fb;
7483         MonoClassField *field;
7484         const char *p, *p2;
7485         int i;
7486         guint32 len, idx;
7487
7488         klass->field.count = tb->num_fields;
7489         klass->field.first = 0;
7490         klass->field.last = klass->field.count;
7491
7492         if (!klass->field.count)
7493                 return;
7494         
7495         klass->fields = g_new0 (MonoClassField, klass->field.count);
7496
7497         for (i = 0; i < klass->field.count; ++i) {
7498                 fb = mono_array_get (tb->fields, gpointer, i);
7499                 field = &klass->fields [i];
7500                 field->name = mono_string_to_utf8 (fb->name);
7501                 if (fb->attrs) {
7502                         /* FIXME: handle type modifiers */
7503                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
7504                         field->type->attrs = fb->attrs;
7505                 } else {
7506                         field->type = fb->type->type;
7507                 }
7508                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7509                         field->data = mono_array_addr (fb->rva_data, char, 0);
7510                 if (fb->offset != -1)
7511                         field->offset = fb->offset;
7512                 field->parent = klass;
7513                 fb->handle = field;
7514                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7515
7516                 if (fb->def_value) {
7517                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7518                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7519                         field->def_value = g_new0 (MonoConstant, 1);
7520                         idx = encode_constant (assembly, fb->def_value, &field->def_value->type);
7521                         /* Copy the data from the blob since it might get realloc-ed */
7522                         p = assembly->blob.data + idx;
7523                         len = mono_metadata_decode_blob_size (p, &p2);
7524                         len += p2 - p;
7525                         field->def_value->value = g_malloc (len);
7526                         memcpy (field->def_value->value, p, len);
7527                 }
7528         }
7529         mono_class_layout_fields (klass);
7530 }
7531
7532 static void
7533 typebuilder_setup_properties (MonoClass *klass)
7534 {
7535         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7536         MonoReflectionPropertyBuilder *pb;
7537         int i;
7538
7539         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7540         klass->property.first = 0;
7541         klass->property.last = klass->property.count;
7542
7543         klass->properties = g_new0 (MonoProperty, klass->property.count);
7544         for (i = 0; i < klass->property.count; ++i) {
7545                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7546                 klass->properties [i].parent = klass;
7547                 klass->properties [i].attrs = pb->attrs;
7548                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7549                 if (pb->get_method)
7550                         klass->properties [i].get = pb->get_method->mhandle;
7551                 if (pb->set_method)
7552                         klass->properties [i].set = pb->set_method->mhandle;
7553         }
7554 }
7555
7556 MonoReflectionEvent *
7557 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7558 {
7559         MonoEvent *event = g_new0 (MonoEvent, 1);
7560         MonoClass *klass;
7561         int j;
7562
7563         klass = my_mono_class_from_mono_type (tb->type.type);
7564
7565         event->parent = klass;
7566         event->attrs = eb->attrs;
7567         event->name = mono_string_to_utf8 (eb->name);
7568         if (eb->add_method)
7569                 event->add = eb->add_method->mhandle;
7570         if (eb->remove_method)
7571                 event->remove = eb->remove_method->mhandle;
7572         if (eb->raise_method)
7573                 event->raise = eb->raise_method->mhandle;
7574
7575         if (eb->other_methods) {
7576                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7577                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7578                         MonoReflectionMethodBuilder *mb = 
7579                                 mono_array_get (eb->other_methods,
7580                                                 MonoReflectionMethodBuilder*, j);
7581                         event->other [j] = mb->mhandle;
7582                 }
7583         }
7584
7585         return mono_event_get_object (mono_object_domain (tb), klass, event);
7586 }
7587
7588 static void
7589 typebuilder_setup_events (MonoClass *klass)
7590 {
7591         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7592         MonoReflectionEventBuilder *eb;
7593         int i, j;
7594
7595         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7596         klass->event.first = 0;
7597         klass->event.last = klass->event.count;
7598
7599         klass->events = g_new0 (MonoEvent, klass->event.count);
7600         for (i = 0; i < klass->event.count; ++i) {
7601                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7602                 klass->events [i].parent = klass;
7603                 klass->events [i].attrs = eb->attrs;
7604                 klass->events [i].name = mono_string_to_utf8 (eb->name);
7605                 if (eb->add_method)
7606                         klass->events [i].add = eb->add_method->mhandle;
7607                 if (eb->remove_method)
7608                         klass->events [i].remove = eb->remove_method->mhandle;
7609                 if (eb->raise_method)
7610                         klass->events [i].raise = eb->raise_method->mhandle;
7611
7612                 if (eb->other_methods) {
7613                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7614                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7615                                 MonoReflectionMethodBuilder *mb = 
7616                                         mono_array_get (eb->other_methods,
7617                                                                         MonoReflectionMethodBuilder*, j);
7618                                 klass->events [i].other [j] = mb->mhandle;
7619                         }
7620                 }
7621         }
7622 }
7623
7624 MonoReflectionType*
7625 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7626 {
7627         MonoClass *klass;
7628         MonoReflectionType* res;
7629
7630         MONO_ARCH_SAVE_REGS;
7631
7632         klass = my_mono_class_from_mono_type (tb->type.type);
7633
7634         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7635
7636         /*
7637          * Fields to set in klass:
7638          * the various flags: delegate/unicode/contextbound etc.
7639          * nested_classes
7640          */
7641         klass->flags = tb->attrs;
7642
7643         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7644                 /* No need to fully construct the type */
7645                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7646
7647         /* enums are done right away */
7648         if (!klass->enumtype)
7649                 ensure_runtime_vtable (klass);
7650
7651         /* fields and object layout */
7652         if (klass->parent) {
7653                 if (!klass->parent->size_inited)
7654                         mono_class_init (klass->parent);
7655                 klass->instance_size += klass->parent->instance_size;
7656                 klass->class_size += klass->parent->class_size;
7657                 klass->min_align = klass->parent->min_align;
7658         } else {
7659                 klass->instance_size = sizeof (MonoObject);
7660                 klass->min_align = 1;
7661         }
7662
7663         /* FIXME: handle packing_size and instance_size */
7664         typebuilder_setup_fields (klass);
7665
7666         typebuilder_setup_properties (klass);
7667
7668         typebuilder_setup_events (klass);
7669
7670         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7671         /* with enums res == tb: need to fix that. */
7672         if (!klass->enumtype)
7673                 g_assert (res != (MonoReflectionType*)tb);
7674         return res;
7675 }
7676
7677 void
7678 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7679 {
7680         MonoGenericParam *param;
7681         MonoImage *image;
7682
7683         MONO_ARCH_SAVE_REGS;
7684
7685         param = g_new0 (MonoGenericParam, 1);
7686
7687         param->method = NULL;
7688         param->name = mono_string_to_utf8 (gparam->name);
7689         param->num = gparam->index;
7690
7691         image = &gparam->tbuilder->module->dynamic_image->image;
7692         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7693
7694         param->pklass->reflection_info = gparam;
7695
7696         gparam->type.type = g_new0 (MonoType, 1);
7697         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7698         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7699         gparam->type.type->data.generic_param = param;
7700 }
7701
7702 MonoArray *
7703 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7704 {
7705         MonoDynamicImage *assembly = sig->module->dynamic_image;
7706         guint32 na = mono_array_length (sig->arguments);
7707         guint32 buflen, i;
7708         MonoArray *result;
7709         char *buf, *p;
7710
7711         MONO_ARCH_SAVE_REGS;
7712
7713         p = buf = g_malloc (10 + na * 10);
7714
7715         mono_metadata_encode_value (0x07, p, &p);
7716         mono_metadata_encode_value (na, p, &p);
7717         for (i = 0; i < na; ++i) {
7718                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7719                 encode_reflection_type (assembly, type, p, &p);
7720         }
7721
7722         buflen = p - buf;
7723         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7724         p = mono_array_addr (result, char, 0);
7725         memcpy (p, buf, buflen);
7726         g_free (buf);
7727
7728         return result;
7729 }
7730
7731 MonoArray *
7732 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
7733 {
7734         MonoDynamicImage *assembly = sig->module->dynamic_image;
7735         guint32 na = mono_array_length (sig->arguments);
7736         guint32 buflen, i;
7737         MonoArray *result;
7738         char *buf, *p;
7739
7740         MONO_ARCH_SAVE_REGS;
7741
7742         p = buf = g_malloc (10 + na * 10);
7743
7744         mono_metadata_encode_value (0x06, p, &p);
7745         for (i = 0; i < na; ++i) {
7746                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
7747                 encode_reflection_type (assembly, type, p, &p);
7748         }
7749
7750         buflen = p - buf;
7751         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
7752         p = mono_array_addr (result, char, 0);
7753         memcpy (p, buf, buflen);
7754         g_free (buf);
7755
7756         return result;
7757 }
7758
7759 void 
7760 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
7761 {
7762         ReflectionMethodBuilder rmb;
7763         MonoMethodSignature *sig;
7764         int i;
7765
7766         sig = dynamic_method_to_signature (mb);
7767
7768         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
7769
7770         /*
7771          * Resolve references.
7772          */
7773         rmb.nrefs = mb->nrefs;
7774         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
7775         for (i = 0; i < mb->nrefs; ++i) {
7776                 gpointer ref = resolve_object (mb->module->image, 
7777                                                mono_array_get (mb->refs, MonoObject*, i));
7778                 if (!ref) {
7779                         g_free (rmb.refs);
7780                         mono_raise_exception (mono_get_exception_type_load (NULL));
7781                         return;
7782                 }
7783                 rmb.refs [i] = ref;
7784         }               
7785
7786         /* FIXME: class */
7787         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
7788
7789         g_free (rmb.refs);
7790
7791         /* ilgen is no longer needed */
7792         mb->ilgen = NULL;
7793 }
7794
7795 /**
7796  * mono_reflection_lookup_dynamic_token:
7797  *
7798  *  Finish the Builder object pointed to by TOKEN and return the corresponding
7799  * runtime structure.
7800  */
7801 gpointer
7802 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
7803 {
7804         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
7805         MonoObject *obj;
7806
7807         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
7808         g_assert (obj);
7809
7810         return resolve_object (image, obj);
7811 }
7812
7813 static gpointer
7814 resolve_object (MonoImage *image, MonoObject *obj)
7815 {
7816         gpointer result = NULL;
7817
7818         if (strcmp (obj->vtable->klass->name, "String") == 0) {
7819                 result = mono_string_intern ((MonoString*)obj);
7820                 g_assert (result);
7821         }
7822         else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
7823                 MonoReflectionType *tb = (MonoReflectionType*)obj;
7824                 result = mono_class_from_mono_type (tb->type);
7825                 g_assert (result);
7826         }
7827         else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
7828                 result = ((MonoReflectionMethod*)obj)->method;
7829                 g_assert (result);
7830         }
7831         else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
7832                 result = ((MonoReflectionMethod*)obj)->method;
7833                 g_assert (result);
7834         }
7835         else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
7836                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
7837                 result = mb->mhandle;
7838                 if (!result) {
7839                         /* Type is not yet created */
7840                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
7841
7842                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7843
7844                         /*
7845                          * Hopefully this has been filled in by calling CreateType() on the
7846                          * TypeBuilder.
7847                          */
7848                         /**
7849                          * TODO: This won't work if the application finishes another 
7850                          * TypeBuilder instance instead of this one.
7851                          */
7852                         result = mb->mhandle;
7853                 }
7854         }
7855         else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
7856                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
7857
7858                 result = cb->mhandle;
7859                 if (!result) {
7860                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
7861
7862                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7863                         result = cb->mhandle;
7864                 }
7865         }
7866         else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
7867                 result = ((MonoReflectionField*)obj)->field;
7868                 g_assert (result);
7869         }
7870         else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
7871                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
7872                 result = fb->handle;
7873
7874                 if (!result) {
7875                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
7876
7877                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7878                         result = fb->handle;
7879                 }
7880         }
7881         else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
7882                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
7883                 MonoClass *klass;
7884
7885                 klass = tb->type.type->data.klass;
7886                 if (klass->wastypebuilder) {
7887                         /* Already created */
7888                         result = klass;
7889                 }
7890                 else {
7891                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
7892                         result = tb->type.type->data.klass;
7893                         g_assert (result);
7894                 }
7895         }
7896         else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
7897                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
7898                 MonoMethodSignature *sig;
7899                 int nargs, i;
7900
7901                 if (helper->arguments)
7902                         nargs = mono_array_length (helper->arguments);
7903                 else
7904                         nargs = 0;
7905
7906                 sig = mono_metadata_signature_alloc (image, nargs);
7907                 sig->explicit_this = helper->call_conv & 64;
7908                 sig->hasthis = helper->call_conv & 32;
7909
7910                 if (helper->call_conv == 0) /* unmanaged */
7911                         sig->call_convention = helper->unmanaged_call_conv - 1;
7912                 else
7913                         if (helper->call_conv & 0x02)
7914                                 sig->call_convention = MONO_CALL_VARARG;
7915                 else
7916                         sig->call_convention = MONO_CALL_DEFAULT;
7917
7918                 sig->param_count = nargs;
7919                 /* TODO: Copy type ? */
7920                 sig->ret = helper->return_type->type;
7921                 for (i = 0; i < nargs; ++i) {
7922                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
7923                         sig->params [i] = rt->type;
7924                 }
7925
7926                 result = sig;
7927         }
7928         else {
7929                 g_print (obj->vtable->klass->name);
7930                 g_assert_not_reached ();
7931         }
7932         return result;
7933 }