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