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