2002-04-23 Patrik Torstensson <patrik.torstensson@labs2.com>
[mono.git] / mono / metadata / reflection.c
1
2 /*
3  * reflection.c: Routines for creating an image at runtime.
4  * 
5  * Author:
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2001, 2002 Ximian, Inc.  http://www.ximian.com
9  *
10  */
11 #include <config.h>
12 #include "mono/metadata/reflection.h"
13 #include "mono/metadata/tabledefs.h"
14 #include "mono/metadata/tokentype.h"
15 #include "mono/metadata/appdomain.h"
16 #include "mono/metadata/opcodes.h"
17 #include <stdio.h>
18 #include <glib.h>
19 #include <errno.h>
20 #include <time.h>
21 #include <string.h>
22 #include "image.h"
23 #include "cil-coff.h"
24 #include "rawbuffer.h"
25 #include "mono-endian.h"
26 #include "private.h"
27 #if HAVE_BOEHM_GC
28 #include <gc/gc.h>
29 #endif
30
31 #define TEXT_OFFSET 512
32 #define CLI_H_SIZE 136
33 #define FILE_ALIGN 512
34 #define START_TEXT_RVA  0x00002000
35
36 typedef struct {
37         MonoReflectionILGen *ilgen;
38         MonoReflectionType *rtype;
39         MonoArray *parameters;
40         MonoArray *pinfo;
41         guint32 attrs;
42         guint32 iattrs;
43         guint32 call_conv;
44         guint32 *table_idx; /* note: it's a pointer */
45         MonoArray *code;
46         MonoObject *type;
47         MonoString *name;
48 } ReflectionMethodBuilder;
49
50 const unsigned char table_sizes [64] = {
51         MONO_MODULE_SIZE,
52         MONO_TYPEREF_SIZE,
53         MONO_TYPEDEF_SIZE,
54         0,
55         MONO_FIELD_SIZE,
56         0,
57         MONO_METHOD_SIZE,
58         0,
59         MONO_PARAM_SIZE,
60         MONO_INTERFACEIMPL_SIZE,
61         MONO_MEMBERREF_SIZE,    /* 0x0A */
62         MONO_CONSTANT_SIZE,
63         MONO_CUSTOM_ATTR_SIZE,
64         MONO_FIELD_MARSHAL_SIZE,
65         MONO_DECL_SECURITY_SIZE,
66         MONO_CLASS_LAYOUT_SIZE,
67         MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
68         MONO_STAND_ALONE_SIGNATURE_SIZE,
69         MONO_EVENT_MAP_SIZE,
70         0,
71         MONO_EVENT_SIZE,
72         MONO_PROPERTY_MAP_SIZE,
73         0,
74         MONO_PROPERTY_SIZE,
75         MONO_METHOD_SEMA_SIZE,
76         MONO_MTHODIMPL_SIZE,
77         MONO_MODULEREF_SIZE,    /* 0x1A */
78         MONO_TYPESPEC_SIZE,
79         MONO_IMPLMAP_SIZE,      
80         MONO_FIELD_RVA_SIZE,
81         0,
82         0,
83         MONO_ASSEMBLY_SIZE,     /* 0x20 */
84         MONO_ASSEMBLY_PROCESSOR_SIZE,
85         MONO_ASSEMBLYOS_SIZE,
86         MONO_ASSEMBLYREF_SIZE,
87         MONO_ASSEMBLYREFPROC_SIZE,
88         MONO_ASSEMBLYREFOS_SIZE,
89         MONO_FILE_SIZE,
90         MONO_EXP_TYPE_SIZE,
91         MONO_MANIFEST_SIZE,
92         MONO_NESTED_CLASS_SIZE,
93         0       /* 0x2A */
94 };
95
96 static guint32 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type);
97 static guint32 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method);
98
99 static void
100 alloc_table (MonoDynamicTable *table, guint nrows)
101 {
102         table->rows = nrows;
103         g_assert (table->columns);
104         table->values = g_realloc (table->values, (1 + table->rows) * table->columns * sizeof (guint32));
105 }
106
107 static guint32
108 string_heap_insert (MonoDynamicStream *sh, const char *str)
109 {
110         guint32 idx;
111         guint32 len;
112         gpointer oldkey, oldval;
113
114         if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
115                 return GPOINTER_TO_UINT (oldval);
116
117         len = strlen (str) + 1;
118         idx = sh->index;
119         if (idx + len > sh->alloc_size) {
120                 sh->alloc_size += len + 4096;
121                 sh->data = g_realloc (sh->data, sh->alloc_size);
122         }
123         /*
124          * We strdup the string even if we already copy them in sh->data
125          * so that the string pointers in the hash remain valid even if
126          * we need to realloc sh->data. We may want to avoid that later.
127          */
128         g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
129         memcpy (sh->data + idx, str, len);
130         sh->index += len;
131         return idx;
132 }
133
134 static void
135 string_heap_init (MonoDynamicStream *sh)
136 {
137         sh->index = 0;
138         sh->alloc_size = 4096;
139         sh->data = g_malloc (4096);
140         sh->hash = g_hash_table_new (g_str_hash, g_str_equal);
141         string_heap_insert (sh, "");
142 }
143
144 #if 0 /* never used */
145 static void
146 string_heap_free (MonoDynamicStream *sh)
147 {
148         g_free (sh->data);
149         g_hash_table_foreach (sh->hash, (GHFunc)g_free, NULL);
150         g_hash_table_destroy (sh->hash);
151 }
152 #endif
153
154 static guint32
155 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
156 {
157         guint32 idx;
158         if (stream->alloc_size < stream->index + len) {
159                 stream->alloc_size += len + 4096;
160                 stream->data = g_realloc (stream->data, stream->alloc_size);
161         }
162         memcpy (stream->data + stream->index, data, len);
163         idx = stream->index;
164         stream->index += len;
165         /* 
166          * align index? Not without adding an additional param that controls it since
167          * we may store a blob value in pieces.
168          */
169         return idx;
170 }
171
172 static void
173 stream_data_align (MonoDynamicStream *stream)
174 {
175         char buf [4] = {0};
176         guint32 count = stream->index % 4;
177
178         /* we assume the stream data will be aligned */
179         if (count)
180                 mono_image_add_stream_data (stream, buf, 4 - count);
181 }
182
183 static void
184 encode_type (MonoDynamicAssembly *assembly, MonoType *type, char *p, char **endbuf)
185 {
186         if (!type) {
187                 g_assert_not_reached ();
188                 return;
189         }
190                 
191         if (type->byref)
192                 mono_metadata_encode_value (MONO_TYPE_BYREF, p, &p);
193
194         switch (type->type){
195         case MONO_TYPE_VOID:
196         case MONO_TYPE_BOOLEAN:
197         case MONO_TYPE_CHAR:
198         case MONO_TYPE_I1:
199         case MONO_TYPE_U1:
200         case MONO_TYPE_I2:
201         case MONO_TYPE_U2:
202         case MONO_TYPE_I4:
203         case MONO_TYPE_U4:
204         case MONO_TYPE_I8:
205         case MONO_TYPE_U8:
206         case MONO_TYPE_R4:
207         case MONO_TYPE_R8:
208         case MONO_TYPE_I:
209         case MONO_TYPE_U:
210         case MONO_TYPE_STRING:
211         case MONO_TYPE_OBJECT:
212         case MONO_TYPE_TYPEDBYREF:
213                 mono_metadata_encode_value (type->type, p, &p);
214                 break;
215         case MONO_TYPE_PTR:
216         case MONO_TYPE_SZARRAY:
217                 mono_metadata_encode_value (type->type, p, &p);
218                 encode_type (assembly, type->data.type, p, &p);
219                 break;
220         case MONO_TYPE_VALUETYPE:
221         case MONO_TYPE_CLASS:
222                 mono_metadata_encode_value (type->type, p, &p);
223                 mono_metadata_encode_value (mono_image_typedef_or_ref (assembly, type), p, &p);
224                 break;
225         case MONO_TYPE_ARRAY:
226                 mono_metadata_encode_value (type->type, p, &p);
227                 encode_type (assembly, type->data.array->type, p, &p);
228                 mono_metadata_encode_value (type->data.array->rank, p, &p);
229                 mono_metadata_encode_value (0, p, &p); /* FIXME: set to 0 for now */
230                 mono_metadata_encode_value (0, p, &p);
231                 break;
232         default:
233                 g_error ("need to encode type %x", type->type);
234         }
235         *endbuf = p;
236 }
237
238 static void
239 encode_reflection_type (MonoDynamicAssembly *assembly, MonoReflectionType *type, char *p, char **endbuf)
240 {
241         if (!type) {
242                 mono_metadata_encode_value (MONO_TYPE_VOID, p, endbuf);
243                 return;
244         }
245         if (type->type) {
246                 encode_type (assembly, type->type, p, endbuf);
247                 return;
248         }
249
250         g_assert_not_reached ();
251
252 }
253
254 static guint32
255 method_encode_signature (MonoDynamicAssembly *assembly, MonoMethodSignature *sig)
256 {
257         char *buf;
258         char *p;
259         int i;
260         guint32 nparams =  sig->param_count;
261         guint32 size = 10 + nparams * 10;
262         guint32 idx;
263         char blob_size [6];
264         char *b = blob_size;
265         
266         p = buf = g_malloc (size);
267         /*
268          * FIXME: vararg, explicit_this, differenc call_conv values...
269          */
270         *p = sig->call_convention;
271         if (sig->hasthis)
272                 *p |= 0x20; /* hasthis */
273         p++;
274         mono_metadata_encode_value (nparams, p, &p);
275         encode_type (assembly, sig->ret, p, &p);
276         for (i = 0; i < nparams; ++i)
277                 encode_type (assembly, sig->params [i], p, &p);
278         /* store length */
279         g_assert (p - buf < size);
280         mono_metadata_encode_value (p-buf, b, &b);
281         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
282         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
283         g_free (buf);
284         return idx;
285 }
286
287 static guint32
288 method_builder_encode_signature (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
289 {
290         /*
291          * FIXME: reuse code from method_encode_signature().
292          */
293         char *buf;
294         char *p;
295         int i;
296         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
297         guint32 size = 10 + nparams * 10;
298         guint32 idx;
299         char blob_size [6];
300         char *b = blob_size;
301         
302         p = buf = g_malloc (size);
303         /* LAMESPEC: all the call conv spec is foobared */
304         *p = mb->call_conv & 0x60; /* has-this, explicit-this */
305         if (mb->call_conv & 2)
306                 *p |= 0x5; /* vararg */
307         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
308                 *p |= 0x20; /* hasthis */
309         p++;
310         mono_metadata_encode_value (nparams, p, &p);
311         encode_reflection_type (assembly, mb->rtype, p, &p);
312         for (i = 0; i < nparams; ++i) {
313                 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
314                 encode_reflection_type (assembly, pt, p, &p);
315         }
316         /* store length */
317         g_assert (p - buf < size);
318         mono_metadata_encode_value (p-buf, b, &b);
319         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
320         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
321         g_free (buf);
322         return idx;
323 }
324
325 static guint32
326 encode_locals (MonoDynamicAssembly *assembly, MonoReflectionILGen *ilgen)
327 {
328         MonoDynamicTable *table;
329         guint32 *values;
330         char *p;
331         guint32 idx, sig_idx, size;
332         guint nl = mono_array_length (ilgen->locals);
333         char *buf;
334         char blob_size [6];
335         char *b = blob_size;
336         int i;
337
338         size = 10 + nl * 10;
339         p = buf = g_malloc (size);
340         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
341         idx = table->next_idx ++;
342         table->rows ++;
343         alloc_table (table, table->rows);
344         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
345
346         mono_metadata_encode_value (0x07, p, &p);
347         mono_metadata_encode_value (nl, p, &p);
348         for (i = 0; i < nl; ++i) {
349                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
350                 encode_reflection_type (assembly, lb->type, p, &p);
351         }
352         g_assert (p - buf < size);
353         mono_metadata_encode_value (p-buf, b, &b);
354         sig_idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
355         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
356         g_free (buf);
357
358         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
359
360         return idx;
361 }
362
363 static guint32
364 method_encode_code (MonoDynamicAssembly *assembly, ReflectionMethodBuilder *mb)
365 {
366         char flags = 0;
367         guint32 idx;
368         guint32 code_size;
369         gint32 max_stack, i;
370         gint32 num_locals = 0;
371         gint32 num_exception = 0;
372         gint maybe_small;
373         guint32 fat_flags;
374         char fat_header [12];
375         guint32 *intp;
376         guint16 *shortp;
377         guint32 local_sig = 0;
378         guint32 header_size = 12;
379         MonoArray *code;
380
381         if ((mb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
382                         (mb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
383                         (mb->iattrs & METHOD_IMPL_ATTRIBUTE_RUNTIME) ||
384                         (mb->attrs & METHOD_ATTRIBUTE_ABSTRACT))
385                 return 0;
386
387         /*if (mb->name)
388                 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
389         if (mb->ilgen) {
390                 code = mb->ilgen->code;
391                 code_size = mb->ilgen->code_len;
392                 max_stack = mb->ilgen->max_stack;
393                 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
394                 if (mb->ilgen->ex_handlers) {
395                         MonoILExceptionInfo *ex_info;
396                         for (i = 0; i < mono_array_length (mb->ilgen->ex_handlers); ++i) {
397                                 ex_info = (MonoILExceptionInfo*)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
398                                 if (ex_info->handlers)
399                                         num_exception += mono_array_length (ex_info->handlers);
400                                 else
401                                         num_exception++;
402                         }
403                 }
404         } else {
405                 code = mb->code;
406                 code_size = mono_array_length (code);
407                 max_stack = 8; /* we probably need to run a verifier on the code... */
408         }
409
410         /* check for exceptions, maxstack, locals */
411         maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
412         if (maybe_small) {
413                 if (code_size < 64 && !(code_size & 1)) {
414                         flags = (code_size << 2) | 0x2;
415                 } else if (code_size < 32 && (code_size & 1)) {
416                         flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
417                 } else {
418                         goto fat_header;
419                 }
420                 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
421                 /* add to the fixup todo list */
422                 if (mb->ilgen && mb->ilgen->num_token_fixups)
423                         mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
424                 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
425                 return assembly->text_rva + idx + CLI_H_SIZE;
426         } 
427 fat_header:
428         if (num_locals)
429                 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
430         /* 
431          * FIXME: need to set also the header size in fat_flags.
432          * (and more sects and init locals flags)
433          */
434         fat_flags =  0x03;
435         if (num_exception)
436                 fat_flags |= METHOD_HEADER_MORE_SECTS;
437         fat_header [0] = fat_flags;
438         fat_header [1] = (header_size / 4 ) << 4;
439         shortp = (guint16*)(fat_header + 2);
440         *shortp = max_stack;
441         intp = (guint32*)(fat_header + 4);
442         *intp = code_size;
443         intp = (guint32*)(fat_header + 8);
444         *intp = local_sig;
445         idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
446         /* add to the fixup todo list */
447         if (mb->ilgen && mb->ilgen->num_token_fixups)
448                 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
449         
450         mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
451         if (num_exception) {
452                 unsigned char sheader [4];
453                 MonoExceptionClause clause;
454                 MonoILExceptionInfo * ex_info;
455                 MonoILExceptionBlock * ex_block;
456                 int j;
457
458                 stream_data_align (&assembly->code);
459                 /* always use fat format for now */
460                 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
461                 num_exception *= sizeof (MonoExceptionClause);
462                 sheader [1] = num_exception & 0xff;
463                 sheader [2] = (num_exception >> 8) & 0xff;
464                 sheader [3] = (num_exception >> 16) & 0xff;
465                 mono_image_add_stream_data (&assembly->code, sheader, 4);
466                 /* fat header, so we are already aligned */
467                 /* reverse order */
468                 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
469                         ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
470                         if (ex_info->handlers) {
471                                 int finally_start = 0;
472                                 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
473                                         ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
474                                         clause.flags = ex_block->type;
475                                         clause.try_offset = ex_info->start;
476                                         /* need fault, too, probably */
477                                         if (clause.flags == MONO_EXCEPTION_CLAUSE_FINALLY)
478                                                 clause.try_len = finally_start - ex_info->start;
479                                         else
480                                                 clause.try_len = ex_info->len;
481                                         clause.handler_offset = ex_block->start;
482                                         clause.handler_len = ex_block->len;
483                                         finally_start = clause.handler_offset + clause.handler_len;
484                                         clause.token_or_filter = ex_block->extype ? mono_metadata_token_from_dor (
485                                                         mono_image_typedef_or_ref (assembly, ex_block->extype->type)): 0;
486                                         /*g_print ("out clause %d: from %d len=%d, handler at %d, %d\n", 
487                                                         clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len);*/
488                                         /* FIXME: ENOENDIAN */
489                                         mono_image_add_stream_data (&assembly->code, (char*)&clause, sizeof (clause));
490                                 }
491                         } else {
492                                 g_error ("No clauses for ex info block %d", i);
493                         }
494                 }
495         }
496         return assembly->text_rva + idx + CLI_H_SIZE;
497 }
498
499 static guint32
500 find_index_in_table (MonoDynamicAssembly *assembly, int table_idx, int col, guint32 token)
501 {
502         int i;
503         MonoDynamicTable *table;
504         guint32 *values;
505         
506         table = &assembly->tables [table_idx];
507
508         g_assert (col < table->columns);
509
510         values = table->values + table->columns;
511         for (i = 1; i <= table->rows; ++i) {
512                 if (values [col] == token)
513                         return i;
514         }
515         return 0;
516 }
517
518 /*
519  * idx is the table index of the object
520  * type is one of CUSTOM_ATTR_*
521  */
522 static void
523 mono_image_add_cattrs (MonoDynamicAssembly *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
524 {
525         MonoDynamicTable *table;
526         MonoReflectionCustomAttr *cattr;
527         guint32 *values;
528         guint32 count, i, token;
529         char blob_size [6];
530         char *p = blob_size;
531         
532         /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
533         if (!cattrs)
534                 return;
535         count = mono_array_length (cattrs);
536         table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
537         table->rows += count;
538         alloc_table (table, table->rows);
539         values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
540         idx <<= CUSTOM_ATTR_BITS;
541         idx |= type;
542         for (i = 0; i < count; ++i) {
543                 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
544                 values [MONO_CUSTOM_ATTR_PARENT] = idx;
545                 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor);
546                 type = mono_metadata_token_index (token);
547                 type <<= CUSTOM_ATTR_TYPE_BITS;
548                 switch (mono_metadata_token_table (token)) {
549                 case MONO_TABLE_METHOD:
550                         type |= CUSTOM_ATTR_TYPE_METHODDEF;
551                         break;
552                 case MONO_TABLE_MEMBERREF:
553                         type |= CUSTOM_ATTR_TYPE_MEMBERREF;
554                         break;
555                 default:
556                         g_error ("got wrong token in custom attr");
557                 }
558                 values [MONO_CUSTOM_ATTR_TYPE] = type;
559                 p = blob_size;
560                 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
561                 values [MONO_CUSTOM_ATTR_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, p - blob_size);
562                 mono_image_add_stream_data (&assembly->blob,
563                         mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
564                 values += MONO_CUSTOM_ATTR_SIZE;
565                 ++table->next_idx;
566         }
567 }
568
569 /*
570  * Fill in the MethodDef and ParamDef tables for a method.
571  * This is used for both normal methods and constructors.
572  */
573 static void
574 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
575 {
576         MonoDynamicTable *table;
577         guint32 *values;
578         char *name;
579         guint i, count;
580
581         /* room in this table is already allocated */
582         table = &assembly->tables [MONO_TABLE_METHOD];
583         *mb->table_idx = table->next_idx ++;
584         values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
585         if (mb->name) {
586                 name = mono_string_to_utf8 (mb->name);
587                 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, name);
588                 g_free (name);
589         } else { /* a constructor */
590                 values [MONO_METHOD_NAME] = string_heap_insert (&assembly->sheap, mb->attrs & METHOD_ATTRIBUTE_STATIC? ".cctor": ".ctor");
591         }
592         values [MONO_METHOD_FLAGS] = mb->attrs;
593         values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
594         values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
595         values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
596         
597         table = &assembly->tables [MONO_TABLE_PARAM];
598         values [MONO_METHOD_PARAMLIST] = table->next_idx;
599
600         if (mb->pinfo) {
601                 count = 0;
602                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
603                         if (mono_array_get (mb->pinfo, gpointer, i))
604                                 count++;
605                 }
606                 table->rows += count;
607                 alloc_table (table, table->rows);
608                 values = table->values + table->next_idx * MONO_PARAM_SIZE;
609                 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
610                         MonoReflectionParamBuilder *pb;
611                         if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
612                                 values [MONO_PARAM_FLAGS] = pb->attrs;
613                                 values [MONO_PARAM_SEQUENCE] = i;
614                                 name = mono_string_to_utf8 (pb->name);
615                                 values [MONO_PARAM_NAME] = string_heap_insert (&assembly->sheap, name);
616                                 g_free (name);
617                                 values += MONO_PARAM_SIZE;
618                                 table->next_idx++;
619                                 mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PARAMDEF, pb->cattrs);
620                         }
621                 }
622         }
623 }
624
625 static void
626 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicAssembly *assembly)
627 {
628         MonoDynamicTable *table;
629         guint32 *values;
630         char *name;
631         ReflectionMethodBuilder rmb;
632
633         rmb.ilgen = mb->ilgen;
634         rmb.rtype = mb->rtype;
635         rmb.parameters = mb->parameters;
636         rmb.pinfo = mb->pinfo;
637         rmb.attrs = mb->attrs;
638         rmb.iattrs = mb->iattrs;
639         rmb.call_conv = mb->call_conv;
640         rmb.code = mb->code;
641         rmb.type = mb->type;
642         rmb.name = mb->name;
643         rmb.table_idx = &mb->table_idx;
644
645         mono_image_basic_method (&rmb, assembly);
646
647         if (mb->dll) { /* It's a P/Invoke method */
648                 guint32 moduleref;
649                 table = &assembly->tables [MONO_TABLE_IMPLMAP];
650                 table->rows ++;
651                 alloc_table (table, table->rows);
652                 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
653                 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | mb->charset;
654                 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
655                 name = mono_string_to_utf8 (mb->dllentry);
656                 values [MONO_IMPLMAP_NAME] = string_heap_insert (&assembly->sheap, name);
657                 g_free (name);
658                 name = mono_string_to_utf8 (mb->dll);
659                 moduleref = string_heap_insert (&assembly->sheap, name);
660                 g_free (name);
661                 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
662                         table = &assembly->tables [MONO_TABLE_MODULEREF];
663                         table->rows ++;
664                         alloc_table (table, table->rows);
665                         table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
666                         values [MONO_IMPLMAP_SCOPE] = table->rows;
667                 }
668         }
669         if (mb->override_method) {
670                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
671                 table = &assembly->tables [MONO_TABLE_METHODIMPL];
672                 table->rows ++;
673                 alloc_table (table, table->rows);
674                 values = table->values + table->rows * MONO_MTHODIMPL_SIZE;
675                 values [MONO_MTHODIMPL_CLASS] = tb->table_idx;
676                 values [MONO_MTHODIMPL_BODY] = METHODDEFORREF_METHODDEF | (mb->table_idx << METHODDEFORREF_BITS);
677                 if (mb->override_method->method)
678                         values [MONO_MTHODIMPL_DECLARATION] = mono_image_get_methodref_token (assembly, mb->override_method->method);
679                 else {
680                         MonoReflectionMethodBuilder *omb = (MonoReflectionMethodBuilder*)mb->override_method;
681                         values [MONO_MTHODIMPL_DECLARATION] = METHODDEFORREF_METHODDEF | (omb->table_idx << METHODDEFORREF_BITS);
682                 }
683         }
684         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
685 }
686
687 static void
688 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicAssembly *assembly)
689 {
690         ReflectionMethodBuilder rmb;
691
692         rmb.ilgen = mb->ilgen;
693         rmb.rtype = mono_type_get_object (domain, &mono_defaults.void_class->byval_arg);
694         rmb.parameters = mb->parameters;
695         rmb.pinfo = mb->pinfo;
696         rmb.attrs = mb->attrs;
697         rmb.iattrs = mb->iattrs;
698         rmb.call_conv = mb->call_conv;
699         rmb.code = NULL;
700         rmb.type = mb->type;
701         rmb.name = NULL;
702         rmb.table_idx = &mb->table_idx;
703
704         mono_image_basic_method (&rmb, assembly);
705         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_METHODDEF, mb->cattrs);
706
707 }
708
709 static guint32
710 fieldref_encode_signature (MonoDynamicAssembly *assembly, MonoClassField *field)
711 {
712         char blob_size [64];
713         char *b = blob_size;
714         char *p;
715         char* buf;
716         guint32 idx;
717         
718         p = buf = g_malloc (64);
719         
720         /* No start code with field refs...
721          * mono_metadata_encode_value (0x06, p, &p);
722          */
723         /* encode custom attributes before the type */
724         encode_type (assembly, field->type, p, &p);
725         g_assert (p-buf < 64);
726         mono_metadata_encode_value (p-buf, b, &b);
727         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
728         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
729         g_free (buf);
730         return idx;
731 }
732
733 static guint32
734 field_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionFieldBuilder *fb)
735 {
736         char blob_size [64];
737         char *b = blob_size;
738         char *p;
739         char* buf;
740         guint32 idx;
741         
742         p = buf = g_malloc (64);
743         
744         mono_metadata_encode_value (0x06, p, &p);
745         /* encode custom attributes before the type */
746         encode_reflection_type (assembly, fb->type, p, &p);
747         g_assert (p-buf < 64);
748         mono_metadata_encode_value (p-buf, b, &b);
749         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
750         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
751         g_free (buf);
752         return idx;
753 }
754
755 static guint32
756 encode_constant (MonoDynamicAssembly *assembly, MonoObject *val, guint32 *ret_type) {
757         char blob_size [64];
758         char *b = blob_size;
759         char *p, *box_val;
760         char* buf;
761         guint32 idx, len;
762         
763         p = buf = g_malloc (64);
764
765         box_val = ((char*)val) + sizeof (MonoObject);
766         *ret_type = val->vtable->klass->byval_arg.type;
767 handle_enum:
768         switch (*ret_type) {
769         case MONO_TYPE_BOOLEAN:
770         case MONO_TYPE_U1:
771         case MONO_TYPE_I1:
772                 len = 1;
773                 break;
774         case MONO_TYPE_CHAR:
775         case MONO_TYPE_U2:
776         case MONO_TYPE_I2:
777                 len = 2;
778                 break;
779         case MONO_TYPE_U4:
780         case MONO_TYPE_I4:
781         case MONO_TYPE_R4:
782                 len = 4;
783                 break;
784         case MONO_TYPE_U8:
785         case MONO_TYPE_I8:
786         case MONO_TYPE_R8:
787                 len = 8;
788                 break;
789         case MONO_TYPE_VALUETYPE:
790                 if (val->vtable->klass->enumtype) {
791                         *ret_type = val->vtable->klass->enum_basetype->type;
792                         goto handle_enum;
793                 } else
794                         g_error ("we can't encode valuetypes");
795         case MONO_TYPE_STRING: {
796                 MonoString *str = (MonoString*)val;
797                 /* there is no signature */
798                 len = str->length * 2;
799                 mono_metadata_encode_value (len, b, &b);
800                 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
801                 /* FIXME: ENOENDIAN */
802                 mono_image_add_stream_data (&assembly->blob, (const char*)mono_string_chars (str), len);
803
804                 g_free (buf);
805                 return idx;
806         }
807         default:
808                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
809         }
810
811         /* there is no signature */
812         mono_metadata_encode_value (len, b, &b);
813         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
814         /* FIXME: ENOENDIAN */
815         mono_image_add_stream_data (&assembly->blob, box_val, len);
816
817         g_free (buf);
818         return idx;
819 }
820
821 static void
822 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicAssembly *assembly)
823 {
824         MonoDynamicTable *table;
825         guint32 *values;
826         char *name;
827
828         /* maybe this fixup should be done in the C# code */
829         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
830                 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
831         table = &assembly->tables [MONO_TABLE_FIELD];
832         fb->table_idx = table->next_idx ++;
833         values = table->values + fb->table_idx * MONO_FIELD_SIZE;
834         name = mono_string_to_utf8 (fb->name);
835         values [MONO_FIELD_NAME] = string_heap_insert (&assembly->sheap, name);
836         g_free (name);
837         values [MONO_FIELD_FLAGS] = fb->attrs;
838         values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
839
840         if (fb->offset != -1) {
841                 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
842                 table->rows ++;
843                 alloc_table (table, table->rows);
844                 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
845                 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
846                 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
847         }
848         if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
849                 guint32 field_type = 0;
850                 table = &assembly->tables [MONO_TABLE_CONSTANT];
851                 table->rows ++;
852                 alloc_table (table, table->rows);
853                 values = table->values + table->rows * MONO_CONSTANT_SIZE;
854                 values [MONO_CONSTANT_PARENT] = HASCONSTANT_FIEDDEF | (fb->table_idx << HASCONSTANT_BITS);
855                 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
856                 values [MONO_CONSTANT_TYPE] = field_type;
857                 values [MONO_CONSTANT_PADDING] = 0;
858         }
859         if (fb->rva_data) {
860                 guint32 rva_idx;
861                 table = &assembly->tables [MONO_TABLE_FIELDRVA];
862                 table->rows ++;
863                 alloc_table (table, table->rows);
864                 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
865                 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
866                 /*
867                  * We store it in the code section because it's simpler for now.
868                  */
869                 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
870                 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva + CLI_H_SIZE;
871         }
872         mono_image_add_cattrs (assembly, fb->table_idx, CUSTOM_ATTR_FIELDDEF, fb->cattrs);
873 }
874
875 static guint32
876 property_encode_signature (MonoDynamicAssembly *assembly, MonoReflectionPropertyBuilder *fb)
877 {
878         char *buf, *p;
879         char blob_size [6];
880         char *b = blob_size;
881         guint32 nparams = 0;
882         MonoReflectionMethodBuilder *mb = fb->get_method;
883         guint32 idx, i, size;
884
885         if (mb && mb->parameters)
886                 nparams = mono_array_length (mb->parameters);
887         size = 24 + nparams * 10;
888         buf = p = g_malloc (size);
889         *p = 0x08;
890         p++;
891         mono_metadata_encode_value (nparams, p, &p);
892         if (mb) {
893                 encode_reflection_type (assembly, mb->rtype, p, &p);
894                 for (i = 0; i < nparams; ++i) {
895                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
896                         encode_reflection_type (assembly, pt, p, &p);
897                 }
898         } else {
899                 *p++ = 1; /* void: a property should probably not be allowed without a getter */
900         }
901         /* store length */
902         g_assert (p - buf < size);
903         mono_metadata_encode_value (p-buf, b, &b);
904         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
905         mono_image_add_stream_data (&assembly->blob, buf, p-buf);
906         g_free (buf);
907         return idx;
908 }
909
910 static void
911 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicAssembly *assembly)
912 {
913         MonoDynamicTable *table;
914         guint32 *values;
915         char *name;
916         guint num_methods = 0;
917         guint32 semaidx;
918
919         /* 
920          * we need to set things in the following tables:
921          * PROPERTYMAP (info already filled in _get_type_info ())
922          * PROPERTY    (rows already preallocated in _get_type_info ())
923          * METHOD      (method info already done with the generic method code)
924          * METHODSEMANTICS
925          */
926         table = &assembly->tables [MONO_TABLE_PROPERTY];
927         pb->table_idx = table->next_idx ++;
928         values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
929         name = mono_string_to_utf8 (pb->name);
930         values [MONO_PROPERTY_NAME] = string_heap_insert (&assembly->sheap, name);
931         g_free (name);
932         values [MONO_PROPERTY_FLAGS] = pb->attrs;
933         values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
934
935         /* FIXME: we still don't handle 'other' methods */
936         if (pb->get_method) num_methods ++;
937         if (pb->set_method) num_methods ++;
938
939         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
940         table->rows += num_methods;
941         alloc_table (table, table->rows);
942
943         if (pb->get_method) {
944                 semaidx = table->next_idx ++;
945                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
946                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
947                 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
948                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
949         }
950         if (pb->set_method) {
951                 semaidx = table->next_idx ++;
952                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
953                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
954                 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
955                 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_PROPERTY;
956         }
957         mono_image_add_cattrs (assembly, pb->table_idx, CUSTOM_ATTR_PROPERTY, pb->cattrs);
958 }
959
960 static void
961 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicAssembly *assembly)
962 {
963         MonoDynamicTable *table;
964         guint32 *values;
965         char *name;
966         guint num_methods = 0;
967         guint32 semaidx;
968
969         /* 
970          * we need to set things in the following tables:
971          * EVENTMAP (info already filled in _get_type_info ())
972          * EVENT    (rows already preallocated in _get_type_info ())
973          * METHOD      (method info already done with the generic method code)
974          * METHODSEMANTICS
975          */
976         table = &assembly->tables [MONO_TABLE_EVENT];
977         eb->table_idx = table->next_idx ++;
978         values = table->values + eb->table_idx * MONO_EVENT_SIZE;
979         name = mono_string_to_utf8 (eb->name);
980         values [MONO_EVENT_NAME] = string_heap_insert (&assembly->sheap, name);
981         g_free (name);
982         values [MONO_EVENT_FLAGS] = eb->attrs;
983         values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, eb->type->type);
984
985         /*
986          * FIXME: we still don't handle 'other' methods 
987          */
988         if (eb->add_method) num_methods ++;
989         if (eb->remove_method) num_methods ++;
990         if (eb->raise_method) num_methods ++;
991
992         table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
993         table->rows += num_methods;
994         alloc_table (table, table->rows);
995
996         if (eb->add_method) {
997                 semaidx = table->next_idx ++;
998                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
999                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
1000                 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
1001                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1002         }
1003         if (eb->remove_method) {
1004                 semaidx = table->next_idx ++;
1005                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1006                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
1007                 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
1008                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1009         }
1010         if (eb->raise_method) {
1011                 semaidx = table->next_idx ++;
1012                 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
1013                 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
1014                 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
1015                 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << HAS_SEMANTICS_BITS) | HAS_SEMANTICS_EVENT;
1016         }
1017         mono_image_add_cattrs (assembly, eb->table_idx, CUSTOM_ATTR_EVENT, eb->cattrs);
1018 }
1019
1020 static guint32
1021 resolution_scope_from_image (MonoDynamicAssembly *assembly, MonoImage *image)
1022 {
1023         MonoDynamicTable *table;
1024         guint32 token;
1025         guint32 *values;
1026         guint32 cols [MONO_ASSEMBLY_SIZE];
1027
1028         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
1029                 return token;
1030
1031         mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
1032
1033         table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
1034         token = table->next_idx ++;
1035         table->rows ++;
1036         alloc_table (table, table->rows);
1037         values = table->values + token * MONO_ASSEMBLYREF_SIZE;
1038         if (strcmp ("corlib", image->assembly_name) == 0)
1039                 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, "mscorlib");
1040         else
1041                 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
1042         values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
1043         values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
1044         values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
1045         values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
1046         values [MONO_ASSEMBLYREF_FLAGS] = 0;
1047         values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
1048         values [MONO_ASSEMBLYREF_CULTURE] = 0;
1049         values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
1050
1051         token <<= RESOLTION_SCOPE_BITS;
1052         token |= RESOLTION_SCOPE_ASSEMBLYREF;
1053         g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
1054         return token;
1055 }
1056
1057 static guint32
1058 create_typespec (MonoDynamicAssembly *assembly, MonoType *type)
1059 {
1060         MonoDynamicTable *table;
1061         guint32 *values;
1062         guint32 token;
1063         char sig [128];
1064         char *p = sig;
1065         char blob_size [6];
1066         char *b = blob_size;
1067
1068         switch (type->type) {
1069         case MONO_TYPE_FNPTR:
1070         case MONO_TYPE_PTR:
1071         case MONO_TYPE_SZARRAY:
1072         case MONO_TYPE_ARRAY:
1073                 encode_type (assembly, type, p, &p);
1074                 break;
1075         default:
1076                 return 0;
1077         }
1078         
1079         g_assert (p-sig < 128);
1080         mono_metadata_encode_value (p-sig, b, &b);
1081         token = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1082         mono_image_add_stream_data (&assembly->blob, sig, p-sig);
1083
1084         table = &assembly->tables [MONO_TABLE_TYPESPEC];
1085         alloc_table (table, table->rows + 1);
1086         values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
1087         values [MONO_TYPESPEC_SIGNATURE] = token;
1088
1089         token = TYPEDEFORREF_TYPESPEC | (table->next_idx << TYPEDEFORREF_BITS);
1090         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1091         table->next_idx ++;
1092         return token;
1093 }
1094
1095 /*
1096  * Despite the name, we handle also TypeSpec (with the above helper).
1097  */
1098 static guint32
1099 mono_image_typedef_or_ref (MonoDynamicAssembly *assembly, MonoType *type)
1100 {
1101         MonoDynamicTable *table;
1102         guint32 *values;
1103         guint32 token;
1104         MonoClass *klass;
1105
1106         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
1107         if (token)
1108                 return token;
1109         token = create_typespec (assembly, type);
1110         if (token)
1111                 return token;
1112         klass = mono_class_from_mono_type (type);
1113         /*
1114          * If it's in the same module:
1115          */
1116         if (klass->image == assembly->assembly.image) {
1117                 MonoReflectionTypeBuilder *tb = klass->reflection_info;
1118                 return TYPEDEFORREF_TYPEDEF | (tb->table_idx << TYPEDEFORREF_BITS);
1119         }
1120
1121         table = &assembly->tables [MONO_TABLE_TYPEREF];
1122         alloc_table (table, table->rows + 1);
1123         values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
1124         values [MONO_TYPEREF_SCOPE] = resolution_scope_from_image (assembly, klass->image);
1125         values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
1126         values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
1127         token = TYPEDEFORREF_TYPEREF | (table->next_idx << TYPEDEFORREF_BITS); /* typeref */
1128         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
1129         table->next_idx ++;
1130         return token;
1131 }
1132
1133 /*
1134  * Insert a memberef row into the metadata: the token that point to the memberref
1135  * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
1136  * mono_image_get_fieldref_token()).
1137  * The sig param is an index to an already built signature.
1138  */
1139 static guint32
1140 mono_image_get_memberref_token (MonoDynamicAssembly *assembly, MonoClass *klass, const char *name, guint32 sig)
1141 {
1142         MonoDynamicTable *table;
1143         guint32 *values;
1144         guint32 token, pclass;
1145         guint32 parent;
1146
1147         parent = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
1148         switch (parent & TYPEDEFORREF_MASK) {
1149         case TYPEDEFORREF_TYPEREF:
1150                 pclass = MEMBERREF_PARENT_TYPEREF;
1151                 break;
1152         case TYPEDEFORREF_TYPESPEC:
1153                 pclass = MEMBERREF_PARENT_TYPESPEC;
1154                 break;
1155         case TYPEDEFORREF_TYPEDEF:
1156                 /* should never get here */
1157         default:
1158                 g_error ("unknow typeref or def token");
1159         }
1160         /* extract the index */
1161         parent >>= TYPEDEFORREF_BITS;
1162
1163         table = &assembly->tables [MONO_TABLE_MEMBERREF];
1164         alloc_table (table, table->rows + 1);
1165         values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
1166         values [MONO_MEMBERREF_CLASS] = pclass | (parent << MEMBERREF_PARENT_BITS);
1167         values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
1168         values [MONO_MEMBERREF_SIGNATURE] = sig;
1169         token = MONO_TOKEN_MEMBER_REF | table->next_idx;
1170         table->next_idx ++;
1171
1172         return token;
1173 }
1174
1175 static guint32
1176 mono_image_get_methodref_token (MonoDynamicAssembly *assembly, MonoMethod *method)
1177 {
1178         guint32 token;
1179         
1180         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
1181         if (token)
1182                 return token;
1183         token = mono_image_get_memberref_token (assembly, method->klass, 
1184                 method->name,  method_encode_signature (assembly, method->signature));
1185         g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
1186         return token;
1187 }
1188
1189 static guint32
1190 mono_image_get_fieldref_token (MonoDynamicAssembly *assembly, MonoClassField *field, MonoClass *klass)
1191 {
1192         guint32 token;
1193         
1194         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
1195         if (token)
1196                 return token;
1197         token = mono_image_get_memberref_token (assembly, klass, 
1198                 field->name,  fieldref_encode_signature (assembly, field));
1199         g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
1200         return token;
1201 }
1202
1203 /*
1204  * Insert into the metadata tables all the info about the TypeBuilder tb.
1205  * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
1206  */
1207 static void
1208 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicAssembly *assembly)
1209 {
1210         MonoDynamicTable *table;
1211         guint *values;
1212         int i;
1213         char *n;
1214
1215         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1216         values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
1217         values [MONO_TYPEDEF_FLAGS] = tb->attrs;
1218         if (tb->parent) { /* interfaces don't have a parent */
1219                 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, tb->parent->type);
1220         } else
1221                 values [MONO_TYPEDEF_EXTENDS] = 0;
1222         n = mono_string_to_utf8 (tb->name);
1223         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
1224         g_free (n);
1225         n = mono_string_to_utf8 (tb->nspace);
1226         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
1227         g_free (n);
1228         values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
1229         values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
1230
1231         /*
1232          * if we have explicitlayout or sequentiallayouts, output data in the
1233          * ClassLayout table.
1234          */
1235         if ((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1236                 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
1237                 table->rows++;
1238                 alloc_table (table, table->rows);
1239                 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
1240                 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
1241                 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
1242                 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
1243         }
1244
1245         /* handle interfaces */
1246         if (tb->interfaces) {
1247                 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
1248                 i = table->rows;
1249                 table->rows += mono_array_length (tb->interfaces);
1250                 alloc_table (table, table->rows);
1251                 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
1252                 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
1253                         MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
1254                         values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
1255                         values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, iface->type);
1256                         values += MONO_INTERFACEIMPL_SIZE;
1257                 }
1258         }
1259
1260         /* handle fields */
1261         if (tb->fields) {
1262                 table = &assembly->tables [MONO_TABLE_FIELD];
1263                 table->rows += mono_array_length (tb->fields);
1264                 alloc_table (table, table->rows);
1265                 for (i = 0; i < mono_array_length (tb->fields); ++i)
1266                         mono_image_get_field_info (
1267                                 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
1268         }
1269
1270         /* handle constructors */
1271         if (tb->ctors) {
1272                 table = &assembly->tables [MONO_TABLE_METHOD];
1273                 table->rows += mono_array_length (tb->ctors);
1274                 alloc_table (table, table->rows);
1275                 for (i = 0; i < mono_array_length (tb->ctors); ++i)
1276                         mono_image_get_ctor_info (domain,
1277                                 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
1278         }
1279
1280         /* handle methods */
1281         if (tb->methods) {
1282                 table = &assembly->tables [MONO_TABLE_METHOD];
1283                 table->rows += mono_array_length (tb->methods);
1284                 alloc_table (table, table->rows);
1285                 for (i = 0; i < mono_array_length (tb->methods); ++i)
1286                         mono_image_get_method_info (
1287                                 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
1288         }
1289
1290         /* Do the same with properties etc.. */
1291         /*
1292          * FIXME: note that the methodsemantics table needs to be sorted, so events
1293          * go before properties; not sure if this is enough...
1294          */
1295         if (tb->events && mono_array_length (tb->events)) {
1296                 table = &assembly->tables [MONO_TABLE_EVENT];
1297                 table->rows += mono_array_length (tb->events);
1298                 alloc_table (table, table->rows);
1299                 table = &assembly->tables [MONO_TABLE_EVENTMAP];
1300                 table->rows ++;
1301                 alloc_table (table, table->rows);
1302                 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
1303                 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
1304                 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
1305                 for (i = 0; i < mono_array_length (tb->events); ++i)
1306                         mono_image_get_event_info (
1307                                 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
1308         }
1309         if (tb->properties && mono_array_length (tb->properties)) {
1310                 table = &assembly->tables [MONO_TABLE_PROPERTY];
1311                 table->rows += mono_array_length (tb->properties);
1312                 alloc_table (table, table->rows);
1313                 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
1314                 table->rows ++;
1315                 alloc_table (table, table->rows);
1316                 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
1317                 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
1318                 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
1319                 for (i = 0; i < mono_array_length (tb->properties); ++i)
1320                         mono_image_get_property_info (
1321                                 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
1322         }
1323         if (tb->subtypes) {
1324                 MonoDynamicTable *ntable;
1325                 
1326                 table = &assembly->tables [MONO_TABLE_TYPEDEF];
1327                 table->rows += mono_array_length (tb->subtypes);
1328                 alloc_table (table, table->rows);
1329
1330                 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
1331                 ntable->rows += mono_array_length (tb->subtypes);
1332                 alloc_table (ntable, ntable->rows);
1333                 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
1334
1335                 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
1336                         MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
1337
1338                         mono_image_get_type_info (domain, subtype, assembly);
1339                         values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
1340                         values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
1341                         /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
1342                                 mono_string_to_utf8 (subtype->name), subtype->table_idx,
1343                                 mono_string_to_utf8 (tb->name), tb->table_idx,
1344                                 ntable->next_idx, ntable->rows);*/
1345                         values += MONO_NESTED_CLASS_SIZE;
1346                         ntable->next_idx++;
1347                 }
1348         }
1349         mono_image_add_cattrs (assembly, tb->table_idx, CUSTOM_ATTR_TYPEDEF, tb->cattrs);
1350 }
1351
1352 static void
1353 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicAssembly *assembly)
1354 {
1355         MonoDynamicTable *table;
1356         int i;
1357         char *name;
1358
1359         table = &assembly->tables [MONO_TABLE_MODULE];
1360         mb->table_idx = table->next_idx ++;
1361         name = mono_string_to_utf8 (mb->module.name);
1362         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, name);
1363         g_free (name);
1364         i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
1365         i /= 16;
1366         ++i;
1367         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
1368         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
1369         table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
1370
1371         mono_image_add_cattrs (assembly, mb->table_idx, CUSTOM_ATTR_MODULE, mb->cattrs);
1372         /*
1373          * fill-in info in other tables as well.
1374          */
1375         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1376         table->rows += mono_array_length (mb->types);
1377         alloc_table (table, table->rows);
1378         /*
1379          * We assign here the typedef indexes to avoid mismatches if a type that
1380          * has not yet been stored in the tables is referenced by another type.
1381          */
1382         for (i = 0; i < mono_array_length (mb->types); ++i) {
1383                 int j;
1384                 MonoReflectionTypeBuilder *type = mono_array_get (mb->types, MonoReflectionTypeBuilder*, i);
1385                 type->table_idx = table->next_idx ++;
1386                 if (!type->subtypes)
1387                         continue;
1388                 for (j = 0; j < mono_array_length (type->subtypes); ++j) {
1389                         MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, j);
1390                         subtype->table_idx = table->next_idx ++;
1391                 }
1392         }
1393         for (i = 0; i < mono_array_length (mb->types); ++i)
1394                 mono_image_get_type_info (domain, mono_array_get (mb->types, MonoReflectionTypeBuilder*, i), assembly);
1395 }
1396
1397 #define align_pointer(base,p)\
1398         do {\
1399                 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
1400                 if (__diff & 3)\
1401                         (p) += 4 - (__diff & 3);\
1402         } while (0)
1403
1404 /*
1405  * build_compressed_metadata() fills in the blob of data that represents the 
1406  * raw metadata as it will be saved in the PE file. The five streams are output 
1407  * and the metadata tables are comnpressed from the guint32 array representation, 
1408  * to the compressed on-disk format.
1409  */
1410 static void
1411 build_compressed_metadata (MonoDynamicAssembly *assembly)
1412 {
1413         int i;
1414         guint64 valid_mask = 0;
1415         guint64 sorted_mask;
1416         guint32 heapt_size = 0;
1417         guint32 meta_size = 256; /* allow for header and other stuff */
1418         guint32 table_offset;
1419         guint32 ntables = 0;
1420         guint64 *int64val;
1421         guint32 *int32val;
1422         guint16 *int16val;
1423         MonoImage *meta;
1424         unsigned char *p;
1425         const char *version = "mono" VERSION;
1426         struct StreamDesc {
1427                 const char *name;
1428                 MonoDynamicStream *stream;
1429         } stream_desc [] = {
1430                 {"#~", &assembly->tstream},
1431                 {"#Strings", &assembly->sheap},
1432                 {"#US", &assembly->us},
1433                 {"#Blob", &assembly->blob},
1434                 {"#GUID", &assembly->guid},
1435         };
1436         
1437         /* tables that are sorted */
1438         sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
1439                 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
1440                 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
1441                 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
1442                 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
1443                 | ((guint64)1 << MONO_TABLE_DECLSECURITY);
1444         
1445         /* Compute table sizes */
1446         /* the MonoImage has already been created in mono_image_basic_init() */
1447         meta = assembly->assembly.image;
1448         
1449         /* Setup the info used by compute_sizes () */
1450         meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
1451         meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
1452         meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
1453
1454         meta_size += assembly->blob.index;
1455         meta_size += assembly->guid.index;
1456         meta_size += assembly->sheap.index;
1457         meta_size += assembly->us.index;
1458
1459         for (i=0; i < 64; ++i)
1460                 meta->tables [i].rows = assembly->tables [i].rows;
1461         
1462         for (i = 0; i < 64; i++){
1463                 if (meta->tables [i].rows == 0)
1464                         continue;
1465                 valid_mask |= (guint64)1 << i;
1466                 ntables ++;
1467                 meta->tables [i].row_size = mono_metadata_compute_size (
1468                         meta, i, &meta->tables [i].size_bitfield);
1469                 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
1470         }
1471         heapt_size += 24; /* #~ header size */
1472         heapt_size += ntables * 4;
1473         meta_size += heapt_size;
1474         meta->raw_metadata = g_malloc0 (meta_size);
1475         p = meta->raw_metadata;
1476         /* the metadata signature */
1477         *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
1478         /* version numbers and 4 bytes reserved */
1479         int16val = (guint16*)p;
1480         *int16val++ = 1;
1481         *int16val = 1;
1482         p += 8;
1483         /* version string */
1484         int32val = (guint32*)p;
1485         *int32val = strlen (version);
1486         p += 4;
1487         memcpy (p, version, *int32val);
1488         p += *int32val;
1489         align_pointer (meta->raw_metadata, p);
1490         int16val = (guint16*)p;
1491         *int16val++ = 0; /* flags must be 0 */
1492         *int16val = 5; /* number of streams */
1493         p += 4;
1494
1495         /*
1496          * write the stream info.
1497          */
1498         table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
1499         table_offset += 3; table_offset &= ~3;
1500
1501         assembly->tstream.index = heapt_size;
1502         for (i = 0; i < 5; ++i) {
1503                 int32val = (guint32*)p;
1504                 *int32val++ = stream_desc [i].stream->offset = table_offset;
1505                 *int32val = stream_desc [i].stream->index;
1506                 table_offset += *int32val;
1507                 table_offset += 3; table_offset &= ~3;
1508                 p += 8;
1509                 strcpy (p, stream_desc [i].name);
1510                 p += strlen (stream_desc [i].name) + 1;
1511                 align_pointer (meta->raw_metadata, p);
1512         }
1513         /* 
1514          * now copy the data, the table stream header and contents goes first.
1515          */
1516         g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
1517         p = meta->raw_metadata + assembly->tstream.offset;
1518         int32val = (guint32*)p;
1519         *int32val = 0; /* reserved */
1520         p += 4;
1521         *p++ = 1; /* version */
1522         *p++ = 0;
1523         if (meta->idx_string_wide)
1524                 *p |= 0x01;
1525         if (meta->idx_guid_wide)
1526                 *p |= 0x02;
1527         if (meta->idx_blob_wide)
1528                 *p |= 0x04;
1529         ++p;
1530         *p++ = 0; /* reserved */
1531         int64val = (guint64*)p;
1532         *int64val++ = valid_mask;
1533         *int64val++ = valid_mask & sorted_mask; /* bitvector of sorted tables  */
1534         p += 16;
1535         int32val = (guint32*)p;
1536         for (i = 0; i < 64; i++){
1537                 if (meta->tables [i].rows == 0)
1538                         continue;
1539                 *int32val++ = meta->tables [i].rows;
1540         }
1541         p = (unsigned char*)int32val;
1542         /* compress the tables */
1543         for (i = 0; i < 64; i++){
1544                 int row, col;
1545                 guint32 *values;
1546                 guint32 bitfield = meta->tables [i].size_bitfield;
1547                 if (!meta->tables [i].rows)
1548                         continue;
1549                 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
1550                         g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
1551                 meta->tables [i].base = p;
1552                 for (row = 1; row <= meta->tables [i].rows; ++row) {
1553                         values = assembly->tables [i].values + row * assembly->tables [i].columns;
1554                         for (col = 0; col < assembly->tables [i].columns; ++col) {
1555                                 switch (mono_metadata_table_size (bitfield, col)) {
1556                                 case 1:
1557                                         *p++ = values [col];
1558                                         break;
1559                                 case 2:
1560                                         int16val = (guint16*)p;
1561                                         *int16val = values [col];
1562                                         p += 2;
1563                                         break;
1564                                 case 4:
1565                                         int32val = (guint32*)p;
1566                                         *int32val = values [col];
1567                                         p += 4;
1568                                         break;
1569                                 default:
1570                                         g_assert_not_reached ();
1571                                 }
1572                         }
1573                 }
1574                 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
1575         }
1576         
1577         g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
1578         memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
1579         memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
1580         memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
1581         memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
1582
1583         assembly->meta_size = assembly->guid.offset + assembly->guid.index;
1584 }
1585
1586 /*
1587  * Some tables in metadata need to be sorted according to some criteria, but
1588  * when methods and fields are first created with reflection, they may be assigned a token
1589  * that doesn't correspond to the final token they will get assigned after the sorting.
1590  * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
1591  * with the reflection objects that represent them. Once all the tables are set up, the 
1592  * reflection objects will contains the correct table index. fixup_method() will fixup the
1593  * tokens for the method with ILGenerator @ilgen.
1594  */
1595 static void
1596 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicAssembly *assembly) {
1597         guint32 code_idx = GPOINTER_TO_UINT (value);
1598         MonoReflectionILTokenInfo *iltoken;
1599         MonoReflectionFieldBuilder *field;
1600         MonoReflectionCtorBuilder *ctor;
1601         MonoReflectionMethodBuilder *method;
1602         guint32 i, idx;
1603         unsigned char *target;
1604
1605         for (i = 0; i < ilgen->num_token_fixups; ++i) {
1606                 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
1607                 target = assembly->code.data + code_idx + iltoken->code_pos;
1608                 switch (target [3]) {
1609                 case MONO_TABLE_FIELD:
1610                         if (strcmp (iltoken->member->vtable->klass->name, "FieldBuilder"))
1611                                 g_assert_not_reached ();
1612                         field = (MonoReflectionFieldBuilder *)iltoken->member;
1613                         idx = field->table_idx;
1614                         break;
1615                 case MONO_TABLE_METHOD:
1616                         if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
1617                                 method = (MonoReflectionMethodBuilder *)iltoken->member;
1618                                 idx = method->table_idx;
1619                         } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
1620                                 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
1621                                 idx = ctor->table_idx;
1622                         } else {
1623                                 g_assert_not_reached ();
1624                         }
1625                         break;
1626                 default:
1627                         g_error ("got unexpected table 0x%02x in fixup", target [3]);
1628                 }
1629                 target [0] = idx & 0xff;
1630                 target [1] = (idx >> 8) & 0xff;
1631                 target [2] = (idx >> 16) & 0xff;
1632         }
1633 }
1634
1635 /*
1636  * mono_image_build_metadata() will fill the info in all the needed metadata tables
1637  * for the AssemblyBuilder @assemblyb: it iterates over the assembly modules
1638  * and recursively outputs the info for a module. Each module will output all the info
1639  * about it's types etc.
1640  * At the end of the process, method and field tokens are fixed up and the on-disk
1641  * compressed metadata representation is created.
1642  */
1643 static void
1644 mono_image_build_metadata (MonoReflectionAssemblyBuilder *assemblyb)
1645 {
1646         MonoDynamicTable *table;
1647         MonoDynamicAssembly *assembly = assemblyb->dynamic_assembly;
1648         MonoDomain *domain = ((MonoObject *)assemblyb)->vtable->domain;
1649         guint32 len;
1650         guint32 *values;
1651         char *name;
1652         int i;
1653         
1654         assembly->text_rva = START_TEXT_RVA;
1655
1656         table = &assembly->tables [MONO_TABLE_ASSEMBLY];
1657         alloc_table (table, 1);
1658         values = table->values + MONO_ASSEMBLY_SIZE;
1659         values [MONO_ASSEMBLY_HASH_ALG] = 0x8004;
1660         name = mono_string_to_utf8 (assemblyb->name);
1661         values [MONO_ASSEMBLY_NAME] = string_heap_insert (&assembly->sheap, name);
1662         g_free (name);
1663         values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
1664         values [MONO_ASSEMBLY_PUBLIC_KEY] = 0;
1665         values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
1666         values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
1667         values [MONO_ASSEMBLY_REV_NUMBER] = 0;
1668         values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
1669         values [MONO_ASSEMBLY_FLAGS] = 0;
1670
1671         mono_image_add_cattrs (assembly, 1, CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
1672
1673         assembly->tables [MONO_TABLE_TYPEDEF].rows = 1; /* .<Module> */
1674         assembly->tables [MONO_TABLE_TYPEDEF].next_idx++;
1675
1676         if (assemblyb->modules) {
1677                 len = mono_array_length (assemblyb->modules);
1678                 table = &assembly->tables [MONO_TABLE_MODULE];
1679                 alloc_table (table, len);
1680                 for (i = 0; i < len; ++i)
1681                         mono_image_fill_module_table (domain, mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i), assembly);
1682         } else {
1683                 table = &assembly->tables [MONO_TABLE_MODULE];
1684                 table->rows++;
1685                 alloc_table (table, table->rows);
1686                 table->values [table->next_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert (&assembly->sheap, "RefEmit_YouForgotToDefineAModule");
1687                 table->next_idx ++;
1688         }
1689
1690         table = &assembly->tables [MONO_TABLE_TYPEDEF];
1691         /* 
1692          * table->rows is already set above and in mono_image_fill_module_table.
1693          */
1694         alloc_table (table, table->rows);
1695         /*
1696          * Set the first entry.
1697          */
1698         values = table->values + table->columns;
1699         values [MONO_TYPEDEF_FLAGS] = 0;
1700         values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
1701         values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
1702         values [MONO_TYPEDEF_EXTENDS] = 0;
1703         values [MONO_TYPEDEF_FIELD_LIST] = 1;
1704         values [MONO_TYPEDEF_METHOD_LIST] = 1;
1705
1706         /* fixup tokens */
1707         mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
1708         
1709         build_compressed_metadata (assembly);
1710 }
1711
1712 /*
1713  * mono_image_insert_string:
1714  * @assembly: assembly builder object
1715  * @str: a string
1716  *
1717  * Insert @str into the user string stream of @assembly.
1718  */
1719 guint32
1720 mono_image_insert_string (MonoReflectionAssemblyBuilder *assembly, MonoString *str)
1721 {
1722         guint32 idx;
1723         char buf [16];
1724         char *b = buf;
1725         
1726         if (!assembly->dynamic_assembly)
1727                 mono_image_basic_init (assembly);
1728         mono_metadata_encode_value (1 | (str->length * 2), b, &b);
1729         idx = mono_image_add_stream_data (&assembly->dynamic_assembly->us, buf, b-buf);
1730         /* FIXME: ENOENDIAN */
1731         mono_image_add_stream_data (&assembly->dynamic_assembly->us, (const char*)mono_string_chars (str), str->length * 2);
1732         mono_image_add_stream_data (&assembly->dynamic_assembly->us, "", 1);
1733         return MONO_TOKEN_STRING | idx;
1734 }
1735
1736 /*
1737  * mono_image_create_token:
1738  * @assembly: a dynamic assembly
1739  * @obj:
1740  *
1741  * Get a token to insert in the IL code stream for the given MemberInfo.
1742  * @obj can be one of:
1743  *      ConstructorBuilder
1744  *      MethodBuilder
1745  *      FieldBuilder
1746  *      MonoCMethod
1747  *      MonoMethod
1748  *      MonoField
1749  *      MonoType
1750  *      TypeBuilder
1751  */
1752 guint32
1753 mono_image_create_token (MonoDynamicAssembly *assembly, MonoObject *obj)
1754 {
1755         MonoClass *klass;
1756         guint32 token;
1757
1758         if (!obj)
1759                 g_error ("System.Array methods not yet supported");
1760         
1761         klass = obj->vtable->klass;
1762         if (strcmp (klass->name, "MethodBuilder") == 0) {
1763                 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
1764                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1765                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1766                 return token;
1767         }
1768         if (strcmp (klass->name, "ConstructorBuilder") == 0) {
1769                 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
1770                 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
1771                 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
1772                 return token;
1773         }
1774         if (strcmp (klass->name, "FieldBuilder") == 0) {
1775                 MonoReflectionFieldBuilder *mb = (MonoReflectionFieldBuilder *)obj;
1776                 return mb->table_idx | MONO_TOKEN_FIELD_DEF;
1777         }
1778         if (strcmp (klass->name, "TypeBuilder") == 0) {
1779                 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
1780                 return tb->table_idx | MONO_TOKEN_TYPE_DEF;
1781         }
1782         if (strcmp (klass->name, "MonoType") == 0) {
1783                 MonoReflectionType *tb = (MonoReflectionType *)obj;
1784                 return mono_metadata_token_from_dor (
1785                         mono_image_typedef_or_ref (assembly, tb->type));
1786         }
1787         if (strcmp (klass->name, "MonoCMethod") == 0 ||
1788                         strcmp (klass->name, "MonoMethod") == 0) {
1789                 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
1790                 token = mono_image_get_methodref_token (assembly, m->method);
1791                 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1792                 return token;
1793         }
1794         if (strcmp (klass->name, "MonoField") == 0) {
1795                 MonoReflectionField *f = (MonoReflectionField *)obj;
1796                 token = mono_image_get_fieldref_token (assembly, f->field, f->klass);
1797                 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1798                 return token;
1799         }
1800         g_print ("requested token for %s\n", klass->name);
1801         return 0;
1802 }
1803
1804 /*
1805  * mono_image_basic_ini:
1806  * @assembly: an assembly builder object
1807  *
1808  * Create the MonoImage that represents the assembly builder and setup some
1809  * of the helper hash table and the basic metadata streams.
1810  */
1811 void
1812 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1813 {
1814         MonoDynamicAssembly *assembly;
1815         MonoImage *image;
1816         int i;
1817         
1818         if (assemblyb->dynamic_assembly)
1819                 return;
1820
1821 #if HAVE_BOEHM_GC
1822         assembly = assemblyb->dynamic_assembly = GC_malloc (sizeof (MonoDynamicAssembly));
1823 #else
1824         assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1825 #endif
1826
1827         assembly->token_fixups = mono_g_hash_table_new (g_direct_hash, g_direct_equal);
1828         assembly->handleref = g_hash_table_new (g_direct_hash, g_direct_equal);
1829         assembly->typeref = g_hash_table_new (mono_metadata_type_hash, mono_metadata_type_equal);
1830
1831         string_heap_init (&assembly->sheap);
1832         mono_image_add_stream_data (&assembly->us, "", 1);
1833         mono_image_add_stream_data (&assembly->blob, "", 1);
1834
1835         for (i=0; i < 64; ++i) {
1836                 assembly->tables [i].next_idx = 1;
1837                 assembly->tables [i].columns = table_sizes [i];
1838         }
1839
1840         image = g_new0 (MonoImage, 1);
1841         
1842         /* keep in sync with image.c */
1843         image->name = mono_string_to_utf8 (assemblyb->name);
1844         image->assembly_name = image->name; /* they may be different */
1845
1846         image->method_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1847         image->class_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1848         image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
1849         image->array_cache = g_hash_table_new (g_direct_hash, g_direct_equal);
1850
1851         assembly->assembly.image = image;
1852         
1853 }
1854
1855 /*
1856  * mono_image_get_heade:
1857  * @assemblyb: an assembly builder object
1858  * @buffer:
1859  * @maxsize
1860  * 
1861  * When we need to save an assembly, we first call this function that ensures the metadata 
1862  * tables are built for all the modules in the assembly. This function creates the PE-COFF
1863  * header, the image sections, the CLI header etc. The header is written in @buffer
1864  * and the length of the data written is returned.
1865  * If @buffer is not big enough (@maxsize), -1 is returned.
1866  */
1867 int
1868 mono_image_get_header (MonoReflectionAssemblyBuilder *assemblyb, char *buffer, int maxsize)
1869 {
1870         MonoMSDOSHeader *msdos;
1871         MonoDotNetHeader *header;
1872         MonoSectionTable *section;
1873         MonoCLIHeader *cli_header;
1874         guint32 header_size =  TEXT_OFFSET + CLI_H_SIZE;
1875         MonoDynamicAssembly *assembly;
1876
1877         static const unsigned char msheader[] = {
1878                 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,  0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
1879                 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1880                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1881                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
1882                 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd,  0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
1883                 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,  0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
1884                 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e,  0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
1885                 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a,  0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1886         };
1887
1888         if (maxsize < header_size)
1889                 return -1;
1890
1891         mono_image_basic_init (assemblyb);
1892         assembly = assemblyb->dynamic_assembly;
1893
1894         mono_image_build_metadata (assemblyb);
1895
1896         memset (buffer, 0, header_size);
1897         memcpy (buffer, msheader, sizeof (MonoMSDOSHeader));
1898
1899         msdos = (MonoMSDOSHeader *)buffer;
1900         header = (MonoDotNetHeader *)(buffer + sizeof (MonoMSDOSHeader));
1901         section = (MonoSectionTable*) (buffer + sizeof (MonoMSDOSHeader) + sizeof (MonoDotNetHeader));
1902
1903         /* FIXME: ENDIAN problem: byteswap as needed */
1904         msdos->pe_offset = sizeof (MonoMSDOSHeader);
1905
1906         header->pesig [0] = 'P';
1907         header->pesig [1] = 'E';
1908         header->pesig [2] = header->pesig [3] = 0;
1909
1910         header->coff.coff_machine = 0x14c;
1911         header->coff.coff_sections = 1; /* only .text supported now */
1912         header->coff.coff_time = time (NULL);
1913         header->coff.coff_opt_header_size = sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4;
1914         /* it's an exe */
1915         header->coff.coff_attributes = 0x010e;
1916         /* it's a dll */
1917         //header->coff.coff_attributes = 0x210e;
1918         header->pe.pe_magic = 0x10B;
1919         header->pe.pe_major = 6;
1920         header->pe.pe_minor = 0;
1921         /* need to set: pe_code_size pe_data_size pe_rva_entry_point pe_rva_code_base pe_rva_data_base */
1922
1923         header->nt.pe_image_base = 0x400000;
1924         header->nt.pe_section_align = 8192;
1925         header->nt.pe_file_alignment = FILE_ALIGN;
1926         header->nt.pe_os_major = 4;
1927         header->nt.pe_os_minor = 0;
1928         header->nt.pe_subsys_major = 4;
1929         /* need to set pe_image_size, pe_header_size */
1930         header->nt.pe_header_size = 0x200;
1931         header->nt.pe_image_size = 0x00008000;
1932         header->nt.pe_subsys_required = 3; /* 3 -> cmdline app, 2 -> GUI app */
1933         header->nt.pe_stack_reserve = 0x00100000;
1934         header->nt.pe_stack_commit = 0x00001000;
1935         header->nt.pe_heap_reserve = 0x00100000;
1936         header->nt.pe_heap_commit = 0x00001000;
1937         header->nt.pe_loader_flags = 0;
1938         header->nt.pe_data_dir_count = 16;
1939
1940 #if 0
1941         /* set: */
1942         header->datadir.pe_import_table
1943         pe_resource_table
1944         pe_reloc_table
1945         pe_iat  
1946 #endif
1947         header->datadir.pe_cli_header.size = 72;
1948         header->datadir.pe_cli_header.rva = assembly->text_rva; /* we put it always at the beginning */
1949
1950         /* Write section tables */
1951         strcpy (section->st_name, ".text");
1952         section->st_virtual_address = START_TEXT_RVA;
1953         section->st_virtual_size = assembly->meta_size +  assembly->code.index;
1954         section->st_raw_data_size = section->st_virtual_size + (FILE_ALIGN - 1);
1955         section->st_raw_data_size &= ~(FILE_ALIGN - 1);
1956         section->st_raw_data_ptr = TEXT_OFFSET;
1957         section->st_flags = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
1958
1959         /* 
1960          * align: build_compressed_metadata () assumes metadata is aligned 
1961          * see below:
1962          * cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1963          */
1964         assembly->code.index += 3;
1965         assembly->code.index &= ~3;
1966
1967         /*
1968          * Write the MonoCLIHeader header 
1969          */
1970         cli_header = (MonoCLIHeader*)(buffer + TEXT_OFFSET);
1971         cli_header->ch_size = 72;
1972         cli_header->ch_runtime_major = 2;
1973         cli_header->ch_flags = CLI_FLAGS_ILONLY;
1974         if (assemblyb->entry_point) 
1975                 cli_header->ch_entry_point = assemblyb->entry_point->table_idx | MONO_TOKEN_METHOD_DEF;
1976         else
1977                 cli_header->ch_entry_point = 0;
1978         cli_header->ch_metadata.rva = assembly->text_rva + assembly->code.index + CLI_H_SIZE;
1979         cli_header->ch_metadata.size = assembly->meta_size;
1980         
1981         return header_size;
1982 }
1983
1984 /*
1985  * We need to return always the same object for MethodInfo, FieldInfo etc..
1986  * type uses a different hash, since it uses custom hash/equal functions.
1987  */
1988 static MonoGHashTable *object_cache = NULL;
1989 static MonoGHashTable *type_cache = NULL;
1990
1991 #define CHECK_OBJECT(t,p)       \
1992         do {    \
1993                 t _obj; \
1994                 if (!object_cache)      \
1995                         object_cache = mono_g_hash_table_new (g_direct_hash, g_direct_equal);   \
1996                 if ((_obj = mono_g_hash_table_lookup (object_cache, (p))))      \
1997                         return _obj;    \
1998         } while (0)
1999
2000 #define CACHE_OBJECT(p,o)       \
2001         do {    \
2002                 mono_g_hash_table_insert (object_cache, p,o);   \
2003         } while (0)
2004
2005 /*
2006  * mono_assembly_get_object:
2007  * @domain: an app domain
2008  * @assembly: an assembly
2009  *
2010  * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
2011  */
2012 MonoReflectionAssembly*
2013 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
2014 {
2015         static MonoClass *System_Reflection_Assembly;
2016         MonoReflectionAssembly *res;
2017         
2018         CHECK_OBJECT (MonoReflectionAssembly *, assembly);
2019         if (!System_Reflection_Assembly)
2020                 System_Reflection_Assembly = mono_class_from_name (
2021                         mono_defaults.corlib, "System.Reflection", "Assembly");
2022         res = (MonoReflectionAssembly *)mono_object_new (domain, System_Reflection_Assembly);
2023         res->assembly = assembly;
2024         CACHE_OBJECT (assembly, res);
2025         return res;
2026 }
2027
2028 static gboolean
2029 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
2030 {
2031         if ((t1->type != t2->type) ||
2032             (t1->byref != t2->byref))
2033                 return FALSE;
2034
2035         switch (t1->type) {
2036         case MONO_TYPE_VOID:
2037         case MONO_TYPE_BOOLEAN:
2038         case MONO_TYPE_CHAR:
2039         case MONO_TYPE_I1:
2040         case MONO_TYPE_U1:
2041         case MONO_TYPE_I2:
2042         case MONO_TYPE_U2:
2043         case MONO_TYPE_I4:
2044         case MONO_TYPE_U4:
2045         case MONO_TYPE_I8:
2046         case MONO_TYPE_U8:
2047         case MONO_TYPE_R4:
2048         case MONO_TYPE_R8:
2049         case MONO_TYPE_STRING:
2050         case MONO_TYPE_I:
2051         case MONO_TYPE_U:
2052         case MONO_TYPE_OBJECT:
2053                 return TRUE;
2054         case MONO_TYPE_VALUETYPE:
2055         case MONO_TYPE_CLASS:
2056                 return t1->data.klass == t2->data.klass;
2057         case MONO_TYPE_PTR:
2058         case MONO_TYPE_SZARRAY:
2059                 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
2060         case MONO_TYPE_ARRAY:
2061                 if (t1->data.array->rank != t2->data.array->rank)
2062                         return FALSE;
2063                 return mymono_metadata_type_equal (t1->data.array->type, t2->data.array->type);
2064         default:
2065                 g_error ("implement type compare for %0x!", t1->type);
2066                 return FALSE;
2067         }
2068
2069         return FALSE;
2070 }
2071
2072 static guint
2073 mymono_metadata_type_hash (MonoType *t1)
2074 {
2075         guint hash;
2076
2077         hash = t1->type;
2078
2079         hash |= t1->byref << 6; /* do not collide with t1->type values */
2080         switch (t1->type) {
2081         case MONO_TYPE_VALUETYPE:
2082         case MONO_TYPE_CLASS:
2083                 /* check if the distribution is good enough */
2084                 return hash << 7 | g_str_hash (t1->data.klass->name);
2085         case MONO_TYPE_PTR:
2086         case MONO_TYPE_SZARRAY:
2087                 return hash << 7 | mymono_metadata_type_hash (t1->data.type);
2088         }
2089         return hash;
2090 }
2091
2092 /*
2093  * mono_type_get_object:
2094  * @domain: an app domain
2095  * @type: a type
2096  *
2097  * Return an System.MonoType object representing the type @type.
2098  */
2099 MonoReflectionType*
2100 mono_type_get_object (MonoDomain *domain, MonoType *type)
2101 {
2102         MonoReflectionType *res;
2103         MonoClass *klass = mono_class_from_mono_type (type);
2104
2105         if (!type_cache)
2106                 type_cache = mono_g_hash_table_new ((GHashFunc)mymono_metadata_type_hash, 
2107                                 (GCompareFunc)mymono_metadata_type_equal);
2108         if ((res = mono_g_hash_table_lookup (type_cache, type)))
2109                 return res;
2110         if (klass->reflection_info) {
2111                 /* should this be considered an error condition? */
2112                 if (!type->byref)
2113                         return klass->reflection_info;
2114         }
2115         mono_class_init (klass);
2116         res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
2117         res->type = type;
2118         mono_g_hash_table_insert (type_cache, type, res);
2119         return res;
2120 }
2121
2122 /*
2123  * mono_method_get_object:
2124  * @domain: an app domain
2125  * @method: a method
2126  *
2127  * Return an System.Reflection.MonoMethod object representing the method @method.
2128  */
2129 MonoReflectionMethod*
2130 mono_method_get_object (MonoDomain *domain, MonoMethod *method)
2131 {
2132         /*
2133          * We use the same C representation for methods and constructors, but the type 
2134          * name in C# is different.
2135          */
2136         const char *cname;
2137         MonoClass *klass;
2138         MonoReflectionMethod *ret;
2139
2140         CHECK_OBJECT (MonoReflectionMethod *, method);
2141         if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
2142                 cname = "MonoCMethod";
2143         else
2144                 cname = "MonoMethod";
2145         klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", cname);
2146
2147         ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
2148         ret->method = method;
2149         ret->name = mono_string_new (domain, method->name);
2150         CACHE_OBJECT (method, ret);
2151         return ret;
2152 }
2153
2154 /*
2155  * mono_field_get_object:
2156  * @domain: an app domain
2157  * @klass: a type
2158  * @field: a field
2159  *
2160  * Return an System.Reflection.MonoField object representing the field @field
2161  * in class @klass.
2162  */
2163 MonoReflectionField*
2164 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
2165 {
2166         MonoReflectionField *res;
2167         MonoClass *oklass;
2168
2169         CHECK_OBJECT (MonoReflectionField *, field);
2170         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
2171         res = (MonoReflectionField *)mono_object_new (domain, oklass);
2172         res->klass = klass;
2173         res->field = field;
2174         CACHE_OBJECT (field, res);
2175         return res;
2176 }
2177
2178 /*
2179  * mono_property_get_object:
2180  * @domain: an app domain
2181  * @klass: a type
2182  * @property: a property
2183  *
2184  * Return an System.Reflection.MonoProperty object representing the property @property
2185  * in class @klass.
2186  */
2187 MonoReflectionProperty*
2188 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
2189 {
2190         MonoReflectionProperty *res;
2191         MonoClass *oklass;
2192
2193         CHECK_OBJECT (MonoReflectionProperty *, property);
2194         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
2195         res = (MonoReflectionProperty *)mono_object_new (domain, oklass);
2196         res->klass = klass;
2197         res->property = property;
2198         CACHE_OBJECT (property, res);
2199         return res;
2200 }
2201
2202 /*
2203  * mono_event_get_object:
2204  * @domain: an app domain
2205  * @klass: a type
2206  * @event: a event
2207  *
2208  * Return an System.Reflection.MonoEvent object representing the event @event
2209  * in class @klass.
2210  */
2211 MonoReflectionEvent*
2212 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
2213 {
2214         MonoReflectionEvent *res;
2215         MonoClass *oklass;
2216
2217         CHECK_OBJECT (MonoReflectionEvent *, event);
2218         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
2219         res = (MonoReflectionEvent *)mono_object_new (domain, oklass);
2220         res->klass = klass;
2221         res->event = event;
2222         CACHE_OBJECT (event, res);
2223         return res;
2224 }
2225
2226 /*
2227  * mono_param_get_objects:
2228  * @domain: an app domain
2229  * @method: a method
2230  *
2231  * Return an System.Reflection.ParameterInfo array object representing the parameters
2232  * in the method @method.
2233  */
2234 MonoReflectionParameter**
2235 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
2236 {
2237         MonoReflectionParameter **res;
2238         MonoReflectionMethod *member;
2239         MonoClass *oklass;
2240         char **names;
2241         int i;
2242
2243         if (!method->signature->param_count)
2244                 return NULL;
2245
2246         member = mono_method_get_object (domain, method);
2247         names = g_new (char *, method->signature->param_count);
2248         mono_method_get_param_names (method, (const char **) names);
2249         
2250         /* Note: the cache is based on the address of the signature into the method
2251          * since we already cache MethodInfos with the method as keys.
2252          */
2253         CHECK_OBJECT (MonoReflectionParameter**, &(method->signature));
2254         oklass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
2255 #if HAVE_BOEHM_GC
2256         res = GC_malloc (sizeof (MonoReflectionParameter*) * method->signature->param_count);
2257 #else
2258         res = g_new0 (MonoReflectionParameter*, method->signature->param_count);
2259 #endif
2260         for (i = 0; i < method->signature->param_count; ++i) {
2261                 res [i] = (MonoReflectionParameter *)mono_object_new (domain, oklass);
2262                 res [i]->ClassImpl = mono_type_get_object (domain, method->signature->params [i]);
2263                 res [i]->DefaultValueImpl = NULL; /* FIXME */
2264                 res [i]->MemberImpl = (MonoObject*)member;
2265                 res [i]->NameImpl = mono_string_new (domain, names [i]);
2266                 res [i]->PositionImpl = i + 1;
2267                 res [i]->AttrsImpl = method->signature->params [i]->attrs;
2268         }
2269         g_free (names);
2270         CACHE_OBJECT (&(method->signature), res);
2271         return res;
2272 }
2273
2274 /*
2275  * mono_reflection_parse_type:
2276  * @name: type name
2277  *
2278  * Parse a type name as accepted by the GetType () method and output the info
2279  * extracted in the info structure.
2280  * the name param will be mangled, so, make a copy before passing it to this function.
2281  * The fields in info will be valid until the memory pointed to by name is valid.
2282  * Returns 0 on parse error.
2283  * See also mono_type_get_name () below.
2284  */
2285 int
2286 mono_reflection_parse_type (char *name, MonoTypeNameParse *info) {
2287
2288         char *start, *p, *w, *last_point;
2289         int in_modifiers = 0;
2290         int isbyref = 0, rank;
2291
2292         start = p = w = name;
2293
2294         info->name = info->name_space = info->assembly = NULL;
2295         info->nest_name = info->nest_name_space = NULL;
2296         info->modifiers = NULL;
2297
2298         last_point = NULL;
2299
2300         while (*p) {
2301                 switch (*p) {
2302                 case '+':
2303                         /* we have parsed the nesting namespace + name */
2304                         if (last_point) {
2305                                 info->nest_name_space = start;
2306                                 *last_point = 0;
2307                                 info->nest_name = last_point + 1;
2308                         } else {
2309                                 info->nest_name_space = (char *)"";
2310                                 info->nest_name = start;
2311                         }
2312                         *p = 0; /* NULL terminate */
2313                         last_point = NULL;
2314                         start = p + 1;
2315                         break;
2316                 case '.':
2317                         last_point = w;
2318                         break;
2319                 case '\\':
2320                         ++p;
2321                         break;
2322                 case '&':
2323                 case '*':
2324                 case '[':
2325                 case ',':
2326                         in_modifiers = 1;
2327                         break;
2328                 default:
2329                         break;
2330                 }
2331                 if (in_modifiers)
2332                         break;
2333                 *w++ = *p++;
2334         }
2335         
2336         if (last_point) {
2337                 info->name_space = start;
2338                 *last_point = 0;
2339                 info->name = last_point + 1;
2340         } else {
2341                 info->name_space = (char *)"";
2342                 info->name = start;
2343         }
2344         while (*p) {
2345                 switch (*p) {
2346                 case '&':
2347                         if (isbyref) /* only one level allowed by the spec */
2348                                 return 0;
2349                         isbyref = 1;
2350                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
2351                         *p++ = 0;
2352                         break;
2353                 case '*':
2354                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
2355                         *p++ = 0;
2356                         break;
2357                 case '[':
2358                         rank = 1;
2359                         *p++ = 0;
2360                         while (*p) {
2361                                 if (*p == ']')
2362                                         break;
2363                                 if (*p == ',')
2364                                         rank++;
2365                                 else if (*p != '*') /* '*' means unknown lower bound */
2366                                         return 0;
2367                                 ++p;
2368                         }
2369                         if (*p++ != ']')
2370                                 return 0;
2371                         info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
2372                         break;
2373                 case ',':
2374                         *p++ = 0;
2375                         while (*p) {
2376                                 if (*p == ' ') {
2377                                         ++p;
2378                                         continue;
2379                                 }
2380                                 break;
2381                         }
2382                         if (!*p)
2383                                 return 0; /* missing assembly name */
2384                         info->assembly = p;
2385                         break;
2386                 default:
2387                         break;
2388                 }
2389         }
2390         *w = 0; /* terminate class name */
2391         if (!info->name || !*info->name)
2392                 return 0;
2393         if (info->nest_name && !*info->nest_name)
2394                 return 0;
2395         /* add other consistency checks */
2396         return 1;
2397 }
2398
2399 static void
2400 mono_type_get_name_recurse (MonoType *type, GString *str)
2401 {
2402         MonoClass *klass;
2403         
2404         switch (type->type) {
2405         case MONO_TYPE_ARRAY: {
2406                 int i, rank = type->data.array->rank;
2407
2408                 mono_type_get_name_recurse (type->data.array->type, str);
2409                 g_string_append_c (str, '[');
2410                 for (i = 1; i < rank; i++)
2411                         g_string_append_c (str, ',');
2412                 g_string_append_c (str, ']');
2413                 break;
2414         }
2415         case MONO_TYPE_SZARRAY:
2416                 mono_type_get_name_recurse (type->data.type, str);
2417                 g_string_append (str, "[]");
2418                 break;
2419         case MONO_TYPE_PTR:
2420                 mono_type_get_name_recurse (type->data.type, str);
2421                 g_string_append_c (str, '*');
2422                 break;
2423         default:
2424                 klass = mono_class_from_mono_type (type);
2425                 if (klass->nested_in) {
2426                         mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
2427                         g_string_append_c (str, '+');
2428                 }
2429                 if (*klass->name_space) {
2430                         g_string_append (str, klass->name_space);
2431                         g_string_append_c (str, '.');
2432                 }
2433                 g_string_append (str, klass->name);
2434                 break;
2435         }
2436 }
2437
2438 /*
2439  * mono_type_get_name:
2440  * @type: a type
2441  *
2442  * Returns the string representation for type as required by System.Reflection.
2443  * The inverse of mono_reflection_parse_type ().
2444  */
2445 char*
2446 mono_type_get_name (MonoType *type)
2447 {
2448         GString* result = g_string_new ("");
2449         mono_type_get_name_recurse (type, result);
2450
2451         if (type->byref)
2452                 g_string_append_c (result, '&');
2453
2454         return g_string_free (result, FALSE);
2455 }
2456
2457 /*
2458  * mono_reflection_get_type:
2459  * @image: a metadata context
2460  * @info: type description structure
2461  * @ignorecase: flag for case-insensitive string compares
2462  *
2463  * Build a MonoType from the type description in @info.
2464  * 
2465  */
2466 MonoType*
2467 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
2468 {
2469         MonoClass *klass;
2470         GList *mod;
2471         int modval;
2472         
2473         if (ignorecase) {
2474                 g_warning ("Ignore case not yet supported in GetType()");
2475                 return NULL;
2476         }
2477
2478         if (!image)
2479                 image = mono_defaults.corlib;
2480
2481         if (info->nest_name) {
2482                 klass = mono_class_from_name (image, info->nest_name_space, info->nest_name);
2483                 if (klass) {
2484                         GList *nested;
2485                         mono_class_init (klass);
2486                         nested = klass->nested_classes;
2487                         klass = NULL;
2488                         while (nested) {
2489                                 klass = nested->data;
2490                                 if (strcmp (klass->name, info->nest_name) == 0 &&
2491                                                 strcmp (klass->name_space, info->nest_name_space) == 0)
2492                                         break;
2493                                 klass = NULL;
2494                                 nested = nested->next;
2495                         }
2496                 }
2497         } else {
2498                 klass = mono_class_from_name (image, info->name_space, info->name);
2499         }
2500         if (!klass)
2501                 return NULL;
2502         mono_class_init (klass);
2503         for (mod = info->modifiers; mod; mod = mod->next) {
2504                 modval = GPOINTER_TO_UINT (mod->data);
2505                 if (!modval) { /* byref: must be last modifier */
2506                         return &klass->this_arg;
2507                 } else if (modval == -1) {
2508                         klass = mono_ptr_class_get (&klass->byval_arg);
2509                 } else { /* array rank */
2510                         klass = mono_array_class_get (&klass->byval_arg, modval);
2511                 }
2512                 mono_class_init (klass);
2513         }
2514         return &klass->byval_arg;
2515 }
2516
2517 /*
2518  * Optimization we could avoid mallocing() an little-endian archs that
2519  * don't crash with unaligned accesses.
2520  */
2521 static void
2522 fill_param_data (MonoImage *image, MonoMethodSignature *sig, guint32 blobidx, void **params) {
2523         int len, i, slen, type;
2524         const char *p = mono_metadata_blob_heap (image, blobidx);
2525
2526         len = mono_metadata_decode_value (p, &p);
2527         if (len < 2 || read16 (p) != 0x0001) /* Prolog */
2528                 return;
2529
2530         /* skip prolog */
2531         p += 2;
2532         for (i = 0; i < sig->param_count; ++i) {
2533                 type = sig->params [i]->type;
2534 handle_enum:
2535                 switch (type) {
2536                 case MONO_TYPE_U1:
2537                 case MONO_TYPE_I1:
2538                 case MONO_TYPE_BOOLEAN: {
2539                         MonoBoolean *bval = params [i] = g_malloc (sizeof (MonoBoolean));
2540                         *bval = *p;
2541                         ++p;
2542                         break;
2543                 }
2544                 case MONO_TYPE_CHAR:
2545                 case MONO_TYPE_U2:
2546                 case MONO_TYPE_I2: {
2547                         guint16 *val = params [i] = g_malloc (sizeof (guint16));
2548                         *val = read16 (p);
2549                         p += 2;
2550                         break;
2551                 }
2552 #if SIZEOF_VOID_P == 4
2553                 case MONO_TYPE_U:
2554                 case MONO_TYPE_I:
2555 #endif
2556                 case MONO_TYPE_R4:
2557                 case MONO_TYPE_U4:
2558                 case MONO_TYPE_I4: {
2559                         guint32 *val = params [i] = g_malloc (sizeof (guint32));
2560                         *val = read32 (p);
2561                         p += 4;
2562                         break;
2563                 }
2564 #if SIZEOF_VOID_P == 8
2565                 case MONO_TYPE_U: /* error out instead? this should probably not happen */
2566                 case MONO_TYPE_I:
2567 #endif
2568                 case MONO_TYPE_R8:
2569                 case MONO_TYPE_U8:
2570                 case MONO_TYPE_I8: {
2571                         guint64 *val = params [i] = g_malloc (sizeof (guint64));
2572                         *val = read64 (p);
2573                         p += 8;
2574                         break;
2575                 }
2576                 case MONO_TYPE_VALUETYPE:
2577                         if (sig->params [i]->data.klass->enumtype) {
2578                                 type = sig->params [i]->data.klass->enum_basetype->type;
2579                                 goto handle_enum;
2580                         } else {
2581                                 g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
2582                         }
2583                         break;
2584                 case MONO_TYPE_STRING: {
2585                         slen = mono_metadata_decode_value (p, &p);
2586                         params [i] = mono_string_new_len (mono_domain_get (), p, slen);
2587                         p += slen;
2588                         break;
2589                 }
2590                 default:
2591                         g_warning ("Type %02x not handled in custom attr value decoding", sig->params [i]->type);
2592                         break;
2593                 }
2594         }
2595 }
2596
2597 static void
2598 free_param_data (MonoMethodSignature *sig, void **params) {
2599         int i;
2600         for (i = 0; i < sig->param_count; ++i) {
2601                 switch (sig->params [i]->type) {
2602                 case MONO_TYPE_BOOLEAN:
2603                 case MONO_TYPE_CHAR:
2604                 case MONO_TYPE_U:
2605                 case MONO_TYPE_I:
2606                 case MONO_TYPE_U1:
2607                 case MONO_TYPE_I1:
2608                 case MONO_TYPE_U2:
2609                 case MONO_TYPE_I2:
2610                 case MONO_TYPE_U4:
2611                 case MONO_TYPE_I4:
2612                 case MONO_TYPE_U8:
2613                 case MONO_TYPE_I8:
2614                 case MONO_TYPE_R8:
2615                 case MONO_TYPE_R4:
2616                 case MONO_TYPE_VALUETYPE:
2617                         g_free (params [i]);
2618                         break;
2619                 default:
2620                         break;
2621                 }
2622         }
2623 }
2624
2625 /*
2626  * Find the method index in the metadata methodDef table.
2627  * Later put these three helper methods in metadata and export them.
2628  */
2629 static guint32
2630 find_method_index (MonoMethod *method) {
2631         MonoClass *klass = method->klass;
2632         int i;
2633
2634         for (i = 0; i < klass->method.count; ++i) {
2635                 if (method == klass->methods [i])
2636                         return klass->method.first + 1 + i;
2637         }
2638         return 0;
2639 }
2640
2641 /*
2642  * Find the field index in the metadata FieldDef table.
2643  */
2644 static guint32
2645 find_field_index (MonoClass *klass, MonoClassField *field) {
2646         int i;
2647
2648         for (i = 0; i < klass->field.count; ++i) {
2649                 if (field == &klass->fields [i])
2650                         return klass->field.first + 1 + i;
2651         }
2652         return 0;
2653 }
2654
2655 /*
2656  * Find the property index in the metadata Property table.
2657  */
2658 static guint32
2659 find_property_index (MonoClass *klass, MonoProperty *property) {
2660         int i;
2661
2662         for (i = 0; i < klass->property.count; ++i) {
2663                 if (property == &klass->properties [i])
2664                         return klass->property.first + 1 + i;
2665         }
2666         return 0;
2667 }
2668
2669 /*
2670  * Find the event index in the metadata Event table.
2671  */
2672 static guint32
2673 find_event_index (MonoClass *klass, MonoEvent *event) {
2674         int i;
2675
2676         for (i = 0; i < klass->event.count; ++i) {
2677                 if (event == &klass->events [i])
2678                         return klass->event.first + 1 + i;
2679         }
2680         return 0;
2681 }
2682
2683 /*
2684  * mono_reflection_get_custom_attrs:
2685  * @obj: a reflection object handle
2686  *
2687  * Return an array with all the custom attributes defined of the
2688  * reflection handle @obj. The objects are fully build.
2689  */
2690 MonoArray*
2691 mono_reflection_get_custom_attrs (MonoObject *obj)
2692 {
2693         guint32 idx, mtoken, i, len;
2694         guint32 cols [MONO_CUSTOM_ATTR_SIZE];
2695         MonoClass *klass;
2696         MonoImage *image;
2697         MonoTableInfo *ca;
2698         MonoMethod *method;
2699         MonoObject *attr;
2700         MonoArray *result;
2701         GList *list = NULL;
2702         void **params;
2703         
2704         klass = obj->vtable->klass;
2705         /* FIXME: need to handle: Module */
2706         if (klass == mono_defaults.monotype_class) {
2707                 MonoReflectionType *rtype = (MonoReflectionType*)obj;
2708                 klass = mono_class_from_mono_type (rtype->type);
2709                 idx = mono_metadata_token_index (klass->type_token);
2710                 idx <<= CUSTOM_ATTR_BITS;
2711                 idx |= CUSTOM_ATTR_TYPEDEF;
2712                 image = klass->image;
2713         } else if (strcmp ("Assembly", klass->name) == 0) {
2714                 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
2715                 idx = 1; /* there is only one assembly */
2716                 idx <<= CUSTOM_ATTR_BITS;
2717                 idx |= CUSTOM_ATTR_ASSEMBLY;
2718                 image = rassembly->assembly->image;
2719         } else if (strcmp ("MonoProperty", klass->name) == 0) {
2720                 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
2721                 idx = find_property_index (rprop->klass, rprop->property);
2722                 idx <<= CUSTOM_ATTR_BITS;
2723                 idx |= CUSTOM_ATTR_PROPERTY;
2724                 image = rprop->klass->image;
2725         } else if (strcmp ("MonoEvent", klass->name) == 0) {
2726                 MonoReflectionEvent *revent = (MonoReflectionEvent*)obj;
2727                 idx = find_event_index (revent->klass, revent->event);
2728                 idx <<= CUSTOM_ATTR_BITS;
2729                 idx |= CUSTOM_ATTR_EVENT;
2730                 image = revent->klass->image;
2731         } else if (strcmp ("MonoField", klass->name) == 0) {
2732                 MonoReflectionField *rfield = (MonoReflectionField*)obj;
2733                 idx = find_field_index (rfield->klass, rfield->field);
2734                 idx <<= CUSTOM_ATTR_BITS;
2735                 idx |= CUSTOM_ATTR_FIELDDEF;
2736                 image = rfield->klass->image;
2737         } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
2738                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
2739                 idx = find_method_index (rmethod->method);
2740                 idx <<= CUSTOM_ATTR_BITS;
2741                 idx |= CUSTOM_ATTR_METHODDEF;
2742                 image = method->klass->image;
2743         } else if (strcmp ("ParameterInfo", klass->name) == 0) {
2744                 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
2745                 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
2746                 guint32 method_index = find_method_index (rmethod->method);
2747                 guint32 param_list, param_last, param_pos, found;
2748
2749                 image = rmethod->method->klass->image;
2750                 ca = &image->tables [MONO_TABLE_METHOD];
2751
2752                 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
2753                 if (method_index == ca->rows) {
2754                         ca = &image->tables [MONO_TABLE_PARAM];
2755                         param_last = ca->rows + 1;
2756                 } else {
2757                         param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
2758                         ca = &image->tables [MONO_TABLE_PARAM];
2759                 }
2760                 found = 0;
2761                 for (i = param_list; i < param_last; ++i) {
2762                         param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
2763                         if (param_pos == param->PositionImpl) {
2764                                 found = 1;
2765                                 break;
2766                         }
2767                 }
2768                 if (!found)
2769                         return mono_array_new (mono_domain_get (), mono_defaults.object_class, 0);
2770                 idx = i;
2771                 idx <<= CUSTOM_ATTR_BITS;
2772                 idx |= CUSTOM_ATTR_PARAMDEF;
2773         } else { /* handle other types here... */
2774                 g_error ("get custom attrs not yet supported for %s", klass->name);
2775         }
2776
2777         /* at this point image and index are set correctly for searching the custom attr */
2778         ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
2779         /* the table is not sorted */
2780         for (i = 0; i < ca->rows; ++i) {
2781                 mono_metadata_decode_row (ca, i, cols, MONO_CUSTOM_ATTR_SIZE);
2782                 if (cols [MONO_CUSTOM_ATTR_PARENT] != idx)
2783                         continue;
2784                 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> CUSTOM_ATTR_TYPE_BITS;
2785                 switch (cols [MONO_CUSTOM_ATTR_TYPE] & CUSTOM_ATTR_TYPE_MASK) {
2786                 case CUSTOM_ATTR_TYPE_METHODDEF:
2787                         mtoken |= MONO_TOKEN_METHOD_DEF;
2788                         break;
2789                 case CUSTOM_ATTR_TYPE_MEMBERREF:
2790                         mtoken |= MONO_TOKEN_MEMBER_REF;
2791                         break;
2792                 default:
2793                         g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
2794                         break;
2795                 }
2796                 method = mono_get_method (image, mtoken, NULL);
2797                 if (!method)
2798                         g_error ("Can't find custom attr constructor");
2799                 mono_class_init (method->klass);
2800                 /*g_print ("got attr %s\n", method->klass->name);*/
2801                 params = g_new (void*, method->signature->param_count);
2802                 fill_param_data (image, method->signature, cols [MONO_CUSTOM_ATTR_VALUE], params);
2803                 attr = mono_object_new (mono_domain_get (), method->klass);
2804                 mono_runtime_invoke (method, attr, params);
2805                 list = g_list_prepend (list, attr);
2806                 free_param_data (method->signature, params);
2807                 g_free (params);
2808         }
2809
2810         len = g_list_length (list);
2811         /*
2812          * The return type is really object[], but System/Attribute.cs does a cast
2813          * to (Attribute []) and that is not allowed: I'm lazy for now, but we should
2814          * probably fix that.
2815          */
2816         klass = mono_class_from_name (mono_defaults.corlib, "System", "Attribute");
2817         result = mono_array_new (mono_domain_get (), klass, len);
2818         for (i = 0; i < len; ++i) {
2819                 mono_array_set (result, gpointer, i, list->data);
2820                 list = list->next;
2821         }
2822         g_list_free (g_list_first (list));
2823
2824         return result;
2825 }
2826
2827 /*
2828  * mono_reflection_get_custom_attrs_blob:
2829  * @ctor: custom attribute constructor
2830  * @ctorArgs: arguments o the constructor
2831  * @properties:
2832  * @propValues:
2833  * @fields:
2834  * @fieldValues:
2835  * 
2836  * Creates the blob of data that needs to be saved in the metadata and that represents
2837  * the custom attributed described by @ctor, @ctorArgs etc.
2838  * Returns: a Byte array representing the blob of data.
2839  */
2840 MonoArray*
2841 mono_reflection_get_custom_attrs_blob (MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues) {
2842         MonoArray *result;
2843         MonoMethodSignature *sig;
2844         MonoObject *arg;
2845         char *buffer, *p, *argval;
2846         guint32 buflen, i, type;
2847
2848         if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2849                 g_warning ("ConstructorBuilder Custom attribute not yet supported");
2850                 /* 
2851                  * maybe we should have a param array to method signature function and
2852                  * continue with the normal codepath.
2853                  */
2854                 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, 4);
2855                 mono_array_set (result, char, 0, 1);
2856                 return result;
2857         }
2858         buflen = 256;
2859         p = buffer = g_malloc (buflen);
2860         /* write the prolog */
2861         *p++ = 1;
2862         *p++ = 0;
2863         sig = ((MonoReflectionMethod*)ctor)->method->signature;
2864         /* FIXME: ENOENDIAN */
2865         for (i = 0; i < sig->param_count; ++i) {
2866                 if ((p-buffer) + 10 >= buflen) {
2867                         char *newbuf;
2868                         buflen *= 2;
2869                         newbuf = g_realloc (buffer, buflen);
2870                         p = newbuf + (p-buffer);
2871                         buffer = newbuf;
2872                 }
2873                 arg = (MonoObject*)mono_array_get (ctorArgs, gpointer, i);
2874                 argval = ((char*)arg + sizeof (MonoObject));
2875                 type = sig->params [i]->type;
2876 handle_enum:
2877                 switch (type) {
2878                 case MONO_TYPE_BOOLEAN:
2879                 case MONO_TYPE_U1:
2880                 case MONO_TYPE_I1:
2881                         *p++ = *argval;
2882                         break;
2883                 case MONO_TYPE_CHAR:
2884                 case MONO_TYPE_U2:
2885                 case MONO_TYPE_I2: {
2886                         guint16 *val = (guint16*)p;
2887                         *val = *(guint16*)argval;
2888                         p += 2;
2889                         break;
2890                 }
2891                 case MONO_TYPE_U4:
2892                 case MONO_TYPE_I4:
2893                 case MONO_TYPE_R4: {
2894                         guint32 *val = (guint32*)p;
2895                         *val = *(guint32*)argval;
2896                         p += 4;
2897                         break;
2898                 }
2899                 case MONO_TYPE_U8:
2900                 case MONO_TYPE_I8:
2901                 case MONO_TYPE_R8: {
2902                         guint64 *val = (guint64*)p;
2903                         *val = *(guint64*)argval;
2904                         p += 8;
2905                         break;
2906                 }
2907                 case MONO_TYPE_VALUETYPE:
2908                         if (sig->params [i]->data.klass->enumtype) {
2909                                 type = sig->params [i]->data.klass->enum_basetype->type;
2910                                 goto handle_enum;
2911                         } else {
2912                                 g_warning ("generic valutype %s not handled in custom attr value decoding", sig->params [i]->data.klass->name);
2913                         }
2914                         break;
2915                 case MONO_TYPE_STRING: {
2916                         char *str = mono_string_to_utf8 ((MonoString*)arg);
2917                         guint32 slen = strlen (str);
2918                         if ((p-buffer) + 10 + slen >= buflen) {
2919                                 char *newbuf;
2920                                 buflen *= 2;
2921                                 buflen += slen;
2922                                 newbuf = g_realloc (buffer, buflen);
2923                                 p = newbuf + (p-buffer);
2924                                 buffer = newbuf;
2925                         }
2926                         mono_metadata_encode_value (slen, p, &p);
2927                         memcpy (p, str, slen);
2928                         p += slen;
2929                         g_free (str);
2930                         break;
2931                 }
2932                 default:
2933                         g_error ("type 0x%02x not yet supported in custom attr encoder", type);
2934                 }
2935         }
2936         /* 
2937          * we don't support properties and fields, yet, set to 0.
2938          */
2939         *p++ = 0;
2940         *p++ = 0;
2941         buflen = p - buffer;
2942         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
2943         p = mono_array_addr (result, char, 0);
2944         memcpy (p, buffer, buflen);
2945         g_free (buffer);
2946         return result;
2947 }
2948
2949 /*
2950  * mono_reflection_setup_internal_class:
2951  * @tb: a TypeBuilder object
2952  *
2953  * Creates a MonoClass that represents the TypeBuilder.
2954  * This is a trick that lets us simplify a lot of reflection code
2955  * (and will allow us to support Build and Run assemblies easier).
2956  */
2957 void
2958 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
2959 {
2960         MonoClass *klass, *parent;
2961
2962         klass = g_new0 (MonoClass, 1);
2963
2964         klass->image = tb->module->assemblyb->dynamic_assembly->assembly.image;
2965
2966         if (tb->parent)
2967                 parent = mono_class_from_mono_type (tb->parent->type);
2968         
2969         klass->inited = 1; /* we lie to the runtime */
2970         klass->name = mono_string_to_utf8 (tb->name);
2971         klass->name_space = mono_string_to_utf8 (tb->nspace);
2972         klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
2973         klass->flags = tb->attrs;
2974
2975         klass->element_class = klass;
2976         klass->reflection_info = tb; /* need to pin. */
2977
2978         mono_class_setup_parent (klass, parent);
2979         mono_class_setup_mono_type (klass);
2980
2981         /*
2982          * FIXME: handle interfaces.
2983          */
2984
2985         tb->type.type = &klass->byval_arg;
2986
2987         /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
2988 }
2989
2990 MonoArray *
2991 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
2992 {
2993         MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
2994         guint32 na = mono_array_length (sig->arguments);
2995         guint32 buflen, i;
2996         MonoArray *result;
2997         char *buf, *p;
2998
2999         p = buf = g_malloc (10 + na * 10);
3000
3001         mono_metadata_encode_value (0x07, p, &p);
3002         mono_metadata_encode_value (na, p, &p);
3003         for (i = 0; i < na; ++i) {
3004                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
3005                 encode_reflection_type (assembly, type, p, &p);
3006         }
3007
3008         buflen = p - buf;
3009         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3010         p = mono_array_addr (result, char, 0);
3011         memcpy (p, buf, buflen);
3012         g_free (buf);
3013
3014         return result;
3015 }
3016
3017 MonoArray *
3018 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
3019 {
3020         MonoDynamicAssembly *assembly = sig->module->assemblyb->dynamic_assembly;
3021         guint32 na = mono_array_length (sig->arguments);
3022         guint32 buflen, i;
3023         MonoArray *result;
3024         char *buf, *p;
3025
3026         p = buf = g_malloc (10 + na * 10);
3027
3028         mono_metadata_encode_value (0x06, p, &p);
3029         for (i = 0; i < na; ++i) {
3030                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType *, i);
3031                 encode_reflection_type (assembly, type, p, &p);
3032         }
3033
3034         buflen = p - buf;
3035         result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
3036         p = mono_array_addr (result, char, 0);
3037         memcpy (p, buf, buflen);
3038         g_free (buf);
3039
3040         return result;
3041 }
3042