2004-09-09 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  * @type_resolve: whenever type resolve was already tried
5651  *
5652  * Build a MonoType from the type description in @info.
5653  * 
5654  */
5655
5656 MonoType*
5657 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
5658 {
5659         MonoType *type;
5660         MonoReflectionAssembly *assembly;
5661         GString *fullName;
5662         GList *mod;
5663
5664         type = mono_reflection_get_type_internal (image, info, ignorecase);
5665         if (type)
5666                 return type;
5667         if (!mono_domain_has_type_resolve (mono_domain_get ()))
5668                 return NULL;
5669
5670         /* FIXME: Enabling this causes regressions (#65577) */
5671         /*
5672         if (type_resolve) {
5673                 if (*type_resolve) 
5674                         return NULL;
5675                 else
5676                         *type_resolve = TRUE;
5677         }
5678         */
5679         
5680         /* Reconstruct the type name */
5681         fullName = g_string_new ("");
5682         if (info->name_space && (info->name_space [0] != '\0'))
5683                 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
5684         else
5685                 g_string_printf (fullName, info->name);
5686         for (mod = info->nested; mod; mod = mod->next)
5687                 g_string_append_printf (fullName, "+%s", (char*)mod->data);
5688
5689         assembly = 
5690                 mono_domain_try_type_resolve (
5691                         mono_domain_get (), fullName->str, NULL);
5692         if (assembly && (!image || (assembly->assembly->image == image))) {
5693
5694                 if (assembly->assembly->dynamic) {
5695                         /* Enumerate all modules */
5696                         MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
5697                         int i;
5698
5699                         type = NULL;
5700                         if (abuilder->modules) {
5701                                 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
5702                                         MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
5703                                         type = mono_reflection_get_type_internal (&mb->dynamic_image->image, info, ignorecase);
5704                                         if (type)
5705                                                 break;
5706                                 }
5707                         }
5708
5709                         if (!type && abuilder->loaded_modules) {
5710                                 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
5711                                         MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
5712                                         type = mono_reflection_get_type_internal (mod->image, info, ignorecase);
5713                                         if (type)
5714                                                 break;
5715                                 }
5716                         }
5717                 }
5718                 else
5719                         type = mono_reflection_get_type_internal (assembly->assembly->image, 
5720                                                                                                           info, ignorecase);
5721         }
5722         g_string_free (fullName, TRUE);
5723         return type;
5724 }
5725
5726 /*
5727  * mono_reflection_type_from_name:
5728  * @name: type name.
5729  * @image: a metadata context (can be NULL).
5730  *
5731  * Retrieves a MonoType from its @name. If the name is not fully qualified,
5732  * it defaults to get the type from @image or, if @image is NULL or loading
5733  * from it fails, uses corlib.
5734  * 
5735  */
5736 MonoType*
5737 mono_reflection_type_from_name (char *name, MonoImage *image)
5738 {
5739         MonoType *type;
5740         MonoTypeNameParse info;
5741         MonoAssembly *assembly;
5742         char *tmp;
5743         gboolean type_resolve = FALSE;
5744
5745         /* Make a copy since parse_type modifies its argument */
5746         tmp = g_strdup (name);
5747         
5748         /*g_print ("requested type %s\n", str);*/
5749         if (!mono_reflection_parse_type (tmp, &info)) {
5750                 g_free (tmp);
5751                 g_list_free (info.modifiers);
5752                 g_list_free (info.nested);
5753                 return NULL;
5754         }
5755
5756         if (info.assembly.name) {
5757                 assembly = mono_assembly_loaded (&info.assembly);
5758                 if (!assembly) {
5759                         /* then we must load the assembly ourselve - see #60439 */
5760                         assembly = mono_assembly_load (&info.assembly, NULL, NULL);
5761                         if (!assembly) {
5762                                 g_free (tmp);
5763                                 g_list_free (info.modifiers);
5764                                 g_list_free (info.nested);
5765                                 return NULL;
5766                         }
5767                 }
5768                 image = assembly->image;
5769         } else if (image == NULL) {
5770                 image = mono_defaults.corlib;
5771         }
5772
5773         type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5774         if (type == NULL && !info.assembly.name && image != mono_defaults.corlib) {
5775                 image = mono_defaults.corlib;
5776                 type = mono_reflection_get_type (image, &info, FALSE, &type_resolve);
5777         }
5778
5779         g_free (tmp);
5780         g_list_free (info.modifiers);
5781         g_list_free (info.nested);
5782         return type;
5783 }
5784
5785 static void*
5786 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
5787 {
5788         int slen, type = t->type;
5789 handle_enum:
5790         switch (type) {
5791         case MONO_TYPE_U1:
5792         case MONO_TYPE_I1:
5793         case MONO_TYPE_BOOLEAN: {
5794                 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
5795                 *bval = *p;
5796                 *end = p + 1;
5797                 return bval;
5798         }
5799         case MONO_TYPE_CHAR:
5800         case MONO_TYPE_U2:
5801         case MONO_TYPE_I2: {
5802                 guint16 *val = g_malloc (sizeof (guint16));
5803                 *val = read16 (p);
5804                 *end = p + 2;
5805                 return val;
5806         }
5807 #if SIZEOF_VOID_P == 4
5808         case MONO_TYPE_U:
5809         case MONO_TYPE_I:
5810 #endif
5811         case MONO_TYPE_R4:
5812         case MONO_TYPE_U4:
5813         case MONO_TYPE_I4: {
5814                 guint32 *val = g_malloc (sizeof (guint32));
5815                 *val = read32 (p);
5816                 *end = p + 4;
5817                 return val;
5818         }
5819 #if SIZEOF_VOID_P == 8
5820         case MONO_TYPE_U: /* error out instead? this should probably not happen */
5821         case MONO_TYPE_I:
5822 #endif
5823         case MONO_TYPE_R8:
5824         case MONO_TYPE_U8:
5825         case MONO_TYPE_I8: {
5826                 guint64 *val = g_malloc (sizeof (guint64));
5827                 *val = read64 (p);
5828                 *end = p + 8;
5829                 return val;
5830         }
5831         case MONO_TYPE_VALUETYPE:
5832                 if (t->data.klass->enumtype) {
5833                         type = t->data.klass->enum_basetype->type;
5834                         goto handle_enum;
5835                 } else {
5836                         g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
5837                 }
5838                 break;
5839         case MONO_TYPE_STRING:
5840                 if (*p == (char)0xFF) {
5841                         *end = p + 1;
5842                         return NULL;
5843                 }
5844                 slen = mono_metadata_decode_value (p, &p);
5845                 *end = p + slen;
5846                 return mono_string_new_len (mono_domain_get (), p, slen);
5847         case MONO_TYPE_CLASS: {
5848                 char *n;
5849                 MonoType *t;
5850                 if (*p == (char)0xFF) {
5851                         *end = p + 1;
5852                         return NULL;
5853                 }
5854 handle_type:
5855                 slen = mono_metadata_decode_value (p, &p);
5856                 n = g_memdup (p, slen + 1);
5857                 n [slen] = 0;
5858                 t = mono_reflection_type_from_name (n, image);
5859                 if (!t)
5860                         g_warning ("Cannot load type '%s'", n);
5861                 g_free (n);
5862                 *end = p + slen;
5863                 if (t)
5864                         return mono_type_get_object (mono_domain_get (), t);
5865                 else
5866                         return NULL;
5867         }
5868         case MONO_TYPE_OBJECT: {
5869                 char subt = *p++;
5870                 MonoObject *obj;
5871                 MonoClass *subc = NULL;
5872                 void *val;
5873
5874                 if (subt == 0x50) {
5875                         goto handle_type;
5876                 } else if (subt == 0x0E) {
5877                         type = MONO_TYPE_STRING;
5878                         goto handle_enum;
5879                 } else if (subt == 0x55) {
5880                         char *n;
5881                         MonoType *t;
5882                         slen = mono_metadata_decode_value (p, &p);
5883                         n = g_memdup (p, slen + 1);
5884                         n [slen] = 0;
5885                         t = mono_reflection_type_from_name (n, image);
5886                         if (!t)
5887                                 g_warning ("Cannot load type '%s'", n);
5888                         g_free (n);
5889                         p += slen;
5890                         subc = mono_class_from_mono_type (t);
5891                 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
5892                         MonoType simple_type = {{0}};
5893                         simple_type.type = subt;
5894                         subc = mono_class_from_mono_type (&simple_type);
5895                 } else {
5896                         g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
5897                 }
5898                 val = load_cattr_value (image, &subc->byval_arg, p, end);
5899                 obj = mono_object_new (mono_domain_get (), subc);
5900                 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
5901                 g_free (val);
5902                 return obj;
5903         }
5904         case MONO_TYPE_SZARRAY:
5905         {
5906                 MonoArray *arr;
5907                 guint32 i, alen, basetype;
5908                 alen = read32 (p);
5909                 p += 4;
5910                 if (alen == 0xffffffff) {
5911                         *end = p;
5912                         return NULL;
5913                 }
5914                 arr = mono_array_new (mono_domain_get(), t->data.klass, alen);
5915                 basetype = t->data.klass->byval_arg.type;
5916                 switch (basetype)
5917                 {
5918                         case MONO_TYPE_U1:
5919                         case MONO_TYPE_I1:
5920                         case MONO_TYPE_BOOLEAN:
5921                                 for (i=0;i<alen;i++)
5922                                 {
5923                                         MonoBoolean val=*p++;
5924                                         mono_array_set(arr,MonoBoolean,i,val);
5925                                 }
5926                                 break;
5927                         case MONO_TYPE_CHAR:
5928                         case MONO_TYPE_U2:
5929                         case MONO_TYPE_I2:
5930                                 for (i=0;i<alen;i++)
5931                                 {
5932                                         guint16 val=read16(p);
5933                                         mono_array_set(arr,guint16,i,val);
5934                                         p+=2;
5935                                 }
5936                                 break;
5937                         case MONO_TYPE_R4:
5938                         case MONO_TYPE_U4:
5939                         case MONO_TYPE_I4:
5940                                 for (i=0;i<alen;i++)
5941                                 {
5942                                         guint32 val=read32(p);
5943                                         mono_array_set(arr,guint32,i,val);
5944                                         p+=4;
5945                                 }
5946                                 break;
5947                         case MONO_TYPE_R8:
5948                         case MONO_TYPE_U8:
5949                         case MONO_TYPE_I8:
5950                                 for (i=0;i<alen;i++)
5951                                 {
5952                                         guint64 val=read64(p);
5953                                         mono_array_set(arr,guint64,i,val);
5954                                         p+=8;
5955                                 }
5956                                 break;
5957                         case MONO_TYPE_CLASS:
5958                         case MONO_TYPE_OBJECT:
5959                         case MONO_TYPE_STRING:
5960                                 for (i = 0; i < alen; i++) {
5961                                         MonoObject *item = load_cattr_value (image, &t->data.klass->byval_arg, p, &p);
5962                                         mono_array_set (arr, gpointer, i, item);
5963                                 }
5964                                 break;
5965                         default:
5966                                 g_error("Type 0x%02x not handled in custom attr array decoding",t->data.type->type);
5967                 }
5968                 *end=p;
5969                 return arr;
5970         }
5971         default:
5972                 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
5973         }
5974         return NULL;
5975 }
5976
5977 static gboolean
5978 type_is_reference (MonoType *type)
5979 {
5980         switch (type->type) {
5981         case MONO_TYPE_BOOLEAN:
5982         case MONO_TYPE_CHAR:
5983         case MONO_TYPE_U:
5984         case MONO_TYPE_I:
5985         case MONO_TYPE_U1:
5986         case MONO_TYPE_I1:
5987         case MONO_TYPE_U2:
5988         case MONO_TYPE_I2:
5989         case MONO_TYPE_U4:
5990         case MONO_TYPE_I4:
5991         case MONO_TYPE_U8:
5992         case MONO_TYPE_I8:
5993         case MONO_TYPE_R8:
5994         case MONO_TYPE_R4:
5995         case MONO_TYPE_VALUETYPE:
5996                 return FALSE;
5997         default:
5998                 return TRUE;
5999         }
6000 }
6001
6002 static void
6003 free_param_data (MonoMethodSignature *sig, void **params) {
6004         int i;
6005         for (i = 0; i < sig->param_count; ++i) {
6006                 if (!type_is_reference (sig->params [i]))
6007                         g_free (params [i]);
6008         }
6009 }
6010
6011 /*
6012  * Find the method index in the metadata methodDef table.
6013  * Later put these three helper methods in metadata and export them.
6014  */
6015 static guint32
6016 find_method_index (MonoMethod *method) {
6017         MonoClass *klass = method->klass;
6018         int i;
6019
6020         for (i = 0; i < klass->method.count; ++i) {
6021                 if (method == klass->methods [i])
6022                         return klass->method.first + 1 + i;
6023         }
6024         return 0;
6025 }
6026
6027 /*
6028  * Find the field index in the metadata FieldDef table.
6029  */
6030 static guint32
6031 find_field_index (MonoClass *klass, MonoClassField *field) {
6032         int i;
6033
6034         for (i = 0; i < klass->field.count; ++i) {
6035                 if (field == &klass->fields [i])
6036                         return klass->field.first + 1 + i;
6037         }
6038         return 0;
6039 }
6040
6041 /*
6042  * Find the property index in the metadata Property table.
6043  */
6044 static guint32
6045 find_property_index (MonoClass *klass, MonoProperty *property) {
6046         int i;
6047
6048         for (i = 0; i < klass->property.count; ++i) {
6049                 if (property == &klass->properties [i])
6050                         return klass->property.first + 1 + i;
6051         }
6052         return 0;
6053 }
6054
6055 /*
6056  * Find the event index in the metadata Event table.
6057  */
6058 static guint32
6059 find_event_index (MonoClass *klass, MonoEvent *event) {
6060         int i;
6061
6062         for (i = 0; i < klass->event.count; ++i) {
6063                 if (event == &klass->events [i])
6064                         return klass->event.first + 1 + i;
6065         }
6066         return 0;
6067 }
6068
6069 static MonoObject*
6070 create_custom_attr (MonoImage *image, MonoMethod *method, 
6071                                         const char *data, guint32 len)
6072 {
6073         const char *p = data;
6074         const char *named;
6075         guint32 i, j, num_named;
6076         MonoObject *attr;
6077         void **params;
6078
6079         mono_class_init (method->klass);
6080
6081         if (len == 0) {
6082                 attr = mono_object_new (mono_domain_get (), method->klass);
6083                 mono_runtime_invoke (method, attr, NULL, NULL);
6084                 return attr;
6085         }
6086
6087         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
6088                 return NULL;
6089
6090         /*g_print ("got attr %s\n", method->klass->name);*/
6091         
6092         params = g_new (void*, method->signature->param_count);
6093
6094         /* skip prolog */
6095         p += 2;
6096         for (i = 0; i < method->signature->param_count; ++i) {
6097                 params [i] = load_cattr_value (image, method->signature->params [i], p, &p);
6098         }
6099
6100         named = p;
6101         attr = mono_object_new (mono_domain_get (), method->klass);
6102         mono_runtime_invoke (method, attr, params, NULL);
6103         free_param_data (method->signature, params);
6104         g_free (params);
6105         num_named = read16 (named);
6106         named += 2;
6107         for (j = 0; j < num_named; j++) {
6108                 gint name_len;
6109                 char *name, named_type, data_type;
6110                 named_type = *named++;
6111                 data_type = *named++; /* type of data */
6112                 if (data_type == 0x55) {
6113                         gint type_len;
6114                         char *type_name;
6115                         type_len = mono_metadata_decode_blob_size (named, &named);
6116                         type_name = g_malloc (type_len + 1);
6117                         memcpy (type_name, named, type_len);
6118                         type_name [type_len] = 0;
6119                         named += type_len;
6120                         /* FIXME: lookup the type and check type consistency */
6121                 } else if (data_type == MONO_TYPE_SZARRAY && (named_type == 0x54 || named_type == 0x53)) {
6122                         /* this seems to be the type of the element of the array */
6123                         /* g_print ("skipping 0x%02x after prop\n", *named); */
6124                         named++;
6125                 }
6126                 name_len = mono_metadata_decode_blob_size (named, &named);
6127                 name = g_malloc (name_len + 1);
6128                 memcpy (name, named, name_len);
6129                 name [name_len] = 0;
6130                 named += name_len;
6131                 if (named_type == 0x53) {
6132                         MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
6133                         void *val = load_cattr_value (image, field->type, named, &named);
6134                         mono_field_set_value (attr, field, val);
6135                         if (!type_is_reference (field->type))
6136                                 g_free (val);
6137                 } else if (named_type == 0x54) {
6138                         MonoProperty *prop;
6139                         void *pparams [1];
6140                         MonoType *prop_type;
6141
6142                         prop = mono_class_get_property_from_name (mono_object_class (attr), name);
6143                         /* can we have more that 1 arg in a custom attr named property? */
6144                         prop_type = prop->get? prop->get->signature->ret: prop->set->signature->params [prop->set->signature->param_count - 1];
6145                         pparams [0] = load_cattr_value (image, prop_type, named, &named);
6146                         mono_property_set_value (prop, attr, pparams, NULL);
6147                         if (!type_is_reference (prop_type))
6148                                 g_free (pparams [0]);
6149                 }
6150                 g_free (name);
6151         }
6152
6153         return attr;
6154 }
6155
6156 MonoArray*
6157 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
6158 {
6159         MonoArray *result;
6160         MonoClass *klass;
6161         MonoObject *attr;
6162         int i;
6163
6164         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6165         result = mono_array_new (mono_domain_get (), klass, cinfo->num_attrs);
6166         for (i = 0; i < cinfo->num_attrs; ++i) {
6167                 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
6168                 mono_array_set (result, gpointer, i, attr);
6169         }
6170         return result;
6171 }
6172
6173 MonoCustomAttrInfo*
6174 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
6175 {
6176         guint32 mtoken, i, len;
6177         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
6178         MonoTableInfo *ca;
6179         MonoCustomAttrInfo *ainfo;
6180         GList *tmp, *list = NULL;
6181         const char *data;
6182
6183         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
6184
6185         i = mono_metadata_custom_attrs_from_index (image, idx);
6186         if (!i)
6187                 return NULL;
6188         i --;
6189         while (i < ca->rows) {
6190                 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
6191                         break;
6192                 list = g_list_prepend (list, GUINT_TO_POINTER (i));
6193                 ++i;
6194         }
6195         len = g_list_length (list);
6196         if (!len)
6197                 return NULL;
6198         ainfo = g_malloc0 (sizeof (MonoCustomAttrInfo) + sizeof (MonoCustomAttrEntry) * (len - MONO_ZERO_LEN_ARRAY));
6199         ainfo->num_attrs = len;
6200         ainfo->image = image;
6201         for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
6202                 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
6203                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
6204                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
6205                 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
6206                         mtoken |= MONO_TOKEN_METHOD_DEF;
6207                         break;
6208                 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
6209                         mtoken |= MONO_TOKEN_MEMBER_REF;
6210                         break;
6211                 default:
6212                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
6213                         break;
6214                 }
6215                 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
6216                 if (!ainfo->attrs [i].ctor)
6217                         g_error ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
6218                 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
6219                 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
6220                 ainfo->attrs [i].data = data;
6221         }
6222         g_list_free (list);
6223
6224         return ainfo;
6225 }
6226
6227 MonoCustomAttrInfo*
6228 mono_custom_attrs_from_method (MonoMethod *method)
6229 {
6230         MonoCustomAttrInfo *cinfo;
6231         guint32 idx;
6232         
6233         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, method)))
6234                 return cinfo;
6235         idx = find_method_index (method);
6236         idx <<= MONO_CUSTOM_ATTR_BITS;
6237         idx |= MONO_CUSTOM_ATTR_METHODDEF;
6238         return mono_custom_attrs_from_index (method->klass->image, idx);
6239 }
6240
6241 MonoCustomAttrInfo*
6242 mono_custom_attrs_from_class (MonoClass *klass)
6243 {
6244         MonoCustomAttrInfo *cinfo;
6245         guint32 idx;
6246         
6247         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, klass)))
6248                 return cinfo;
6249         idx = mono_metadata_token_index (klass->type_token);
6250         idx <<= MONO_CUSTOM_ATTR_BITS;
6251         idx |= MONO_CUSTOM_ATTR_TYPEDEF;
6252         return mono_custom_attrs_from_index (klass->image, idx);
6253 }
6254
6255 MonoCustomAttrInfo*
6256 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
6257 {
6258         MonoCustomAttrInfo *cinfo;
6259         guint32 idx;
6260         
6261         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, assembly)))
6262                 return cinfo;
6263         idx = 1; /* there is only one assembly */
6264         idx <<= MONO_CUSTOM_ATTR_BITS;
6265         idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
6266         return mono_custom_attrs_from_index (assembly->image, idx);
6267 }
6268
6269 static MonoCustomAttrInfo*
6270 mono_custom_attrs_from_module (MonoImage *image)
6271 {
6272         MonoCustomAttrInfo *cinfo;
6273         guint32 idx;
6274         
6275         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, image)))
6276                 return cinfo;
6277         idx = 1; /* there is only one module */
6278         idx <<= MONO_CUSTOM_ATTR_BITS;
6279         idx |= MONO_CUSTOM_ATTR_MODULE;
6280         return mono_custom_attrs_from_index (image, idx);
6281 }
6282
6283 MonoCustomAttrInfo*
6284 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
6285 {
6286         MonoCustomAttrInfo *cinfo;
6287         guint32 idx;
6288         
6289         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, property)))
6290                 return cinfo;
6291         idx = find_property_index (klass, property);
6292         idx <<= MONO_CUSTOM_ATTR_BITS;
6293         idx |= MONO_CUSTOM_ATTR_PROPERTY;
6294         return mono_custom_attrs_from_index (klass->image, idx);
6295 }
6296
6297 MonoCustomAttrInfo*
6298 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
6299 {
6300         MonoCustomAttrInfo *cinfo;
6301         guint32 idx;
6302         
6303         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, event)))
6304                 return cinfo;
6305         idx = find_event_index (klass, event);
6306         idx <<= MONO_CUSTOM_ATTR_BITS;
6307         idx |= MONO_CUSTOM_ATTR_EVENT;
6308         return mono_custom_attrs_from_index (klass->image, idx);
6309 }
6310
6311 MonoCustomAttrInfo*
6312 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
6313 {
6314         MonoCustomAttrInfo *cinfo;
6315         guint32 idx;
6316         
6317         if (dynamic_custom_attrs && (cinfo = g_hash_table_lookup (dynamic_custom_attrs, field)))
6318                 return cinfo;
6319         idx = find_field_index (klass, field);
6320         idx <<= MONO_CUSTOM_ATTR_BITS;
6321         idx |= MONO_CUSTOM_ATTR_FIELDDEF;
6322         return mono_custom_attrs_from_index (klass->image, idx);
6323 }
6324
6325 MonoCustomAttrInfo*
6326 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
6327 {
6328         MonoTableInfo *ca;
6329         guint32 i, idx, method_index;
6330         guint32 param_list, param_last, param_pos, found;
6331         MonoImage *image;
6332         MonoReflectionMethodAux *aux;
6333
6334         if (method->klass->image->dynamic) {
6335                 aux = mono_g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
6336                 if (!aux || !aux->param_cattr)
6337                         return NULL;
6338                 return aux->param_cattr [param];
6339         }
6340
6341         image = method->klass->image;
6342         method_index = find_method_index (method);
6343         ca = &image->tables [MONO_TABLE_METHOD];
6344
6345         if (method->klass->generic_inst || method->klass->gen_params ||
6346             method->signature->generic_param_count) {
6347                 /* FIXME FIXME FIXME */
6348                 return NULL;
6349         }
6350
6351         param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
6352         if (method_index == ca->rows) {
6353                 ca = &image->tables [MONO_TABLE_PARAM];
6354                 param_last = ca->rows + 1;
6355         } else {
6356                 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
6357                 ca = &image->tables [MONO_TABLE_PARAM];
6358         }
6359         found = FALSE;
6360         for (i = param_list; i < param_last; ++i) {
6361                 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
6362                 if (param_pos == param) {
6363                         found = TRUE;
6364                         break;
6365                 }
6366         }
6367         if (!found)
6368                 return NULL;
6369         idx = i;
6370         idx <<= MONO_CUSTOM_ATTR_BITS;
6371         idx |= MONO_CUSTOM_ATTR_PARAMDEF;
6372         return mono_custom_attrs_from_index (image, idx);
6373 }
6374
6375 /*
6376  * mono_reflection_get_custom_attrs:
6377  * @obj: a reflection object handle
6378  *
6379  * Return an array with all the custom attributes defined of the
6380  * reflection handle @obj. The objects are fully build.
6381  */
6382 MonoArray*
6383 mono_reflection_get_custom_attrs (MonoObject *obj)
6384 {
6385         MonoClass *klass;
6386         MonoArray *result;
6387         MonoCustomAttrInfo *cinfo = NULL;
6388         
6389         MONO_ARCH_SAVE_REGS;
6390
6391         klass = obj->vtable->klass;
6392         /* FIXME: need to handle: Module */
6393         if (klass == mono_defaults.monotype_class) {
6394                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
6395                 klass = mono_class_from_mono_type (rtype->type);
6396                 cinfo = mono_custom_attrs_from_class (klass);
6397         } else if (strcmp ("Assembly", klass->name) == 0) {
6398                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
6399                 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
6400         } else if (strcmp ("Module", klass->name) == 0) {
6401                 MonoReflectionModule *module = (MonoReflectionModule*)obj;
6402                 cinfo = mono_custom_attrs_from_module (module->image);
6403         } else if (strcmp ("MonoProperty", klass->name) == 0) {
6404                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
6405                 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
6406         } else if (strcmp ("MonoEvent", klass->name) == 0) {
6407                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
6408                 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
6409         } else if (strcmp ("MonoField", klass->name) == 0) {
6410                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
6411                 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
6412         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
6413                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
6414                 cinfo = mono_custom_attrs_from_method (rmethod->method);
6415         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
6416                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
6417                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
6418                 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
6419         } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
6420                 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
6421                 cinfo = mono_custom_attrs_from_builders (assemblyb->assembly.assembly->image, assemblyb->cattrs);
6422         } else if (strcmp ("TypeBuilder", klass->name) == 0) {
6423                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
6424                 cinfo = mono_custom_attrs_from_builders (&tb->module->dynamic_image->image, tb->cattrs);
6425         } else { /* handle other types here... */
6426                 g_error ("get custom attrs not yet supported for %s", klass->name);
6427         }
6428
6429         if (cinfo) {
6430                 result = mono_custom_attrs_construct (cinfo);
6431                 if (!cinfo->cached)
6432                         mono_custom_attrs_free (cinfo);
6433         } else {
6434                 klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
6435                 result = mono_array_new (mono_domain_get (), klass, 0);
6436         }
6437
6438         return result;
6439 }
6440
6441 static MonoMethodSignature*
6442 parameters_to_signature (MonoArray *parameters) {
6443         MonoMethodSignature *sig;
6444         int count, i;
6445
6446         count = parameters? mono_array_length (parameters): 0;
6447
6448         sig = g_malloc0 (sizeof (MonoMethodSignature) + sizeof (MonoType*) * count);
6449         sig->param_count = count;
6450         sig->sentinelpos = -1; /* FIXME */
6451         for (i = 0; i < count; ++i) {
6452                 MonoReflectionType *pt = mono_array_get (parameters, MonoReflectionType*, i);
6453                 sig->params [i] = pt->type;
6454         }
6455         return sig;
6456 }
6457
6458 static MonoMethodSignature*
6459 ctor_builder_to_signature (MonoReflectionCtorBuilder *ctor) {
6460         MonoMethodSignature *sig;
6461
6462         sig = parameters_to_signature (ctor->parameters);
6463         sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6464         sig->ret = &mono_defaults.void_class->byval_arg;
6465         return sig;
6466 }
6467
6468 static MonoMethodSignature*
6469 method_builder_to_signature (MonoReflectionMethodBuilder *method) {
6470         MonoMethodSignature *sig;
6471
6472         sig = parameters_to_signature (method->parameters);
6473         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6474         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6475         sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
6476         return sig;
6477 }
6478
6479 static MonoMethodSignature*
6480 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
6481         MonoMethodSignature *sig;
6482
6483         sig = parameters_to_signature (method->parameters);
6484         sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
6485         sig->ret = method->rtype? method->rtype->type: &mono_defaults.void_class->byval_arg;
6486         sig->generic_param_count = 0;
6487         return sig;
6488 }
6489
6490 static void
6491 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
6492 {
6493         MonoClass *klass = mono_object_class (prop);
6494         if (strcmp (klass->name, "PropertyBuilder") == 0) {
6495                 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
6496                 *name = mono_string_to_utf8 (pb->name);
6497                 *type = pb->type->type;
6498         } else {
6499                 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
6500                 *name = g_strdup (p->property->name);
6501                 if (p->property->get)
6502                         *type = p->property->get->signature->ret;
6503                 else
6504                         *type = p->property->set->signature->params [p->property->set->signature->param_count - 1];
6505         }
6506 }
6507
6508 static void
6509 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
6510 {
6511         MonoClass *klass = mono_object_class (field);
6512         if (strcmp (klass->name, "FieldBuilder") == 0) {
6513                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
6514                 *name = mono_string_to_utf8 (fb->name);
6515                 *type = fb->type->type;
6516         } else {
6517                 MonoReflectionField *f = (MonoReflectionField *)field;
6518                 *name = g_strdup (f->field->name);
6519                 *type = f->field->type;
6520         }
6521 }
6522
6523 /*
6524  * Encode a value in a custom attribute stream of bytes.
6525  * The value to encode is either supplied as an object in argument val
6526  * (valuetypes are boxed), or as a pointer to the data in the
6527  * argument argval.
6528  * @type represents the type of the value
6529  * @buffer is the start of the buffer
6530  * @p the current position in the buffer
6531  * @buflen contains the size of the buffer and is used to return the new buffer size
6532  * if this needs to be realloced.
6533  * @retbuffer and @retp return the start and the position of the buffer
6534  */
6535 static void
6536 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
6537 {
6538         MonoTypeEnum simple_type;
6539         
6540         if ((p-buffer) + 10 >= *buflen) {
6541                 char *newbuf;
6542                 *buflen *= 2;
6543                 newbuf = g_realloc (buffer, *buflen);
6544                 p = newbuf + (p-buffer);
6545                 buffer = newbuf;
6546         }
6547         if (!argval)
6548                 argval = ((char*)arg + sizeof (MonoObject));
6549         simple_type = type->type;
6550 handle_enum:
6551         switch (simple_type) {
6552         case MONO_TYPE_BOOLEAN:
6553         case MONO_TYPE_U1:
6554         case MONO_TYPE_I1:
6555                 *p++ = *argval;
6556                 break;
6557         case MONO_TYPE_CHAR:
6558         case MONO_TYPE_U2:
6559         case MONO_TYPE_I2:
6560                 swap_with_size (p, argval, 2, 1);
6561                 p += 2;
6562                 break;
6563         case MONO_TYPE_U4:
6564         case MONO_TYPE_I4:
6565         case MONO_TYPE_R4:
6566                 swap_with_size (p, argval, 4, 1);
6567                 p += 4;
6568                 break;
6569         case MONO_TYPE_U8:
6570         case MONO_TYPE_I8:
6571         case MONO_TYPE_R8:
6572                 swap_with_size (p, argval, 8, 1);
6573                 p += 8;
6574                 break;
6575         case MONO_TYPE_VALUETYPE:
6576                 if (type->data.klass->enumtype) {
6577                         simple_type = type->data.klass->enum_basetype->type;
6578                         goto handle_enum;
6579                 } else {
6580                         g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
6581                 }
6582                 break;
6583         case MONO_TYPE_STRING: {
6584                 char *str;
6585                 guint32 slen;
6586                 if (!arg) {
6587                         *p++ = 0xFF;
6588                         break;
6589                 }
6590                 str = mono_string_to_utf8 ((MonoString*)arg);
6591                 slen = strlen (str);
6592                 if ((p-buffer) + 10 + slen >= *buflen) {
6593                         char *newbuf;
6594                         *buflen *= 2;
6595                         *buflen += slen;
6596                         newbuf = g_realloc (buffer, *buflen);
6597                         p = newbuf + (p-buffer);
6598                         buffer = newbuf;
6599                 }
6600                 mono_metadata_encode_value (slen, p, &p);
6601                 memcpy (p, str, slen);
6602                 p += slen;
6603                 g_free (str);
6604                 break;
6605         }
6606         case MONO_TYPE_CLASS: {
6607                 char *str;
6608                 guint32 slen;
6609                 MonoClass *k;
6610                 if (!arg) {
6611                         *p++ = 0xFF;
6612                         break;
6613                 }
6614                 k = mono_object_class (arg);
6615                 if (!mono_object_isinst (arg, mono_defaults.monotype_class) &&
6616                                 (strcmp (k->name, "TypeBuilder") || strcmp (k->name_space, "System.Reflection.Emit")))
6617                         g_error ("only types allowed, not %s.%s", k->name_space, k->name);
6618 handle_type:
6619                 str = type_get_qualified_name (((MonoReflectionType*)arg)->type, NULL);
6620                 slen = strlen (str);
6621                 if ((p-buffer) + 10 + slen >= *buflen) {
6622                         char *newbuf;
6623                         *buflen *= 2;
6624                         *buflen += slen;
6625                         newbuf = g_realloc (buffer, *buflen);
6626                         p = newbuf + (p-buffer);
6627                         buffer = newbuf;
6628                 }
6629                 mono_metadata_encode_value (slen, p, &p);
6630                 memcpy (p, str, slen);
6631                 p += slen;
6632                 g_free (str);
6633                 break;
6634         }
6635         case MONO_TYPE_SZARRAY: {
6636                 int len, i;
6637                 MonoClass *eclass, *arg_eclass;
6638
6639                 if (!arg) {
6640                         *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
6641                         break;
6642                 }
6643                 len = mono_array_length ((MonoArray*)arg);
6644                 *p++ = len & 0xff;
6645                 *p++ = (len >> 8) & 0xff;
6646                 *p++ = (len >> 16) & 0xff;
6647                 *p++ = (len >> 24) & 0xff;
6648                 *retp = p;
6649                 *retbuffer = buffer;
6650                 eclass = type->data.klass;
6651                 arg_eclass = mono_object_class (arg)->element_class;
6652                 if (eclass->valuetype && arg_eclass->valuetype) {
6653                         char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
6654                         int elsize = mono_class_array_element_size (eclass);
6655                         for (i = 0; i < len; ++i) {
6656                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
6657                                 elptr += elsize;
6658                         }
6659                 } else {
6660                         for (i = 0; i < len; ++i) {
6661                                 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
6662                         }
6663                 }
6664                 break;
6665         }
6666         /* it may be a boxed value or a Type */
6667         case MONO_TYPE_OBJECT: {
6668                 MonoClass *klass = mono_object_class (arg);
6669                 char *str;
6670                 guint32 slen;
6671                 
6672                 if (mono_object_isinst (arg, mono_defaults.monotype_class)) {
6673                         *p++ = 0x50;
6674                         goto handle_type;
6675                 } else if (klass->enumtype) {
6676                         *p++ = 0x55;
6677                 } else if (klass == mono_defaults.string_class) {
6678                         simple_type = MONO_TYPE_STRING;
6679                         *p++ = 0x0E;
6680                         goto handle_enum;
6681                 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
6682                         *p++ = simple_type = klass->byval_arg.type;
6683                         goto handle_enum;
6684                 } else {
6685                         g_error ("unhandled type in custom attr");
6686                 }
6687                 str = type_get_qualified_name (klass->enum_basetype, NULL);
6688                 slen = strlen (str);
6689                 if ((p-buffer) + 10 + slen >= *buflen) {
6690                         char *newbuf;
6691                         *buflen *= 2;
6692                         *buflen += slen;
6693                         newbuf = g_realloc (buffer, *buflen);
6694                         p = newbuf + (p-buffer);
6695                         buffer = newbuf;
6696                 }
6697                 mono_metadata_encode_value (slen, p, &p);
6698                 memcpy (p, str, slen);
6699                 p += slen;
6700                 g_free (str);
6701                 simple_type = klass->enum_basetype->type;
6702                 goto handle_enum;
6703         }
6704         default:
6705                 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
6706         }
6707         *retp = p;
6708         *retbuffer = buffer;
6709 }
6710
6711 /*
6712  * mono_reflection_get_custom_attrs_blob:
6713  * @ctor: custom attribute constructor
6714  * @ctorArgs: arguments o the constructor
6715  * @properties:
6716  * @propValues:
6717  * @fields:
6718  * @fieldValues:
6719  * 
6720  * Creates the blob of data that needs to be saved in the metadata and that represents
6721  * the custom attributed described by @ctor, @ctorArgs etc.
6722  * Returns: a Byte array representing the blob of data.
6723  */
6724 MonoArray*
6725 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) 
6726 {
6727         MonoArray *result;
6728         MonoMethodSignature *sig;
6729         MonoObject *arg;
6730         char *buffer, *p;
6731         guint32 buflen, i;
6732
6733         MONO_ARCH_SAVE_REGS;
6734
6735         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
6736                 sig = ctor_builder_to_signature ((MonoReflectionCtorBuilder*)ctor);
6737         } else {
6738                 sig = ((MonoReflectionMethod*)ctor)->method->signature;
6739         }
6740         g_assert (mono_array_length (ctorArgs) == sig->param_count);
6741         buflen = 256;
6742         p = buffer = g_malloc (buflen);
6743         /* write the prolog */
6744         *p++ = 1;
6745         *p++ = 0;
6746         for (i = 0; i < sig->param_count; ++i) {
6747                 arg = mono_array_get (ctorArgs, MonoObject*, i);
6748                 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
6749         }
6750         i = 0;
6751         if (properties)
6752                 i += mono_array_length (properties);
6753         if (fields)
6754                 i += mono_array_length (fields);
6755         *p++ = i & 0xff;
6756         *p++ = (i >> 8) & 0xff;
6757         if (properties) {
6758                 MonoObject *prop;
6759                 for (i = 0; i < mono_array_length (properties); ++i) {
6760                         MonoType *ptype;
6761                         char *pname;
6762                         int len;
6763                         
6764                         prop = mono_array_get (properties, gpointer, i);
6765                         get_prop_name_and_type (prop, &pname, &ptype);
6766                         *p++ = 0x54; /* PROPERTY signature */
6767
6768                         /* Preallocate a large enough buffer */
6769                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6770                                 char *str = type_get_qualified_name (ptype, NULL);
6771                                 len = strlen (str);
6772                                 g_free (str);
6773                         }
6774                         else
6775                                 len = 0;
6776                         len += strlen (pname);
6777
6778                         if ((p-buffer) + 20 + len >= buflen) {
6779                                 char *newbuf;
6780                                 buflen *= 2;
6781                                 buflen += len;
6782                                 newbuf = g_realloc (buffer, buflen);
6783                                 p = newbuf + (p-buffer);
6784                                 buffer = newbuf;
6785                         }
6786
6787                         if (ptype->type == MONO_TYPE_VALUETYPE && ptype->data.klass->enumtype) {
6788                                 char *str = type_get_qualified_name (ptype, NULL);
6789                                 int slen = strlen (str);
6790
6791                                 *p++ = 0x55;
6792                                 /*
6793                                  * This seems to be optional...
6794                                  * *p++ = 0x80;
6795                                  */
6796                                 mono_metadata_encode_value (slen, p, &p);
6797                                 memcpy (p, str, slen);
6798                                 p += slen;
6799                                 g_free (str);
6800                         } else {
6801                                 mono_metadata_encode_value (ptype->type, p, &p);
6802                                 if (ptype->type == MONO_TYPE_SZARRAY)
6803                                         mono_metadata_encode_value (ptype->data.klass->this_arg.type, p, &p);
6804                         }
6805                         len = strlen (pname);
6806                         mono_metadata_encode_value (len, p, &p);
6807                         memcpy (p, pname, len);
6808                         p += len;
6809                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ptype, (MonoObject*)mono_array_get (propValues, gpointer, i), NULL);
6810                         g_free (pname);
6811                 }
6812         }
6813
6814         if (fields) {
6815                 MonoObject *field;
6816                 for (i = 0; i < mono_array_length (fields); ++i) {
6817                         MonoType *ftype;
6818                         char *fname;
6819                         int len;
6820                         
6821                         field = mono_array_get (fields, gpointer, i);
6822                         get_field_name_and_type (field, &fname, &ftype);
6823                         *p++ = 0x53; /* FIELD signature */
6824                         if (ftype->type == MONO_TYPE_VALUETYPE && ftype->data.klass->enumtype) {
6825                                 char *str = type_get_qualified_name (ftype, NULL);
6826                                 int slen = strlen (str);
6827                                 if ((p-buffer) + 10 + slen >= buflen) {
6828                                         char *newbuf;
6829                                         buflen *= 2;
6830                                         buflen += slen;
6831                                         newbuf = g_realloc (buffer, buflen);
6832                                         p = newbuf + (p-buffer);
6833                                         buffer = newbuf;
6834                                 }
6835                                 *p++ = 0x55;
6836                                 /*
6837                                  * This seems to be optional...
6838                                  * *p++ = 0x80;
6839                                  */
6840                                 mono_metadata_encode_value (slen, p, &p);
6841                                 memcpy (p, str, slen);
6842                                 p += slen;
6843                                 g_free (str);
6844                         } else {
6845                                 mono_metadata_encode_value (ftype->type, p, &p);
6846                                 if (ftype->type == MONO_TYPE_SZARRAY)
6847                                         mono_metadata_encode_value (ftype->data.klass->this_arg.type, p, &p);
6848                         }
6849                         len = strlen (fname);
6850                         mono_metadata_encode_value (len, p, &p);
6851                         memcpy (p, fname, len);
6852                         p += len;
6853                         encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, ftype, (MonoObject*)mono_array_get (fieldValues, gpointer, i), NULL);
6854                         g_free (fname);
6855                 }
6856         }
6857
6858         g_assert (p - buffer <= buflen);
6859         buflen = p - buffer;
6860         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
6861         p = mono_array_addr (result, char, 0);
6862         memcpy (p, buffer, buflen);
6863         g_free (buffer);
6864         if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
6865                 g_free (sig);
6866         return result;
6867 }
6868
6869 /*
6870  * mono_reflection_setup_internal_class:
6871  * @tb: a TypeBuilder object
6872  *
6873  * Creates a MonoClass that represents the TypeBuilder.
6874  * This is a trick that lets us simplify a lot of reflection code
6875  * (and will allow us to support Build and Run assemblies easier).
6876  */
6877 void
6878 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
6879 {
6880         MonoClass *klass, *parent;
6881
6882         MONO_ARCH_SAVE_REGS;
6883
6884         if (tb->parent) {
6885                 /* check so we can compile corlib correctly */
6886                 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
6887                         /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
6888                         parent = tb->parent->type->data.klass;
6889                 } else 
6890                         parent = my_mono_class_from_mono_type (tb->parent->type);
6891         } else
6892                 parent = NULL;
6893         
6894         /* the type has already being created: it means we just have to change the parent */
6895         if (tb->type.type) {
6896                 klass = mono_class_from_mono_type (tb->type.type);
6897                 klass->parent = NULL;
6898                 /* fool mono_class_setup_parent */
6899                 g_free (klass->supertypes);
6900                 klass->supertypes = NULL;
6901                 mono_class_setup_parent (klass, parent);
6902                 mono_class_setup_mono_type (klass);
6903                 return;
6904         }
6905         
6906         klass = g_new0 (MonoClass, 1);
6907
6908         klass->image = &tb->module->dynamic_image->image;
6909
6910         klass->inited = 1; /* we lie to the runtime */
6911         klass->name = mono_string_to_utf8 (tb->name);
6912         klass->name_space = mono_string_to_utf8 (tb->nspace);
6913         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
6914         klass->flags = tb->attrs;
6915
6916         klass->element_class = klass;
6917         klass->reflection_info = tb; /* need to pin. */
6918
6919         /* Put into cache so mono_class_get () will find it */
6920         mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name,
6921                                                                   tb->table_idx);
6922
6923         mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
6924                                                           GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx),
6925                                                           tb);
6926
6927         if (parent != NULL)
6928                 mono_class_setup_parent (klass, parent);
6929         else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
6930                 const char *old_n = klass->name;
6931                 /* trick to get relative numbering right when compiling corlib */
6932                 klass->name = "BuildingObject";
6933                 mono_class_setup_parent (klass, mono_defaults.object_class);
6934                 klass->name = old_n;
6935         }
6936         mono_class_setup_mono_type (klass);
6937
6938         mono_class_setup_supertypes (klass);
6939
6940         /*
6941          * FIXME: handle interfaces.
6942          */
6943
6944         tb->type.type = &klass->byval_arg;
6945
6946         if (tb->nesting_type) {
6947                 g_assert (tb->nesting_type->type);
6948                 klass->nested_in = mono_class_from_mono_type (tb->nesting_type->type);
6949         }
6950
6951         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
6952 }
6953
6954 /*
6955  * mono_reflection_setup_generic_class:
6956  * @tb: a TypeBuilder object
6957  *
6958  * Setup the generic class after all generic parameters have been added.
6959  */
6960 void
6961 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
6962 {
6963         MonoClass *klass;
6964         int count, i;
6965
6966         MONO_ARCH_SAVE_REGS;
6967
6968         klass = my_mono_class_from_mono_type (tb->type.type);
6969
6970         count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
6971
6972         if (klass->gen_params || (count == 0))
6973                 return;
6974
6975         klass->num_gen_params = count;
6976         klass->gen_params = g_new0 (MonoGenericParam, count);
6977
6978         for (i = 0; i < count; i++) {
6979                 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
6980                 klass->gen_params [i] = *gparam->type.type->data.generic_param;
6981         }
6982 }
6983
6984 /*
6985  * mono_reflection_create_internal_class:
6986  * @tb: a TypeBuilder object
6987  *
6988  * Actually create the MonoClass that is associated with the TypeBuilder.
6989  */
6990 void
6991 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
6992 {
6993         MonoClass *klass;
6994
6995         MONO_ARCH_SAVE_REGS;
6996
6997         klass = my_mono_class_from_mono_type (tb->type.type);
6998
6999         if (klass->enumtype && klass->enum_basetype == NULL) {
7000                 MonoReflectionFieldBuilder *fb;
7001
7002                 g_assert (tb->fields != NULL);
7003                 g_assert (mono_array_length (tb->fields) >= 1);
7004
7005                 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
7006
7007                 klass->enum_basetype = fb->type->type;
7008                 klass->element_class = my_mono_class_from_mono_type (klass->enum_basetype);
7009                 if (!klass->element_class)
7010                         klass->element_class = mono_class_from_mono_type (klass->enum_basetype);
7011                 klass->instance_size = klass->element_class->instance_size;
7012                 klass->size_inited = 1;
7013                 /* 
7014                  * this is almost safe to do with enums and it's needed to be able
7015                  * to create objects of the enum type (for use in SetConstant).
7016                  */
7017                 /* FIXME: Does this mean enums can't have method overrides ? */
7018                 mono_class_setup_vtable (klass, NULL, 0);
7019         }
7020 }
7021
7022 static MonoMarshalSpec*
7023 mono_marshal_spec_from_builder (MonoAssembly *assembly,
7024                                                                 MonoReflectionMarshal *minfo)
7025 {
7026         MonoMarshalSpec *res;
7027
7028         res = g_new0 (MonoMarshalSpec, 1);
7029         res->native = minfo->type;
7030
7031         switch (minfo->type) {
7032         case MONO_NATIVE_LPARRAY:
7033                 res->data.array_data.elem_type = minfo->eltype;
7034                 res->data.array_data.param_num = 0; /* Not yet */
7035                 res->data.array_data.num_elem = minfo->count;
7036                 break;
7037
7038         case MONO_NATIVE_BYVALTSTR:
7039         case MONO_NATIVE_BYVALARRAY:
7040                 res->data.array_data.num_elem = minfo->count;
7041                 break;
7042
7043         case MONO_NATIVE_CUSTOM:
7044                 if (minfo->marshaltyperef)
7045                         res->data.custom_data.custom_name =
7046                                 type_get_fully_qualified_name (minfo->marshaltyperef->type);
7047                 if (minfo->mcookie)
7048                         res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
7049                 break;
7050
7051         default:
7052                 break;
7053         }
7054
7055         return res;
7056 }
7057
7058 static MonoMethod*
7059 reflection_methodbuilder_to_mono_method (MonoClass *klass,
7060                                          ReflectionMethodBuilder *rmb,
7061                                          MonoMethodSignature *sig)
7062 {
7063         MonoMethod *m;
7064         MonoMethodNormal *pm;
7065         MonoMarshalSpec **specs;
7066         MonoReflectionMethodAux *method_aux;
7067         int i;
7068
7069         if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
7070             (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
7071                 m = (MonoMethod *)g_new0 (MonoMethodPInvoke, 1);
7072         else 
7073                 if (rmb->refs)
7074                         m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
7075         else
7076                 m = (MonoMethod *)g_new0 (MonoMethodNormal, 1);
7077
7078         pm = (MonoMethodNormal*)m;
7079
7080         m->slot = -1;
7081         m->flags = rmb->attrs;
7082         m->iflags = rmb->iattrs;
7083         m->name = mono_string_to_utf8 (rmb->name);
7084         m->klass = klass;
7085         m->signature = sig;
7086         if (rmb->table_idx)
7087                 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
7088
7089         if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
7090                 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
7091                         m->string_ctor = 1;
7092
7093                 m->signature->pinvoke = 1;
7094         } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
7095                 /* TODO */
7096                 m->signature->pinvoke = 1;
7097                 return m;
7098         } else if (!m->klass->dummy && 
7099                            !(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
7100                            !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
7101                 MonoMethodHeader *header;
7102                 guint32 code_size;
7103                 gint32 max_stack, i;
7104                 gint32 num_locals = 0;
7105                 gint32 num_clauses = 0;
7106                 guint8 *code;
7107
7108                 if (rmb->ilgen) {
7109                         code = mono_array_addr (rmb->ilgen->code, guint8, 0);
7110                         code_size = rmb->ilgen->code_len;
7111                         max_stack = rmb->ilgen->max_stack;
7112                         num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
7113                         if (rmb->ilgen->ex_handlers)
7114                                 num_clauses = method_count_clauses (rmb->ilgen);
7115                 } else {
7116                         if (rmb->code) {
7117                                 code = mono_array_addr (rmb->code, guint8, 0);
7118                                 code_size = mono_array_length (rmb->code);
7119                                 /* we probably need to run a verifier on the code... */
7120                                 max_stack = 8; 
7121                         }
7122                         else {
7123                                 code = NULL;
7124                                 code_size = 0;
7125                                 max_stack = 8;
7126                         }
7127                 }
7128
7129                 header = g_malloc0 (sizeof (MonoMethodHeader) + 
7130                                                         (num_locals - MONO_ZERO_LEN_ARRAY) * sizeof (MonoType*));
7131                 header->code_size = code_size;
7132                 header->code = g_malloc (code_size);
7133                 memcpy ((char*)header->code, code, code_size);
7134                 header->max_stack = max_stack;
7135                 header->init_locals = rmb->init_locals;
7136                 header->num_locals = num_locals;
7137
7138                 for (i = 0; i < num_locals; ++i) {
7139                         MonoReflectionLocalBuilder *lb = 
7140                                 mono_array_get (rmb->ilgen->locals, 
7141                                                                 MonoReflectionLocalBuilder*, i);
7142
7143                         header->locals [i] = g_new0 (MonoType, 1);
7144                         memcpy (header->locals [i], lb->type->type, sizeof (MonoType));
7145                 }
7146
7147                 header->num_clauses = num_clauses;
7148                 if (num_clauses) {
7149                         header->clauses = method_encode_clauses ((MonoDynamicImage*)klass->image,
7150                                                                  rmb->ilgen,
7151                                                                  num_clauses);
7152                 }
7153
7154                 pm->header = header;
7155         }
7156
7157         if (rmb->generic_params) {
7158                 int count = mono_array_length (rmb->generic_params);
7159                 pm->gen_params = g_new0 (MonoGenericParam, count);
7160                 for (i = 0; i < count; i++) {
7161                         MonoReflectionGenericParam *gp =
7162                                 mono_array_get (rmb->generic_params,
7163                                                 MonoReflectionGenericParam*, i);
7164
7165                         pm->gen_params [i] = *gp->type.type->data.generic_param;
7166                 }
7167         }
7168
7169         if (rmb->refs) {
7170                 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
7171                 int i;
7172
7173                 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
7174
7175                 for (i = 0; i < rmb->nrefs; ++i)
7176                         mw->data = g_list_append (mw->data, rmb->refs [i]);
7177         }
7178
7179         method_aux = NULL;
7180
7181         /* Parameter names */
7182         if (rmb->pinfo) {
7183                 if (!method_aux)
7184                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7185                 method_aux->param_names = g_new0 (char *, m->signature->param_count + 1);
7186                 for (i = 0; i <= m->signature->param_count; ++i) {
7187                         MonoReflectionParamBuilder *pb;
7188                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7189                                 if (pb->name)
7190                                         method_aux->param_names [i] = mono_string_to_utf8 (pb->name);
7191                                 if (pb->cattrs) {
7192                                         if (!method_aux->param_cattr)
7193                                                 method_aux->param_cattr = g_new0 (MonoCustomAttrInfo*, m->signature->param_count + 1);
7194                                         method_aux->param_cattr [i] = mono_custom_attrs_from_builders (klass->image, pb->cattrs);
7195                                 }
7196                         }
7197                 }
7198         }
7199
7200         /* Parameter marshalling */
7201         specs = NULL;
7202         if (rmb->pinfo)         
7203                 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
7204                         MonoReflectionParamBuilder *pb;
7205                         if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
7206                                 if (pb->marshal_info) {
7207                                         if (specs == NULL)
7208                                                 specs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
7209                                         specs [pb->position] = 
7210                                                 mono_marshal_spec_from_builder (klass->image->assembly, pb->marshal_info);
7211                                 }
7212                         }
7213                 }
7214         if (specs != NULL) {
7215                 if (!method_aux)
7216                         method_aux = g_new0 (MonoReflectionMethodAux, 1);
7217                 method_aux->param_marshall = specs;
7218         }
7219
7220         if (klass->image->dynamic && method_aux)
7221                 mono_g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
7222
7223         return m;
7224 }       
7225
7226 static MonoMethod*
7227 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
7228 {
7229         ReflectionMethodBuilder rmb;
7230         MonoMethodSignature *sig;
7231
7232         sig = ctor_builder_to_signature (mb);
7233
7234         reflection_methodbuilder_from_ctor_builder (&rmb, mb);
7235
7236         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7237         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7238
7239         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7240                 /* ilgen is no longer needed */
7241                 mb->ilgen = NULL;
7242         }
7243
7244         return mb->mhandle;
7245 }
7246
7247 static MonoMethod*
7248 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
7249 {
7250         ReflectionMethodBuilder rmb;
7251         MonoMethodSignature *sig;
7252
7253         sig = method_builder_to_signature (mb);
7254
7255         reflection_methodbuilder_from_method_builder (&rmb, mb);
7256
7257         mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
7258         mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
7259
7260         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
7261                 /* ilgen is no longer needed */
7262                 mb->ilgen = NULL;
7263         }
7264         return mb->mhandle;
7265 }
7266
7267 static MonoClassField*
7268 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
7269 {
7270         MonoClassField *field;
7271         const char *p, *p2;
7272         guint32 len, idx;
7273
7274         if (fb->handle)
7275                 return fb->handle;
7276
7277         field = g_new0 (MonoClassField, 1);
7278
7279         field->name = mono_string_to_utf8 (fb->name);
7280         if (fb->attrs) {
7281                 /* FIXME: handle type modifiers */
7282                 field->type = g_memdup (fb->type->type, sizeof (MonoType));
7283                 field->type->attrs = fb->attrs;
7284         } else {
7285                 field->type = fb->type->type;
7286         }
7287         if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7288                 field->data = mono_array_addr (fb->rva_data, char, 0);
7289         if (fb->offset != -1)
7290                 field->offset = fb->offset;
7291         field->parent = klass;
7292         fb->handle = field;
7293         mono_save_custom_attrs (klass->image, field, fb->cattrs);
7294
7295         if (fb->def_value) {
7296                 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7297                 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7298                 idx = encode_constant (assembly, fb->def_value, &field->def_type);
7299                 /* Copy the data from the blob since it might get realloc-ed */
7300                 p = assembly->blob.data + idx;
7301                 len = mono_metadata_decode_blob_size (p, &p2);
7302                 len += p2 - p;
7303                 field->data = g_malloc (len);
7304                 memcpy ((gpointer)field->data, p, len);
7305         }
7306
7307         return field;
7308 }
7309
7310 static MonoType*
7311 do_mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc,
7312                                             MonoType **types)
7313 {
7314         MonoClass *klass;
7315         MonoReflectionTypeBuilder *tb = NULL;
7316         MonoGenericInst *ginst, *cached;
7317         MonoDomain *domain;
7318         MonoType *geninst;
7319         int icount, i;
7320
7321         klass = mono_class_from_mono_type (type->type);
7322         if (!klass->gen_params && !klass->generic_inst &&
7323             !(klass->nested_in && klass->nested_in->gen_params))
7324                 return NULL;
7325
7326         mono_loader_lock ();
7327
7328         domain = mono_object_domain (type);
7329
7330         ginst = g_new0 (MonoGenericInst, 1);
7331
7332         if (!klass->generic_inst) {
7333                 ginst->type_argc = type_argc;
7334                 ginst->type_argv = types;
7335
7336                 for (i = 0; i < ginst->type_argc; ++i) {
7337                         if (!ginst->is_open)
7338                                 ginst->is_open = mono_class_is_open_constructed_type (types [i]);
7339                 }
7340
7341                 ginst->generic_type = &klass->byval_arg;
7342         } else {
7343                 MonoGenericInst *kginst = klass->generic_inst;
7344
7345                 ginst->type_argc = kginst->type_argc;
7346                 ginst->type_argv = g_new0 (MonoType *, ginst->type_argc);
7347
7348                 for (i = 0; i < ginst->type_argc; i++) {
7349                         MonoType *t = kginst->type_argv [i];
7350
7351                         if (t->type == MONO_TYPE_VAR)
7352                                 t = types [t->data.generic_param->num];
7353
7354                         if (!ginst->is_open)
7355                                 ginst->is_open = mono_class_is_open_constructed_type (t);
7356
7357                         ginst->type_argv [i] = t;
7358                 }
7359
7360                 ginst->generic_type = kginst->generic_type;
7361         }
7362
7363         geninst = g_new0 (MonoType, 1);
7364         geninst->type = MONO_TYPE_GENERICINST;
7365
7366         cached = g_hash_table_lookup (klass->image->generic_inst_cache, ginst);
7367         if (cached) {
7368                 g_free (ginst);
7369                 mono_loader_unlock ();
7370                 geninst->data.generic_inst = cached;
7371                 return geninst;
7372         }
7373
7374         geninst->data.generic_inst = ginst;
7375
7376         ginst->context = g_new0 (MonoGenericContext, 1);
7377         ginst->context->ginst = ginst;
7378
7379         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7380                 tb = (MonoReflectionTypeBuilder *) type;
7381
7382                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7383                 ginst->is_dynamic = TRUE;
7384         } else if (!strcmp (((MonoObject *) type)->vtable->klass->name, "MonoGenericInst")) {
7385                 MonoReflectionGenericInst *rgi = (MonoReflectionGenericInst *) type;
7386                 MonoReflectionType *rgt = rgi->generic_type;
7387
7388                 g_assert (!strcmp (((MonoObject *) rgt)->vtable->klass->name, "TypeBuilder"));
7389                 tb = (MonoReflectionTypeBuilder *) rgt;
7390
7391                 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
7392                 ginst->is_dynamic = TRUE;
7393         } else
7394                 icount = klass->interface_count;
7395
7396         ginst->ifaces = g_new0 (MonoType *, icount);
7397         ginst->count_ifaces = icount;
7398
7399         for (i = 0; i < icount; i++) {
7400                 MonoReflectionType *itype;
7401
7402                 if (tb)
7403                         itype = mono_array_get (tb->interfaces, MonoReflectionType *, i);
7404                 else
7405                         itype = mono_type_get_object (domain, &klass->interfaces [i]->byval_arg);
7406                 ginst->ifaces [i] = mono_reflection_bind_generic_parameters (itype, type_argc, types);
7407                 if (!ginst->ifaces [i])
7408                         ginst->ifaces [i] = itype->type;
7409         }
7410
7411         mono_class_create_generic (ginst);
7412
7413         g_hash_table_insert (klass->image->generic_inst_cache, ginst, ginst);
7414
7415         mono_loader_unlock ();
7416
7417         return geninst;
7418 }
7419
7420 MonoType*
7421 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
7422 {
7423         MonoClass *klass, *pklass = NULL;
7424         MonoReflectionType *parent = NULL;
7425         MonoType *geninst;
7426         MonoReflectionTypeBuilder *tb = NULL;
7427         MonoGenericInst *ginst;
7428         MonoDomain *domain;
7429
7430         domain = mono_object_domain (type);
7431         klass = mono_class_from_mono_type (type->type);
7432
7433         if (!strcmp (((MonoObject *) type)->vtable->klass->name, "TypeBuilder")) {
7434                 tb = (MonoReflectionTypeBuilder *) type;
7435
7436                 if (tb->parent) {
7437                         parent = tb->parent;
7438                         pklass = mono_class_from_mono_type (parent->type);
7439                 }
7440         } else {
7441                 pklass = klass->parent;
7442                 if (pklass)
7443                         parent = mono_type_get_object (domain, &pklass->byval_arg);
7444         }
7445
7446         geninst = do_mono_reflection_bind_generic_parameters (type, type_argc, types);
7447         if (!geninst)
7448                 return NULL;
7449
7450         ginst = geninst->data.generic_inst;
7451
7452         if (pklass && pklass->generic_inst)
7453                 ginst->parent = mono_reflection_bind_generic_parameters (parent, type_argc, types);
7454
7455         return geninst;
7456 }
7457
7458 MonoReflectionMethod*
7459 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
7460 {
7461         MonoMethod *method, *inflated;
7462         MonoReflectionMethodBuilder *mb = NULL;
7463         MonoGenericMethod *gmethod;
7464         MonoGenericContext *context;
7465         int count, i;
7466
7467         MONO_ARCH_SAVE_REGS;
7468         if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
7469                 MonoReflectionTypeBuilder *tb;
7470                 MonoClass *klass;
7471
7472                 mb = (MonoReflectionMethodBuilder *) rmethod;
7473                 tb = (MonoReflectionTypeBuilder *) mb->type;
7474                 klass = mono_class_from_mono_type (tb->type.type);
7475
7476                 method = methodbuilder_to_mono_method (klass, mb);
7477         } else
7478                 method = rmethod->method;
7479
7480         count = method->signature->generic_param_count;
7481         if (count != mono_array_length (types))
7482                 return NULL;
7483
7484         gmethod = g_new0 (MonoGenericMethod, 1);
7485         gmethod->mtype_argc = count;
7486         gmethod->mtype_argv = g_new0 (MonoType *, count);
7487         for (i = 0; i < count; i++) {
7488                 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
7489                 gmethod->mtype_argv [i] = garg->type;
7490         }
7491
7492         gmethod->reflection_info = rmethod;
7493
7494         context = g_new0 (MonoGenericContext, 1);
7495         context->ginst = method->klass->generic_inst;
7496         context->gmethod = gmethod;
7497
7498         inflated = mono_class_inflate_generic_method (method, context, NULL);
7499
7500         return mono_method_get_object (
7501                 mono_object_domain (rmethod), inflated, NULL);
7502 }
7503
7504 static MonoMethod *
7505 inflate_mono_method (MonoReflectionGenericInst *type, MonoMethod *method, MonoObject *obj)
7506 {
7507         MonoGenericMethod *gmethod;
7508         MonoGenericInst *ginst;
7509         MonoGenericContext *context;
7510         int i;
7511
7512         ginst = type->type.type->data.generic_inst;
7513
7514         gmethod = g_new0 (MonoGenericMethod, 1);
7515         gmethod->reflection_info = obj;
7516
7517         gmethod->mtype_argc = method->signature->generic_param_count;
7518         gmethod->mtype_argv = g_new0 (MonoType *, gmethod->mtype_argc);
7519
7520         for (i = 0; i < gmethod->mtype_argc; i++) {
7521                 MonoMethodNormal *mn = (MonoMethodNormal *) method;
7522                 MonoGenericParam *gparam = &mn->gen_params [i];
7523
7524                 g_assert (gparam->pklass);
7525                 gmethod->mtype_argv [i] = &gparam->pklass->byval_arg;
7526         }
7527
7528         context = g_new0 (MonoGenericContext, 1);
7529         context->ginst = ginst;
7530         context->gmethod = gmethod;
7531
7532         return mono_class_inflate_generic_method (method, context, ginst->klass);
7533 }
7534
7535 static MonoMethod *
7536 inflate_method (MonoReflectionGenericInst *type, MonoObject *obj)
7537 {
7538         MonoMethod *method;
7539         MonoClass *klass;
7540
7541         klass = mono_class_from_mono_type (type->type.type);
7542
7543         if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
7544                 method = methodbuilder_to_mono_method (klass, (MonoReflectionMethodBuilder *) obj);
7545         else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
7546                 method = ctorbuilder_to_mono_method (klass, (MonoReflectionCtorBuilder *) obj);
7547         else if (!strcmp (obj->vtable->klass->name, "MonoMethod") ||
7548                  !strcmp (obj->vtable->klass->name, "MonoCMethod"))
7549                 method = ((MonoReflectionMethod *) obj)->method;
7550         else {
7551                 method = NULL; /* prevent compiler warning */
7552                 g_assert_not_reached ();
7553         }
7554
7555         return inflate_mono_method (type, method, obj);
7556 }
7557
7558 void
7559 mono_reflection_generic_inst_initialize (MonoReflectionGenericInst *type,
7560                                          MonoArray *methods, MonoArray *ctors,
7561                                          MonoArray *fields, MonoArray *properties,
7562                                          MonoArray *events)
7563 {
7564         MonoGenericInst *ginst;
7565         MonoDynamicGenericInst *dginst;
7566         MonoClass *klass, *gklass, *pklass;
7567         int i;
7568
7569         MONO_ARCH_SAVE_REGS;
7570
7571         klass = mono_class_from_mono_type (type->type.type);
7572         ginst = type->type.type->data.generic_inst;
7573
7574         if (ginst->initialized)
7575                 return;
7576
7577         dginst = ginst->dynamic_info = g_new0 (MonoDynamicGenericInst, 1);
7578
7579         gklass = mono_class_from_mono_type (ginst->generic_type);
7580         mono_class_init (gklass);
7581
7582         if (ginst->parent)
7583                 pklass = mono_class_from_mono_type (ginst->parent);
7584         else
7585                 pklass = gklass->parent;
7586
7587         mono_class_setup_parent (klass, pklass);
7588
7589         dginst->count_methods = methods ? mono_array_length (methods) : 0;
7590         dginst->count_ctors = ctors ? mono_array_length (ctors) : 0;
7591         dginst->count_fields = fields ? mono_array_length (fields) : 0;
7592         dginst->count_properties = properties ? mono_array_length (properties) : 0;
7593         dginst->count_events = events ? mono_array_length (events) : 0;
7594
7595         dginst->methods = g_new0 (MonoMethod *, dginst->count_methods);
7596         dginst->ctors = g_new0 (MonoMethod *, dginst->count_ctors);
7597         dginst->fields = g_new0 (MonoClassField, dginst->count_fields);
7598         dginst->properties = g_new0 (MonoProperty, dginst->count_properties);
7599         dginst->events = g_new0 (MonoEvent, dginst->count_events);
7600
7601         for (i = 0; i < dginst->count_methods; i++) {
7602                 MonoObject *obj = mono_array_get (methods, gpointer, i);
7603
7604                 dginst->methods [i] = inflate_method (type, obj);
7605         }
7606
7607         for (i = 0; i < dginst->count_ctors; i++) {
7608                 MonoObject *obj = mono_array_get (ctors, gpointer, i);
7609
7610                 dginst->ctors [i] = inflate_method (type, obj);
7611         }
7612
7613         for (i = 0; i < dginst->count_fields; i++) {
7614                 MonoObject *obj = mono_array_get (fields, gpointer, i);
7615                 MonoClassField *field;
7616                 MonoInflatedField *ifield;
7617
7618                 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
7619                         field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
7620                 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
7621                         field = ((MonoReflectionField *) obj)->field;
7622                 else {
7623                         field = NULL; /* prevent compiler warning */
7624                         g_assert_not_reached ();
7625                 }
7626
7627                 ifield = g_new0 (MonoInflatedField, 1);
7628                 ifield->generic_type = field->type;
7629                 ifield->reflection_info = obj;
7630
7631                 dginst->fields [i] = *field;
7632                 dginst->fields [i].generic_info = ifield;
7633                 dginst->fields [i].type = mono_class_inflate_generic_type (field->type, ginst->context);
7634         }
7635
7636         for (i = 0; i < dginst->count_properties; i++) {
7637                 MonoObject *obj = mono_array_get (properties, gpointer, i);
7638                 MonoProperty *property = &dginst->properties [i];
7639
7640                 if (!strcmp (obj->vtable->klass->name, "PropertyBuilder")) {
7641                         MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *) obj;
7642
7643                         property->parent = klass;
7644                         property->attrs = pb->attrs;
7645                         property->name = mono_string_to_utf8 (pb->name);
7646                         if (pb->get_method)
7647                                 property->get = inflate_method (type, (MonoObject *) pb->get_method);
7648                         if (pb->set_method)
7649                                 property->set = inflate_method (type, (MonoObject *) pb->set_method);
7650                 } else if (!strcmp (obj->vtable->klass->name, "MonoProperty")) {
7651                         *property = *((MonoReflectionProperty *) obj)->property;
7652
7653                         if (property->get)
7654                                 property->get = inflate_mono_method (type, property->get, NULL);
7655                         if (property->set)
7656                                 property->set = inflate_mono_method (type, property->set, NULL);
7657                 } else
7658                         g_assert_not_reached ();
7659         }
7660
7661         for (i = 0; i < dginst->count_events; i++) {
7662                 MonoObject *obj = mono_array_get (events, gpointer, i);
7663                 MonoEvent *event = &dginst->events [i];
7664
7665                 if (!strcmp (obj->vtable->klass->name, "EventBuilder")) {
7666                         MonoReflectionEventBuilder *eb = (MonoReflectionEventBuilder *) obj;
7667
7668                         event->parent = klass;
7669                         event->attrs = eb->attrs;
7670                         event->name = mono_string_to_utf8 (eb->name);
7671                         if (eb->add_method)
7672                                 event->add = inflate_method (type, (MonoObject *) eb->add_method);
7673                         if (eb->remove_method)
7674                                 event->remove = inflate_method (type, (MonoObject *) eb->remove_method);
7675                 } else if (!strcmp (obj->vtable->klass->name, "MonoEvent")) {
7676                         *event = *((MonoReflectionEvent *) obj)->event;
7677
7678                         if (event->add)
7679                                 event->add = inflate_mono_method (type, event->add, NULL);
7680                         if (event->remove)
7681                                 event->remove = inflate_mono_method (type, event->remove, NULL);
7682                 } else
7683                         g_assert_not_reached ();
7684         }
7685
7686         ginst->initialized = TRUE;
7687 }
7688
7689 static void
7690 ensure_runtime_vtable (MonoClass *klass)
7691 {
7692         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7693         int i, num, j, onum;
7694         MonoMethod **overrides;
7695
7696         if (!tb || klass->wastypebuilder)
7697                 return;
7698         if (klass->parent)
7699                 ensure_runtime_vtable (klass->parent);
7700
7701         num = tb->ctors? mono_array_length (tb->ctors): 0;
7702         num += tb->num_methods;
7703         klass->method.count = num;
7704         klass->methods = g_new (MonoMethod*, num);
7705         num = tb->ctors? mono_array_length (tb->ctors): 0;
7706         for (i = 0; i < num; ++i)
7707                 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
7708         num = tb->num_methods;
7709         j = i;
7710         for (i = 0; i < num; ++i)
7711                 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
7712
7713         klass->wastypebuilder = TRUE;
7714         if (tb->interfaces) {
7715                 klass->interface_count = mono_array_length (tb->interfaces);
7716                 klass->interfaces = g_new (MonoClass*, klass->interface_count);
7717                 for (i = 0; i < klass->interface_count; ++i) {
7718                         MonoReflectionType *iface = mono_array_get (tb->interfaces, gpointer, i);
7719                         klass->interfaces [i] = mono_class_from_mono_type (iface->type);
7720                 }
7721         }
7722
7723         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE)
7724                 for (i = 0; i < klass->method.count; ++i)
7725                         klass->methods [i]->slot = i;
7726
7727         /* Overrides */
7728         onum = 0;
7729         if (tb->methods) {
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                                 onum ++;
7735                 }
7736         }
7737
7738         overrides = (MonoMethod**)g_new0 (MonoMethod, onum * 2);
7739
7740         if (tb->methods) {
7741                 onum = 0;
7742                 for (i = 0; i < tb->num_methods; ++i) {
7743                         MonoReflectionMethodBuilder *mb = 
7744                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
7745                         if (mb->override_method) {
7746                                 /* FIXME: What if 'override_method' is a MethodBuilder ? */
7747                                 overrides [onum * 2] = 
7748                                         mb->override_method->method;
7749                                 overrides [onum * 2 + 1] =
7750                                         mb->mhandle;
7751
7752                                 g_assert (mb->mhandle);
7753
7754                                 onum ++;
7755                         }
7756                 }
7757         }
7758
7759         mono_class_setup_vtable (klass, overrides, onum);
7760 }
7761
7762 static void
7763 typebuilder_setup_fields (MonoClass *klass)
7764 {
7765         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7766         MonoReflectionFieldBuilder *fb;
7767         MonoClassField *field;
7768         const char *p, *p2;
7769         int i;
7770         guint32 len, idx;
7771
7772         klass->field.count = tb->num_fields;
7773         klass->field.first = 0;
7774         klass->field.last = klass->field.count;
7775
7776         if (!klass->field.count)
7777                 return;
7778         
7779         klass->fields = g_new0 (MonoClassField, klass->field.count);
7780
7781         for (i = 0; i < klass->field.count; ++i) {
7782                 fb = mono_array_get (tb->fields, gpointer, i);
7783                 field = &klass->fields [i];
7784                 field->name = mono_string_to_utf8 (fb->name);
7785                 if (fb->attrs) {
7786                         /* FIXME: handle type modifiers */
7787                         field->type = g_memdup (fb->type->type, sizeof (MonoType));
7788                         field->type->attrs = fb->attrs;
7789                 } else {
7790                         field->type = fb->type->type;
7791                 }
7792                 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
7793                         field->data = mono_array_addr (fb->rva_data, char, 0);
7794                 if (fb->offset != -1)
7795                         field->offset = fb->offset;
7796                 field->parent = klass;
7797                 fb->handle = field;
7798                 mono_save_custom_attrs (klass->image, field, fb->cattrs);
7799
7800                 if (fb->def_value) {
7801                         MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
7802                         field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
7803                         idx = encode_constant (assembly, fb->def_value, &field->def_type);
7804                         /* Copy the data from the blob since it might get realloc-ed */
7805                         p = assembly->blob.data + idx;
7806                         len = mono_metadata_decode_blob_size (p, &p2);
7807                         len += p2 - p;
7808                         field->data = g_malloc (len);
7809                         memcpy ((gpointer)field->data, p, len);
7810                 }
7811         }
7812         mono_class_layout_fields (klass);
7813 }
7814
7815 static void
7816 typebuilder_setup_properties (MonoClass *klass)
7817 {
7818         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7819         MonoReflectionPropertyBuilder *pb;
7820         int i;
7821
7822         klass->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
7823         klass->property.first = 0;
7824         klass->property.last = klass->property.count;
7825
7826         klass->properties = g_new0 (MonoProperty, klass->property.count);
7827         for (i = 0; i < klass->property.count; ++i) {
7828                 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
7829                 klass->properties [i].parent = klass;
7830                 klass->properties [i].attrs = pb->attrs;
7831                 klass->properties [i].name = mono_string_to_utf8 (pb->name);
7832                 if (pb->get_method)
7833                         klass->properties [i].get = pb->get_method->mhandle;
7834                 if (pb->set_method)
7835                         klass->properties [i].set = pb->set_method->mhandle;
7836         }
7837 }
7838
7839 MonoReflectionEvent *
7840 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
7841 {
7842         MonoEvent *event = g_new0 (MonoEvent, 1);
7843         MonoClass *klass;
7844         int j;
7845
7846         klass = my_mono_class_from_mono_type (tb->type.type);
7847
7848         event->parent = klass;
7849         event->attrs = eb->attrs;
7850         event->name = mono_string_to_utf8 (eb->name);
7851         if (eb->add_method)
7852                 event->add = eb->add_method->mhandle;
7853         if (eb->remove_method)
7854                 event->remove = eb->remove_method->mhandle;
7855         if (eb->raise_method)
7856                 event->raise = eb->raise_method->mhandle;
7857
7858         if (eb->other_methods) {
7859                 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7860                 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7861                         MonoReflectionMethodBuilder *mb = 
7862                                 mono_array_get (eb->other_methods,
7863                                                 MonoReflectionMethodBuilder*, j);
7864                         event->other [j] = mb->mhandle;
7865                 }
7866         }
7867
7868         return mono_event_get_object (mono_object_domain (tb), klass, event);
7869 }
7870
7871 static void
7872 typebuilder_setup_events (MonoClass *klass)
7873 {
7874         MonoReflectionTypeBuilder *tb = klass->reflection_info;
7875         MonoReflectionEventBuilder *eb;
7876         int i, j;
7877
7878         klass->event.count = tb->events ? mono_array_length (tb->events) : 0;
7879         klass->event.first = 0;
7880         klass->event.last = klass->event.count;
7881
7882         klass->events = g_new0 (MonoEvent, klass->event.count);
7883         for (i = 0; i < klass->event.count; ++i) {
7884                 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
7885                 klass->events [i].parent = klass;
7886                 klass->events [i].attrs = eb->attrs;
7887                 klass->events [i].name = mono_string_to_utf8 (eb->name);
7888                 if (eb->add_method)
7889                         klass->events [i].add = eb->add_method->mhandle;
7890                 if (eb->remove_method)
7891                         klass->events [i].remove = eb->remove_method->mhandle;
7892                 if (eb->raise_method)
7893                         klass->events [i].raise = eb->raise_method->mhandle;
7894
7895                 if (eb->other_methods) {
7896                         klass->events [i].other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods));
7897                         for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
7898                                 MonoReflectionMethodBuilder *mb = 
7899                                         mono_array_get (eb->other_methods,
7900                                                                         MonoReflectionMethodBuilder*, j);
7901                                 klass->events [i].other [j] = mb->mhandle;
7902                         }
7903                 }
7904         }
7905 }
7906
7907 MonoReflectionType*
7908 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
7909 {
7910         MonoClass *klass;
7911         MonoReflectionType* res;
7912         int i;
7913
7914         MONO_ARCH_SAVE_REGS;
7915
7916         klass = my_mono_class_from_mono_type (tb->type.type);
7917
7918         mono_save_custom_attrs (klass->image, klass, tb->cattrs);
7919
7920         /*
7921          * Fields to set in klass:
7922          * the various flags: delegate/unicode/contextbound etc.
7923          */
7924         klass->flags = tb->attrs;
7925
7926         if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->run)
7927                 /* No need to fully construct the type */
7928                 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7929
7930         /* enums are done right away */
7931         if (!klass->enumtype)
7932                 ensure_runtime_vtable (klass);
7933
7934         if (tb->subtypes) {
7935                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
7936                         MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
7937                         klass->nested_classes = g_list_prepend (klass->nested_classes, my_mono_class_from_mono_type (subtb->type.type));
7938                 }
7939         }
7940
7941         /* fields and object layout */
7942         if (klass->parent) {
7943                 if (!klass->parent->size_inited)
7944                         mono_class_init (klass->parent);
7945                 klass->instance_size += klass->parent->instance_size;
7946                 klass->class_size += klass->parent->class_size;
7947                 klass->min_align = klass->parent->min_align;
7948         } else {
7949                 klass->instance_size = sizeof (MonoObject);
7950                 klass->min_align = 1;
7951         }
7952
7953         /* FIXME: handle packing_size and instance_size */
7954         typebuilder_setup_fields (klass);
7955
7956         typebuilder_setup_properties (klass);
7957
7958         typebuilder_setup_events (klass);
7959
7960         res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
7961         /* with enums res == tb: need to fix that. */
7962         if (!klass->enumtype)
7963                 g_assert (res != (MonoReflectionType*)tb);
7964         return res;
7965 }
7966
7967 void
7968 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
7969 {
7970         MonoGenericParam *param;
7971         MonoImage *image;
7972
7973         MONO_ARCH_SAVE_REGS;
7974
7975         param = g_new0 (MonoGenericParam, 1);
7976
7977         param->method = NULL;
7978         param->name = mono_string_to_utf8 (gparam->name);
7979         param->num = gparam->index;
7980
7981         image = &gparam->tbuilder->module->dynamic_image->image;
7982         mono_class_from_generic_parameter (param, image, gparam->mbuilder != NULL);
7983
7984         param->pklass->reflection_info = gparam;
7985
7986         gparam->type.type = g_new0 (MonoType, 1);
7987         gparam->type.type->type = gparam->mbuilder ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
7988         gparam->type.type->attrs = TYPE_ATTRIBUTE_PUBLIC;
7989         gparam->type.type->data.generic_param = param;
7990 }
7991
7992 MonoArray *
7993 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
7994 {
7995         MonoDynamicImage *assembly = sig->module->dynamic_image;
7996         guint32 na = mono_array_length (sig->arguments);
7997         guint32 buflen, i;
7998         MonoArray *result;
7999         char *buf, *p;
8000
8001         MONO_ARCH_SAVE_REGS;
8002
8003         p = buf = g_malloc (10 + na * 10);
8004
8005         mono_metadata_encode_value (0x07, p, &p);
8006         mono_metadata_encode_value (na, p, &p);
8007         for (i = 0; i < na; ++i) {
8008                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8009                 encode_reflection_type (assembly, type, p, &p);
8010         }
8011
8012         buflen = p - buf;
8013         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8014         p = mono_array_addr (result, char, 0);
8015         memcpy (p, buf, buflen);
8016         g_free (buf);
8017
8018         return result;
8019 }
8020
8021 MonoArray *
8022 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
8023 {
8024         MonoDynamicImage *assembly = sig->module->dynamic_image;
8025         guint32 na = mono_array_length (sig->arguments);
8026         guint32 buflen, i;
8027         MonoArray *result;
8028         char *buf, *p;
8029
8030         MONO_ARCH_SAVE_REGS;
8031
8032         p = buf = g_malloc (10 + na * 10);
8033
8034         mono_metadata_encode_value (0x06, p, &p);
8035         for (i = 0; i < na; ++i) {
8036                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
8037                 encode_reflection_type (assembly, type, p, &p);
8038         }
8039
8040         buflen = p - buf;
8041         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
8042         p = mono_array_addr (result, char, 0);
8043         memcpy (p, buf, buflen);
8044         g_free (buf);
8045
8046         return result;
8047 }
8048
8049 void 
8050 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
8051 {
8052         ReflectionMethodBuilder rmb;
8053         MonoMethodSignature *sig;
8054         int i;
8055
8056         sig = dynamic_method_to_signature (mb);
8057
8058         reflection_methodbuilder_from_dynamic_method (&rmb, mb);
8059
8060         /*
8061          * Resolve references.
8062          */
8063         rmb.nrefs = mb->nrefs;
8064         rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
8065         for (i = 0; i < mb->nrefs; ++i) {
8066                 gpointer ref = resolve_object (mb->module->image, 
8067                                                mono_array_get (mb->refs, MonoObject*, i));
8068                 if (!ref) {
8069                         g_free (rmb.refs);
8070                         mono_raise_exception (mono_get_exception_type_load (NULL));
8071                         return;
8072                 }
8073                 rmb.refs [i] = ref;
8074         }               
8075
8076         /* FIXME: class */
8077         mb->mhandle = reflection_methodbuilder_to_mono_method (mono_defaults.object_class, &rmb, sig);
8078
8079         g_free (rmb.refs);
8080
8081         /* ilgen is no longer needed */
8082         mb->ilgen = NULL;
8083 }
8084
8085 /**
8086  * mono_reflection_lookup_dynamic_token:
8087  *
8088  *  Finish the Builder object pointed to by TOKEN and return the corresponding
8089  * runtime structure.
8090  */
8091 gpointer
8092 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token)
8093 {
8094         MonoDynamicImage *assembly = (MonoDynamicImage*)image;
8095         MonoObject *obj;
8096
8097         obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
8098         g_assert (obj);
8099
8100         return resolve_object (image, obj);
8101 }
8102
8103 static gpointer
8104 resolve_object (MonoImage *image, MonoObject *obj)
8105 {
8106         gpointer result = NULL;
8107
8108         if (strcmp (obj->vtable->klass->name, "String") == 0) {
8109                 result = mono_string_intern ((MonoString*)obj);
8110                 g_assert (result);
8111         }
8112         else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
8113                 MonoReflectionType *tb = (MonoReflectionType*)obj;
8114                 result = mono_class_from_mono_type (tb->type);
8115                 g_assert (result);
8116         }
8117         else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0) {
8118                 result = ((MonoReflectionMethod*)obj)->method;
8119                 g_assert (result);
8120         }
8121         else if (strcmp (obj->vtable->klass->name, "MonoCMethod") == 0) {
8122                 result = ((MonoReflectionMethod*)obj)->method;
8123                 g_assert (result);
8124         }
8125         else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
8126                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8127                 result = mb->mhandle;
8128                 if (!result) {
8129                         /* Type is not yet created */
8130                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
8131
8132                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8133
8134                         /*
8135                          * Hopefully this has been filled in by calling CreateType() on the
8136                          * TypeBuilder.
8137                          */
8138                         /**
8139                          * TODO: This won't work if the application finishes another 
8140                          * TypeBuilder instance instead of this one.
8141                          */
8142                         result = mb->mhandle;
8143                 }
8144         }
8145         else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
8146                 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8147
8148                 result = cb->mhandle;
8149                 if (!result) {
8150                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
8151
8152                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8153                         result = cb->mhandle;
8154                 }
8155         }
8156         else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
8157                 result = ((MonoReflectionField*)obj)->field;
8158                 g_assert (result);
8159         }
8160         else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
8161                 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8162                 result = fb->handle;
8163
8164                 if (!result) {
8165                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
8166
8167                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8168                         result = fb->handle;
8169                 }
8170         }
8171         else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
8172                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8173                 MonoClass *klass;
8174
8175                 klass = tb->type.type->data.klass;
8176                 if (klass->wastypebuilder) {
8177                         /* Already created */
8178                         result = klass;
8179                 }
8180                 else {
8181                         mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
8182                         result = tb->type.type->data.klass;
8183                         g_assert (result);
8184                 }
8185         }
8186         else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
8187                 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
8188                 MonoMethodSignature *sig;
8189                 int nargs, i;
8190
8191                 if (helper->arguments)
8192                         nargs = mono_array_length (helper->arguments);
8193                 else
8194                         nargs = 0;
8195
8196                 sig = mono_metadata_signature_alloc (image, nargs);
8197                 sig->explicit_this = helper->call_conv & 64;
8198                 sig->hasthis = helper->call_conv & 32;
8199
8200                 if (helper->call_conv == 0) /* unmanaged */
8201                         sig->call_convention = helper->unmanaged_call_conv - 1;
8202                 else
8203                         if (helper->call_conv & 0x02)
8204                                 sig->call_convention = MONO_CALL_VARARG;
8205                 else
8206                         sig->call_convention = MONO_CALL_DEFAULT;
8207
8208                 sig->param_count = nargs;
8209                 /* TODO: Copy type ? */
8210                 sig->ret = helper->return_type->type;
8211                 for (i = 0; i < nargs; ++i) {
8212                         MonoReflectionType *rt = mono_array_get (helper->arguments, MonoReflectionType*, i);
8213                         sig->params [i] = rt->type;
8214                 }
8215
8216                 result = sig;
8217         }
8218         else {
8219                 g_print (obj->vtable->klass->name);
8220                 g_assert_not_reached ();
8221         }
8222         return result;
8223 }