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