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