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