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