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