Merge pull request #4540 from kumpera/android-changes-part1
[mono.git] / mono / metadata / sre-encode.c
1 /**
2  * \file
3  * Routines for encoding SRE builders into a
4  * MonoDynamicImage and generating tokens.
5  *   
6  * 
7  * Author:
8  *   Paolo Molaro (lupus@ximian.com)
9  *
10  * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12  * Copyright 2011 Rodrigo Kumpera
13  * Copyright 2016 Microsoft
14  *
15  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
16  */
17 #include <config.h>
18 #include <glib.h>
19
20 #include "mono/metadata/dynamic-image-internals.h"
21 #include "mono/metadata/dynamic-stream-internals.h"
22 #include "mono/metadata/object-internals.h"
23 #include "mono/metadata/reflection-internals.h"
24 #include "mono/metadata/sre-internals.h"
25 #include "mono/metadata/tabledefs.h"
26 #include "mono/metadata/tokentype.h"
27 #include "mono/utils/checked-build.h"
28
29 typedef struct {
30         char *p;
31         char *buf;
32         char *end;
33 } SigBuffer;
34
35 static guint32 create_typespec (MonoDynamicImage *assembly, MonoType *type);
36 static void    encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
37 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
38
39 static guint32
40 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
41 {
42         return mono_dynstream_add_data (stream, data, len);
43 }
44
45 static void
46 alloc_table (MonoDynamicTable *table, guint nrows)
47 {
48         mono_dynimage_alloc_table (table, nrows);
49 }
50
51 static void
52 sigbuffer_init (SigBuffer *buf, int size)
53 {
54         MONO_REQ_GC_NEUTRAL_MODE;
55
56         buf->buf = (char *)g_malloc (size);
57         buf->p = buf->buf;
58         buf->end = buf->buf + size;
59 }
60
61 static void
62 sigbuffer_make_room (SigBuffer *buf, int size)
63 {
64         MONO_REQ_GC_NEUTRAL_MODE;
65
66         if (buf->end - buf->p < size) {
67                 int new_size = buf->end - buf->buf + size + 32;
68                 char *p = (char *)g_realloc (buf->buf, new_size);
69                 size = buf->p - buf->buf;
70                 buf->buf = p;
71                 buf->p = p + size;
72                 buf->end = buf->buf + new_size;
73         }
74 }
75
76 static void
77 sigbuffer_add_value (SigBuffer *buf, guint32 val)
78 {
79         MONO_REQ_GC_NEUTRAL_MODE;
80
81         sigbuffer_make_room (buf, 6);
82         mono_metadata_encode_value (val, buf->p, &buf->p);
83 }
84
85 static void
86 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
87 {
88         MONO_REQ_GC_NEUTRAL_MODE;
89
90         sigbuffer_make_room (buf, 1);
91         buf->p [0] = val;
92         buf->p++;
93 }
94
95 static void
96 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
97 {
98         MONO_REQ_GC_NEUTRAL_MODE;
99
100         sigbuffer_make_room (buf, size);
101         memcpy (buf->p, p, size);
102         buf->p += size;
103 }
104
105 static void
106 sigbuffer_free (SigBuffer *buf)
107 {
108         MONO_REQ_GC_NEUTRAL_MODE;
109
110         g_free (buf->buf);
111 }
112
113 static guint32
114 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
115 {
116         MONO_REQ_GC_NEUTRAL_MODE;
117
118         char blob_size [8];
119         char *b = blob_size;
120         guint32 size = buf->p - buf->buf;
121         /* store length */
122         g_assert (size <= (buf->end - buf->buf));
123         mono_metadata_encode_value (size, b, &b);
124         return mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
125 }
126
127
128 static void
129 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
130 {
131         MONO_REQ_GC_NEUTRAL_MODE;
132
133         int i;
134         MonoGenericInst *class_inst;
135         MonoClass *klass;
136
137         g_assert (gclass);
138
139         class_inst = gclass->context.class_inst;
140
141         sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
142         klass = gclass->container_class;
143         sigbuffer_add_value (buf, klass->byval_arg.type);
144         sigbuffer_add_value (buf, mono_dynimage_encode_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
145
146         sigbuffer_add_value (buf, class_inst->type_argc);
147         for (i = 0; i < class_inst->type_argc; ++i)
148                 encode_type (assembly, class_inst->type_argv [i], buf);
149
150 }
151
152 static void
153 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
154 {
155         MONO_REQ_GC_NEUTRAL_MODE;
156
157         if (!type) {
158                 g_assert_not_reached ();
159                 return;
160         }
161                 
162         if (type->byref)
163                 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
164
165         switch (type->type){
166         case MONO_TYPE_VOID:
167         case MONO_TYPE_BOOLEAN:
168         case MONO_TYPE_CHAR:
169         case MONO_TYPE_I1:
170         case MONO_TYPE_U1:
171         case MONO_TYPE_I2:
172         case MONO_TYPE_U2:
173         case MONO_TYPE_I4:
174         case MONO_TYPE_U4:
175         case MONO_TYPE_I8:
176         case MONO_TYPE_U8:
177         case MONO_TYPE_R4:
178         case MONO_TYPE_R8:
179         case MONO_TYPE_I:
180         case MONO_TYPE_U:
181         case MONO_TYPE_STRING:
182         case MONO_TYPE_OBJECT:
183         case MONO_TYPE_TYPEDBYREF:
184                 sigbuffer_add_value (buf, type->type);
185                 break;
186         case MONO_TYPE_PTR:
187                 sigbuffer_add_value (buf, type->type);
188                 encode_type (assembly, type->data.type, buf);
189                 break;
190         case MONO_TYPE_SZARRAY:
191                 sigbuffer_add_value (buf, type->type);
192                 encode_type (assembly, &type->data.klass->byval_arg, buf);
193                 break;
194         case MONO_TYPE_VALUETYPE:
195         case MONO_TYPE_CLASS: {
196                 MonoClass *k = mono_class_from_mono_type (type);
197
198                 if (mono_class_is_gtd (k)) {
199                         MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, mono_class_get_generic_container (k)->context.class_inst, TRUE);
200                         encode_generic_class (assembly, gclass, buf);
201                 } else {
202                         /*
203                          * Make sure we use the correct type.
204                          */
205                         sigbuffer_add_value (buf, k->byval_arg.type);
206                         /*
207                          * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
208                          * otherwise two typerefs could point to the same type, leading to
209                          * verification errors.
210                          */
211                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
212                 }
213                 break;
214         }
215         case MONO_TYPE_ARRAY:
216                 sigbuffer_add_value (buf, type->type);
217                 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
218                 sigbuffer_add_value (buf, type->data.array->rank);
219                 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
220                 sigbuffer_add_value (buf, 0);
221                 break;
222         case MONO_TYPE_GENERICINST:
223                 encode_generic_class (assembly, type->data.generic_class, buf);
224                 break;
225         case MONO_TYPE_VAR:
226         case MONO_TYPE_MVAR:
227                 sigbuffer_add_value (buf, type->type);
228                 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
229                 break;
230         default:
231                 g_error ("need to encode type %x", type->type);
232         }
233 }
234
235 static void
236 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionTypeHandle type, SigBuffer *buf, MonoError *error)
237 {
238         MONO_REQ_GC_UNSAFE_MODE;
239
240         error_init (error);
241
242         if (!type) {
243                 sigbuffer_add_value (buf, MONO_TYPE_VOID);
244                 return;
245         }
246
247         MonoType *t = mono_reflection_type_handle_mono_type (type, error);
248         return_if_nok (error);
249         encode_type (assembly, t, buf);
250 }
251
252 static void
253 encode_reflection_type_raw (MonoDynamicImage *assembly, MonoReflectionType* type_raw, SigBuffer *buf, MonoError *error)
254 {
255         HANDLE_FUNCTION_ENTER (); /* FIXME callers of encode_reflection_type_raw should use handles */
256         error_init (error);
257         MONO_HANDLE_DCL (MonoReflectionType, type);
258         encode_reflection_type (assembly, type, buf, error);
259         HANDLE_FUNCTION_RETURN ();
260 }
261
262
263 static void
264 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArrayHandle modreq, MonoArrayHandle modopt, SigBuffer *buf, MonoError *error)
265 {
266         HANDLE_FUNCTION_ENTER ();
267         MONO_REQ_GC_UNSAFE_MODE;
268
269         int i;
270
271         error_init (error);
272
273         if (!MONO_HANDLE_IS_NULL (modreq)) {
274                 for (i = 0; i < mono_array_handle_length (modreq); ++i) {
275                         MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
276                         if (!is_ok (error))
277                                 goto leave;
278                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
279                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
280                 }
281         }
282         if (!MONO_HANDLE_IS_NULL (modopt)) {
283                 for (i = 0; i < mono_array_handle_length (modopt); ++i) {
284                         MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
285                         if (!is_ok (error))
286                                 goto leave;
287                         sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
288                         sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
289                 }
290         }
291 leave:
292         HANDLE_FUNCTION_RETURN ();
293 }
294
295 static void
296 encode_custom_modifiers_raw (MonoDynamicImage *assembly, MonoArray *modreq_raw, MonoArray *modopt_raw, SigBuffer *buf, MonoError *error)
297 {
298         HANDLE_FUNCTION_ENTER (); /* FIXME callers of encode_custom_modifiers_raw should use handles */
299         error_init (error);
300         MONO_HANDLE_DCL (MonoArray, modreq);
301         MONO_HANDLE_DCL (MonoArray, modopt);
302         encode_custom_modifiers (assembly, modreq, modopt, buf, error);
303         HANDLE_FUNCTION_RETURN ();
304 }
305
306
307 #ifndef DISABLE_REFLECTION_EMIT
308 guint32
309 mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
310 {
311         MONO_REQ_GC_UNSAFE_MODE;
312
313         SigBuffer buf;
314         int i;
315         guint32 nparams =  sig->param_count;
316         guint32 idx;
317
318         if (!assembly->save)
319                 return 0;
320
321         sigbuffer_init (&buf, 32);
322         /*
323          * FIXME: vararg, explicit_this, differenc call_conv values...
324          */
325         idx = sig->call_convention;
326         if (sig->hasthis)
327                 idx |= 0x20; /* hasthis */
328         if (sig->generic_param_count)
329                 idx |= 0x10; /* generic */
330         sigbuffer_add_byte (&buf, idx);
331         if (sig->generic_param_count)
332                 sigbuffer_add_value (&buf, sig->generic_param_count);
333         sigbuffer_add_value (&buf, nparams);
334         encode_type (assembly, sig->ret, &buf);
335         for (i = 0; i < nparams; ++i) {
336                 if (i == sig->sentinelpos)
337                         sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
338                 encode_type (assembly, sig->params [i], &buf);
339         }
340         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
341         sigbuffer_free (&buf);
342         return idx;
343 }
344 #else /* DISABLE_REFLECTION_EMIT */
345 guint32
346 mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
347 {
348         g_assert_not_reached ();
349         return 0;
350 }
351 #endif
352
353 guint32
354 mono_dynimage_encode_method_builder_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
355 {
356         MONO_REQ_GC_UNSAFE_MODE;
357
358         error_init (error);
359
360         /*
361          * FIXME: reuse code from method_encode_signature().
362          */
363         SigBuffer buf;
364         int i;
365         guint32 nparams =  mb->parameters ? mono_array_length (mb->parameters): 0;
366         guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
367         guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
368         guint32 idx;
369
370         sigbuffer_init (&buf, 32);
371         /* LAMESPEC: all the call conv spec is foobared */
372         idx = mb->call_conv & 0x60; /* has-this, explicit-this */
373         if (mb->call_conv & 2)
374                 idx |= 0x5; /* vararg */
375         if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
376                 idx |= 0x20; /* hasthis */
377         if (ngparams)
378                 idx |= 0x10; /* generic */
379         sigbuffer_add_byte (&buf, idx);
380         if (ngparams)
381                 sigbuffer_add_value (&buf, ngparams);
382         sigbuffer_add_value (&buf, nparams + notypes);
383         encode_custom_modifiers_raw (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
384         if (!is_ok (error))
385                 goto leave;
386         encode_reflection_type_raw (assembly, mb->rtype, &buf, error);
387         if (!is_ok (error))
388                 goto leave;
389         for (i = 0; i < nparams; ++i) {
390                 MonoArray *modreq = NULL;
391                 MonoArray *modopt = NULL;
392                 MonoReflectionType *pt;
393
394                 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
395                         modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
396                 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
397                         modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
398                 encode_custom_modifiers_raw (assembly, modreq, modopt, &buf, error);
399                 if (!is_ok (error))
400                         goto leave;
401                 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
402                 encode_reflection_type_raw (assembly, pt, &buf, error);
403                 if (!is_ok (error))
404                         goto leave;
405         }
406         if (notypes)
407                 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
408         for (i = 0; i < notypes; ++i) {
409                 MonoReflectionType *pt;
410
411                 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
412                 encode_reflection_type_raw (assembly, pt, &buf, error);
413                 if (!is_ok (error))
414                         goto leave;
415         }
416
417         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
418 leave:
419         sigbuffer_free (&buf);
420         return idx;
421 }
422
423 guint32
424 mono_dynimage_encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
425 {
426         MONO_REQ_GC_UNSAFE_MODE;
427
428         error_init (error);
429
430         MonoDynamicTable *table;
431         guint32 *values;
432         guint32 idx, sig_idx;
433         guint nl = mono_array_length (ilgen->locals);
434         SigBuffer buf;
435         int i;
436
437         sigbuffer_init (&buf, 32);
438         sigbuffer_add_value (&buf, 0x07);
439         sigbuffer_add_value (&buf, nl);
440         for (i = 0; i < nl; ++i) {
441                 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
442                 
443                 if (lb->is_pinned)
444                         sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
445                 
446                 encode_reflection_type_raw (assembly, (MonoReflectionType*)lb->type, &buf, error);
447                 if (!is_ok (error)) {
448                         sigbuffer_free (&buf);
449                         return 0;
450                 }
451         }
452         sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
453         sigbuffer_free (&buf);
454
455         if (assembly->standalonesig_cache == NULL)
456                 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
457         idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
458         if (idx)
459                 return idx;
460
461         table = &assembly->tables [MONO_TABLE_STANDALONESIG];
462         idx = table->next_idx ++;
463         table->rows ++;
464         alloc_table (table, table->rows);
465         values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
466
467         values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
468
469         g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
470
471         return idx;
472 }
473
474
475 /*
476  * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
477  * dest may be misaligned.
478  */
479 static void
480 swap_with_size (char *dest, const char* val, int len, int nelem) {
481         MONO_REQ_GC_NEUTRAL_MODE;
482 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
483         int elem;
484
485         for (elem = 0; elem < nelem; ++elem) {
486                 switch (len) {
487                 case 1:
488                         *dest = *val;
489                         break;
490                 case 2:
491                         dest [0] = val [1];
492                         dest [1] = val [0];
493                         break;
494                 case 4:
495                         dest [0] = val [3];
496                         dest [1] = val [2];
497                         dest [2] = val [1];
498                         dest [3] = val [0];
499                         break;
500                 case 8:
501                         dest [0] = val [7];
502                         dest [1] = val [6];
503                         dest [2] = val [5];
504                         dest [3] = val [4];
505                         dest [4] = val [3];
506                         dest [5] = val [2];
507                         dest [6] = val [1];
508                         dest [7] = val [0];
509                         break;
510                 default:
511                         g_assert_not_reached ();
512                 }
513                 dest += len;
514                 val += len;
515         }
516 #else
517         memcpy (dest, val, len * nelem);
518 #endif
519 }
520
521
522 guint32
523 mono_dynimage_encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
524 {
525         MONO_REQ_GC_UNSAFE_MODE;
526
527         char blob_size [64];
528         char *b = blob_size;
529         char *box_val;
530         char* buf;
531         guint32 idx = 0, len = 0, dummy = 0;
532
533         buf = (char *)g_malloc (64);
534         if (!val) {
535                 *ret_type = MONO_TYPE_CLASS;
536                 len = 4;
537                 box_val = (char*)&dummy;
538         } else {
539                 box_val = ((char*)val) + sizeof (MonoObject);
540                 *ret_type = val->vtable->klass->byval_arg.type;
541         }
542 handle_enum:
543         switch (*ret_type) {
544         case MONO_TYPE_BOOLEAN:
545         case MONO_TYPE_U1:
546         case MONO_TYPE_I1:
547                 len = 1;
548                 break;
549         case MONO_TYPE_CHAR:
550         case MONO_TYPE_U2:
551         case MONO_TYPE_I2:
552                 len = 2;
553                 break;
554         case MONO_TYPE_U4:
555         case MONO_TYPE_I4:
556         case MONO_TYPE_R4:
557                 len = 4;
558                 break;
559         case MONO_TYPE_U8:
560         case MONO_TYPE_I8:
561                 len = 8;
562                 break;
563         case MONO_TYPE_R8:
564                 len = 8;
565                 break;
566         case MONO_TYPE_VALUETYPE: {
567                 MonoClass *klass = val->vtable->klass;
568                 
569                 if (klass->enumtype) {
570                         *ret_type = mono_class_enum_basetype (klass)->type;
571                         goto handle_enum;
572                 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
573                         len = 8;
574                 } else 
575                         g_error ("we can't encode valuetypes, we should have never reached this line");
576                 break;
577         }
578         case MONO_TYPE_CLASS:
579                 break;
580         case MONO_TYPE_STRING: {
581                 MonoString *str = (MonoString*)val;
582                 /* there is no signature */
583                 len = str->length * 2;
584                 mono_metadata_encode_value (len, b, &b);
585 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
586                 {
587                         char *swapped = g_malloc (2 * mono_string_length (str));
588                         const char *p = (const char*)mono_string_chars (str);
589
590                         swap_with_size (swapped, p, 2, mono_string_length (str));
591                         idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
592                         g_free (swapped);
593                 }
594 #else
595                 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
596 #endif
597
598                 g_free (buf);
599                 return idx;
600         }
601         case MONO_TYPE_GENERICINST:
602                 *ret_type = mono_class_get_generic_class (val->vtable->klass)->container_class->byval_arg.type;
603                 goto handle_enum;
604         default:
605                 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
606         }
607
608         /* there is no signature */
609         mono_metadata_encode_value (len, b, &b);
610 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
611         idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
612         swap_with_size (blob_size, box_val, len, 1);
613         mono_image_add_stream_data (&assembly->blob, blob_size, len);
614 #else
615         idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
616 #endif
617
618         g_free (buf);
619         return idx;
620 }
621
622 guint32
623 mono_dynimage_encode_field_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
624 {
625         MONO_REQ_GC_UNSAFE_MODE;
626
627         error_init (error);
628
629         SigBuffer buf;
630         guint32 idx;
631         guint32 typespec = 0;
632         MonoType *type;
633         MonoClass *klass;
634
635         type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
636         return_val_if_nok (error, 0);
637         klass = mono_class_from_mono_type (type);
638
639         sigbuffer_init (&buf, 32);
640         
641         sigbuffer_add_value (&buf, 0x06);
642         encode_custom_modifiers_raw (assembly, fb->modreq, fb->modopt, &buf, error);
643         if (!is_ok (error))
644                 goto fail;
645         /* encode custom attributes before the type */
646
647         if (mono_class_is_gtd (klass))
648                 typespec = create_typespec (assembly, type);
649
650         if (typespec) {
651                 MonoGenericClass *gclass;
652                 gclass = mono_metadata_lookup_generic_class (klass, mono_class_get_generic_container (klass)->context.class_inst, TRUE);
653                 encode_generic_class (assembly, gclass, &buf);
654         } else {
655                 encode_type (assembly, type, &buf);
656         }
657         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
658         sigbuffer_free (&buf);
659         return idx;
660 fail:
661         sigbuffer_free (&buf);
662         return 0;
663 }
664
665 #ifndef DISABLE_REFLECTION_EMIT
666 /*field_image is the image to which the eventual custom mods have been encoded against*/
667 guint32
668 mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
669 {
670         MONO_REQ_GC_NEUTRAL_MODE;
671
672         SigBuffer buf;
673         guint32 idx, i, token;
674
675         if (!assembly->save)
676                 return 0;
677
678         sigbuffer_init (&buf, 32);
679         
680         sigbuffer_add_value (&buf, 0x06);
681         /* encode custom attributes before the type */
682         if (type->num_mods) {
683                 for (i = 0; i < type->num_mods; ++i) {
684                         if (field_image) {
685                                 MonoError error;
686                                 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
687                                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
688
689                                 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
690                         } else {
691                                 token = type->modifiers [i].token;
692                         }
693
694                         if (type->modifiers [i].required)
695                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
696                         else
697                                 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
698
699                         sigbuffer_add_value (&buf, token);
700                 }
701         }
702         encode_type (assembly, type, &buf);
703         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
704         sigbuffer_free (&buf);
705         return idx;
706 }
707 #else /* DISABLE_REFLECTION_EMIT */
708 guint32
709 mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
710 {
711         g_assert_not_reached ();
712         return 0;
713 }
714 #endif /* DISABLE_REFLECTION_EMIT */
715
716 static guint32
717 create_typespec (MonoDynamicImage *assembly, MonoType *type)
718 {
719         MONO_REQ_GC_NEUTRAL_MODE;
720
721         MonoDynamicTable *table;
722         guint32 *values;
723         guint32 token;
724         SigBuffer buf;
725
726         if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
727                 return token;
728
729         sigbuffer_init (&buf, 32);
730         switch (type->type) {
731         case MONO_TYPE_FNPTR:
732         case MONO_TYPE_PTR:
733         case MONO_TYPE_SZARRAY:
734         case MONO_TYPE_ARRAY:
735         case MONO_TYPE_VAR:
736         case MONO_TYPE_MVAR:
737         case MONO_TYPE_GENERICINST:
738                 encode_type (assembly, type, &buf);
739                 break;
740         case MONO_TYPE_CLASS:
741         case MONO_TYPE_VALUETYPE: {
742                 MonoClass *k = mono_class_from_mono_type (type);
743                 if (!k || !mono_class_is_gtd (k)) {
744                         sigbuffer_free (&buf);
745                         return 0;
746                 }
747                 encode_type (assembly, type, &buf);
748                 break;
749         }
750         default:
751                 sigbuffer_free (&buf);
752                 return 0;
753         }
754
755         table = &assembly->tables [MONO_TABLE_TYPESPEC];
756         if (assembly->save) {
757                 token = sigbuffer_add_to_blob_cached (assembly, &buf);
758                 alloc_table (table, table->rows + 1);
759                 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
760                 values [MONO_TYPESPEC_SIGNATURE] = token;
761         }
762         sigbuffer_free (&buf);
763
764         token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
765         g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
766         table->next_idx ++;
767         return token;
768 }
769
770 guint32
771 mono_dynimage_encode_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
772 {
773         MONO_REQ_GC_UNSAFE_MODE;
774
775         MonoDynamicTable *table;
776         guint32 *values;
777         guint32 token, scope, enclosing;
778         MonoClass *klass;
779
780         /* if the type requires a typespec, we must try that first*/
781         if (try_typespec && (token = create_typespec (assembly, type)))
782                 return token;
783         token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
784         if (token)
785                 return token;
786         klass = mono_class_from_mono_type (type);
787
788         MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, mono_class_get_ref_info (klass));
789         /*
790          * If it's in the same module and not a generic type parameter:
791          */
792         if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) && 
793                         (type->type != MONO_TYPE_MVAR)) {
794                 token = MONO_TYPEDEFORREF_TYPEDEF | (MONO_HANDLE_GETVAL (tb, table_idx) << MONO_TYPEDEFORREF_BITS);
795                 mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, tb));
796                 return token;
797         }
798
799         if (klass->nested_in) {
800                 enclosing = mono_dynimage_encode_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
801                 /* get the typeref idx of the enclosing type */
802                 enclosing >>= MONO_TYPEDEFORREF_BITS;
803                 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
804         } else {
805                 scope = mono_reflection_resolution_scope_from_image (assembly, klass->image);
806         }
807         table = &assembly->tables [MONO_TABLE_TYPEREF];
808         if (assembly->save) {
809                 alloc_table (table, table->rows + 1);
810                 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
811                 values [MONO_TYPEREF_SCOPE] = scope;
812                 values [MONO_TYPEREF_NAME] = mono_dynstream_insert_string (&assembly->sheap, klass->name);
813                 values [MONO_TYPEREF_NAMESPACE] = mono_dynstream_insert_string (&assembly->sheap, klass->name_space);
814         }
815         token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
816         g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
817         table->next_idx ++;
818         mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, tb));
819         return token;
820 }
821
822 /*
823  * Despite the name, we handle also TypeSpec (with the above helper).
824  */
825 static guint32
826 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
827 {
828         return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
829 }
830
831 guint32
832 mono_dynimage_encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
833 {
834         SigBuffer buf;
835         int i;
836         guint32 nparams = context->method_inst->type_argc;
837         guint32 idx;
838
839         if (!assembly->save)
840                 return 0;
841
842         sigbuffer_init (&buf, 32);
843         /*
844          * FIXME: vararg, explicit_this, differenc call_conv values...
845          */
846         sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
847         sigbuffer_add_value (&buf, nparams);
848
849         for (i = 0; i < nparams; i++)
850                 encode_type (assembly, context->method_inst->type_argv [i], &buf);
851
852         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
853         sigbuffer_free (&buf);
854         return idx;
855 }
856
857 #ifndef DISABLE_REFLECTION_EMIT
858 static gboolean
859 encode_sighelper_arg (MonoDynamicImage *assembly, int i, MonoArrayHandle helper_arguments, MonoArrayHandle helper_modreqs, MonoArrayHandle helper_modopts, SigBuffer* buf, MonoError *error)
860 {
861         HANDLE_FUNCTION_ENTER();
862         error_init (error);
863         MonoArrayHandle modreqs = MONO_HANDLE_NEW (MonoArray, NULL);
864         MonoArrayHandle modopts = MONO_HANDLE_NEW (MonoArray, NULL);
865
866         if (!MONO_HANDLE_IS_NULL (helper_modreqs) && (i < mono_array_handle_length (helper_modreqs)))
867                 MONO_HANDLE_ARRAY_GETREF (modreqs, helper_modreqs, i);
868         if (!MONO_HANDLE_IS_NULL (helper_modopts) && (i < mono_array_handle_length (helper_modopts)))
869                 MONO_HANDLE_ARRAY_GETREF (modopts, helper_modopts, i);
870
871         encode_custom_modifiers (assembly, modreqs, modopts, buf, error);
872         if (!is_ok (error))
873                 goto leave;
874         MonoReflectionTypeHandle pt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
875         MONO_HANDLE_ARRAY_GETREF (pt, helper_arguments, i);
876         encode_reflection_type (assembly, pt, buf, error);
877         if (!is_ok (error))
878                 goto leave;
879 leave:
880         HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
881 }
882
883 guint32
884 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error)
885 {
886         SigBuffer buf;
887         guint32 nargs;
888         guint32 i, idx;
889
890         error_init (error);
891
892         if (!assembly->save)
893                 return 0;
894
895         /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
896         g_assert (MONO_HANDLE_GETVAL (helper, type) == 2);
897
898         MonoArrayHandle arguments = MONO_HANDLE_NEW_GET (MonoArray, helper, arguments);
899         if (!MONO_HANDLE_IS_NULL (arguments))
900                 nargs = mono_array_handle_length (arguments);
901         else
902                 nargs = 0;
903
904         sigbuffer_init (&buf, 32);
905
906         /* Encode calling convention */
907         /* Change Any to Standard */
908         if ((MONO_HANDLE_GETVAL (helper, call_conv) & 0x03) == 0x03)
909                 MONO_HANDLE_SETVAL (helper, call_conv, guint32, 0x01);
910         /* explicit_this implies has_this */
911         if (MONO_HANDLE_GETVAL (helper, call_conv) & 0x40)
912                 MONO_HANDLE_SETVAL (helper, call_conv, guint32, MONO_HANDLE_GETVAL (helper, call_conv) & 0x20);
913
914         if (MONO_HANDLE_GETVAL (helper, call_conv) == 0) { /* Unmanaged */
915                 idx = MONO_HANDLE_GETVAL (helper, unmanaged_call_conv) - 1;
916         } else {
917                 /* Managed */
918                 idx = MONO_HANDLE_GETVAL (helper, call_conv) & 0x60; /* has_this + explicit_this */
919                 if (MONO_HANDLE_GETVAL (helper, call_conv) & 0x02) /* varargs */
920                         idx += 0x05;
921         }
922
923         sigbuffer_add_byte (&buf, idx);
924         sigbuffer_add_value (&buf, nargs);
925         encode_reflection_type (assembly, MONO_HANDLE_NEW_GET (MonoReflectionType, helper, return_type), &buf, error);
926         if (!is_ok (error))
927                 goto fail;
928         MonoArrayHandle modreqs = MONO_HANDLE_NEW_GET (MonoArray, helper, modreqs);
929         MonoArrayHandle modopts = MONO_HANDLE_NEW_GET (MonoArray, helper, modopts);
930         for (i = 0; i < nargs; ++i) {
931                 if (!encode_sighelper_arg (assembly, i, arguments, modreqs, modopts, &buf, error))
932                         goto fail;
933         }
934         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
935         sigbuffer_free (&buf);
936
937         return idx;
938 fail:
939         sigbuffer_free (&buf);
940         return 0;
941 }
942 #else /* DISABLE_REFLECTION_EMIT */
943 guint32
944 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error)
945 {
946         g_assert_not_reached ();
947         return 0;
948 }
949 #endif /* DISABLE_REFLECTION_EMIT */
950
951 static MonoArray *
952 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
953 {
954         MonoReflectionModuleBuilder *module = sig->module;
955         MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
956         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
957         guint32 buflen, i;
958         MonoArray *result;
959         SigBuffer buf;
960
961         error_init (error);
962
963         sigbuffer_init (&buf, 32);
964
965         sigbuffer_add_value (&buf, 0x07);
966         sigbuffer_add_value (&buf, na);
967         if (assembly != NULL){
968                 for (i = 0; i < na; ++i) {
969                         MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
970                         encode_reflection_type_raw (assembly, type, &buf, error);
971                         if (!is_ok (error)) goto fail;
972                 }
973         }
974
975         buflen = buf.p - buf.buf;
976         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
977         if (!is_ok (error)) goto fail;
978         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
979         sigbuffer_free (&buf);
980         return result;
981 fail:
982         sigbuffer_free (&buf);
983         return NULL;
984 }
985
986 static MonoArray *
987 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
988 {
989         MonoDynamicImage *assembly = sig->module->dynamic_image;
990         guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
991         guint32 buflen, i;
992         MonoArray *result;
993         SigBuffer buf;
994
995         error_init (error);
996
997         sigbuffer_init (&buf, 32);
998
999         sigbuffer_add_value (&buf, 0x06);
1000         for (i = 0; i < na; ++i) {
1001                 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
1002                 encode_reflection_type_raw (assembly, type, &buf, error);
1003                 if (!is_ok (error))
1004                         goto fail;
1005         }
1006
1007         buflen = buf.p - buf.buf;
1008         result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
1009         if (!is_ok (error)) goto fail;
1010         memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
1011         sigbuffer_free (&buf);
1012
1013         return result;
1014 fail:
1015         sigbuffer_free (&buf);
1016         return NULL;
1017 }
1018
1019 static char*
1020 type_get_fully_qualified_name (MonoType *type)
1021 {
1022         MONO_REQ_GC_NEUTRAL_MODE;
1023
1024         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1025 }
1026
1027 #ifndef DISABLE_REFLECTION_EMIT_SAVE
1028 guint32
1029 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
1030 {
1031         MONO_REQ_GC_UNSAFE_MODE;
1032
1033         error_init (error);
1034
1035         char *str;
1036         SigBuffer buf;
1037         guint32 idx, len;
1038
1039         sigbuffer_init (&buf, 32);
1040
1041         sigbuffer_add_value (&buf, minfo->type);
1042
1043         switch (minfo->type) {
1044         case MONO_NATIVE_BYVALTSTR:
1045         case MONO_NATIVE_BYVALARRAY:
1046                 sigbuffer_add_value (&buf, minfo->count);
1047                 break;
1048         case MONO_NATIVE_LPARRAY:
1049                 if (minfo->eltype || minfo->has_size) {
1050                         sigbuffer_add_value (&buf, minfo->eltype);
1051                         if (minfo->has_size) {
1052                                 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1053                                 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1054
1055                                 /* LAMESPEC: ElemMult is undocumented */
1056                                 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1057                         }
1058                 }
1059                 break;
1060         case MONO_NATIVE_SAFEARRAY:
1061                 if (minfo->eltype)
1062                         sigbuffer_add_value (&buf, minfo->eltype);
1063                 break;
1064         case MONO_NATIVE_CUSTOM:
1065                 if (minfo->guid) {
1066                         str = mono_string_to_utf8_checked (minfo->guid, error);
1067                         if (!is_ok (error)) {
1068                                 sigbuffer_free (&buf);
1069                                 return 0;
1070                         }
1071                         len = strlen (str);
1072                         sigbuffer_add_value (&buf, len);
1073                         sigbuffer_add_mem (&buf, str, len);
1074                         g_free (str);
1075                 } else {
1076                         sigbuffer_add_value (&buf, 0);
1077                 }
1078                 /* native type name */
1079                 sigbuffer_add_value (&buf, 0);
1080                 /* custom marshaler type name */
1081                 if (minfo->marshaltype || minfo->marshaltyperef) {
1082                         if (minfo->marshaltyperef) {
1083                                 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
1084                                 if (!is_ok (error)) {
1085                                         sigbuffer_free (&buf);
1086                                         return 0;
1087                                 }
1088                                 str = type_get_fully_qualified_name (marshaltype);
1089                         } else {
1090                                 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
1091                                 if (!is_ok (error)) {
1092                                         sigbuffer_free (&buf);
1093                                         return 0;
1094                                 }
1095                         }
1096                         len = strlen (str);
1097                         sigbuffer_add_value (&buf, len);
1098                         sigbuffer_add_mem (&buf, str, len);
1099                         g_free (str);
1100                 } else {
1101                         /* FIXME: Actually a bug, since this field is required.  Punting for now ... */
1102                         sigbuffer_add_value (&buf, 0);
1103                 }
1104                 if (minfo->mcookie) {
1105                         str = mono_string_to_utf8_checked (minfo->mcookie, error);
1106                         if (!is_ok (error)) {
1107                                 sigbuffer_free (&buf);
1108                                 return 0;
1109                         }
1110                         len = strlen (str);
1111                         sigbuffer_add_value (&buf, len);
1112                         sigbuffer_add_mem (&buf, str, len);
1113                         g_free (str);
1114                 } else {
1115                         sigbuffer_add_value (&buf, 0);
1116                 }
1117                 break;
1118         default:
1119                 break;
1120         }
1121         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1122         sigbuffer_free (&buf);
1123         return idx;
1124 }
1125
1126 guint32
1127 mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
1128 {
1129         MONO_REQ_GC_UNSAFE_MODE;
1130
1131         error_init (error);
1132
1133         SigBuffer buf;
1134         guint32 nparams = 0;
1135         MonoReflectionMethodBuilder *mb = fb->get_method;
1136         MonoReflectionMethodBuilder *smb = fb->set_method;
1137         guint32 idx, i;
1138
1139         if (mb && mb->parameters)
1140                 nparams = mono_array_length (mb->parameters);
1141         if (!mb && smb && smb->parameters)
1142                 nparams = mono_array_length (smb->parameters) - 1;
1143         sigbuffer_init (&buf, 32);
1144         if (fb->call_conv & 0x20)
1145                 sigbuffer_add_byte (&buf, 0x28);
1146         else
1147                 sigbuffer_add_byte (&buf, 0x08);
1148         sigbuffer_add_value (&buf, nparams);
1149         if (mb) {
1150                 encode_reflection_type_raw (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
1151                 if (!is_ok (error))
1152                         goto fail;
1153                 for (i = 0; i < nparams; ++i) {
1154                         MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1155                         encode_reflection_type_raw (assembly, pt, &buf, error);
1156                         if (!is_ok (error))
1157                                 goto fail;
1158                 }
1159         } else if (smb && smb->parameters) {
1160                 /* the property type is the last param */
1161                 encode_reflection_type_raw (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
1162                 if (!is_ok (error))
1163                         goto fail;
1164
1165                 for (i = 0; i < nparams; ++i) {
1166                         MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1167                         encode_reflection_type_raw (assembly, pt, &buf, error);
1168                         if (!is_ok (error))
1169                                 goto fail;
1170                 }
1171         } else {
1172                 encode_reflection_type_raw (assembly, (MonoReflectionType*)fb->type, &buf, error);
1173                 if (!is_ok (error))
1174                         goto fail;
1175         }
1176
1177         idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1178         sigbuffer_free (&buf);
1179         return idx;
1180 fail:
1181         sigbuffer_free (&buf);
1182         return 0;
1183 }
1184
1185
1186 #else /*DISABLE_REFLECTION_EMIT_SAVE*/
1187 guint32
1188 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
1189 {
1190         g_assert_not_reached ();
1191         return 0;
1192 }
1193
1194 guint32
1195 mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
1196 {
1197         g_assert_not_reached ();
1198         return 0;
1199 }
1200 #endif /*DISABLE_REFLECTION_EMIT_SAVE*/
1201
1202 #ifndef DISABLE_REFLECTION_EMIT
1203 MonoArray *
1204 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
1205 {
1206         MonoError error;
1207         MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
1208         mono_error_set_pending_exception (&error);
1209         return result;
1210 }
1211
1212 MonoArray *
1213 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
1214 {
1215         MonoError error;
1216         MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
1217         mono_error_set_pending_exception (&error);
1218         return result;
1219 }
1220 #else /* DISABLE_REFLECTION_EMIT */
1221 MonoArray *
1222 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
1223 {
1224         g_assert_not_reached ();
1225         return NULL;
1226 }
1227
1228 MonoArray *
1229 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
1230 {
1231         g_assert_not_reached ();
1232         return NULL;
1233 }
1234
1235 #endif /* DISABLE_REFLECTION_EMIT */