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