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