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