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