2 * sre-encode.c: Routines for encoding SRE builders into a
3 * MonoDynamicImage and generating tokens.
7 * Paolo Molaro (lupus@ximian.com)
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
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
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"
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);
37 #define mono_type_array_get_and_resolve(array, index, error) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index), error)
40 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
42 return mono_dynstream_add_data (stream, data, len);
46 alloc_table (MonoDynamicTable *table, guint nrows)
48 mono_dynimage_alloc_table (table, nrows);
52 sigbuffer_init (SigBuffer *buf, int size)
54 MONO_REQ_GC_NEUTRAL_MODE;
56 buf->buf = (char *)g_malloc (size);
58 buf->end = buf->buf + size;
62 sigbuffer_make_room (SigBuffer *buf, int size)
64 MONO_REQ_GC_NEUTRAL_MODE;
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;
72 buf->end = buf->buf + new_size;
77 sigbuffer_add_value (SigBuffer *buf, guint32 val)
79 MONO_REQ_GC_NEUTRAL_MODE;
81 sigbuffer_make_room (buf, 6);
82 mono_metadata_encode_value (val, buf->p, &buf->p);
86 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
88 MONO_REQ_GC_NEUTRAL_MODE;
90 sigbuffer_make_room (buf, 1);
96 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
98 MONO_REQ_GC_NEUTRAL_MODE;
100 sigbuffer_make_room (buf, size);
101 memcpy (buf->p, p, size);
106 sigbuffer_free (SigBuffer *buf)
108 MONO_REQ_GC_NEUTRAL_MODE;
114 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
116 MONO_REQ_GC_NEUTRAL_MODE;
120 guint32 size = buf->p - buf->buf;
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);
129 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
131 MONO_REQ_GC_NEUTRAL_MODE;
134 MonoGenericInst *class_inst;
139 class_inst = gclass->context.class_inst;
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));
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);
153 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
155 MONO_REQ_GC_NEUTRAL_MODE;
158 g_assert_not_reached ();
163 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
167 case MONO_TYPE_BOOLEAN:
181 case MONO_TYPE_STRING:
182 case MONO_TYPE_OBJECT:
183 case MONO_TYPE_TYPEDBYREF:
184 sigbuffer_add_value (buf, type->type);
187 sigbuffer_add_value (buf, type->type);
188 encode_type (assembly, type->data.type, buf);
190 case MONO_TYPE_SZARRAY:
191 sigbuffer_add_value (buf, type->type);
192 encode_type (assembly, &type->data.klass->byval_arg, buf);
194 case MONO_TYPE_VALUETYPE:
195 case MONO_TYPE_CLASS: {
196 MonoClass *k = mono_class_from_mono_type (type);
198 if (k->generic_container) {
199 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
200 encode_generic_class (assembly, gclass, buf);
203 * Make sure we use the correct type.
205 sigbuffer_add_value (buf, k->byval_arg.type);
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.
211 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
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);
222 case MONO_TYPE_GENERICINST:
223 encode_generic_class (assembly, type->data.generic_class, buf);
227 sigbuffer_add_value (buf, type->type);
228 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
231 g_error ("need to encode type %x", type->type);
236 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
238 MONO_REQ_GC_UNSAFE_MODE;
240 mono_error_init (error);
243 sigbuffer_add_value (buf, MONO_TYPE_VOID);
247 MonoType *t = mono_reflection_type_get_handle (type, error);
248 return_if_nok (error);
249 encode_type (assembly, t, buf);
253 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
255 MONO_REQ_GC_UNSAFE_MODE;
259 mono_error_init (error);
262 for (i = 0; i < mono_array_length (modreq); ++i) {
263 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
264 return_if_nok (error);
265 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
266 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
270 for (i = 0; i < mono_array_length (modopt); ++i) {
271 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
272 return_if_nok (error);
273 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
274 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
279 #ifndef DISABLE_REFLECTION_EMIT
281 mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
283 MONO_REQ_GC_UNSAFE_MODE;
287 guint32 nparams = sig->param_count;
293 sigbuffer_init (&buf, 32);
295 * FIXME: vararg, explicit_this, differenc call_conv values...
297 idx = sig->call_convention;
299 idx |= 0x20; /* hasthis */
300 if (sig->generic_param_count)
301 idx |= 0x10; /* generic */
302 sigbuffer_add_byte (&buf, idx);
303 if (sig->generic_param_count)
304 sigbuffer_add_value (&buf, sig->generic_param_count);
305 sigbuffer_add_value (&buf, nparams);
306 encode_type (assembly, sig->ret, &buf);
307 for (i = 0; i < nparams; ++i) {
308 if (i == sig->sentinelpos)
309 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
310 encode_type (assembly, sig->params [i], &buf);
312 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
313 sigbuffer_free (&buf);
316 #else /* DISABLE_REFLECTION_EMIT */
318 mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
320 g_assert_not_reached ();
326 mono_dynimage_encode_method_builder_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
328 MONO_REQ_GC_UNSAFE_MODE;
330 mono_error_init (error);
333 * FIXME: reuse code from method_encode_signature().
337 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
338 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
339 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
342 sigbuffer_init (&buf, 32);
343 /* LAMESPEC: all the call conv spec is foobared */
344 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
345 if (mb->call_conv & 2)
346 idx |= 0x5; /* vararg */
347 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
348 idx |= 0x20; /* hasthis */
350 idx |= 0x10; /* generic */
351 sigbuffer_add_byte (&buf, idx);
353 sigbuffer_add_value (&buf, ngparams);
354 sigbuffer_add_value (&buf, nparams + notypes);
355 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
358 encode_reflection_type (assembly, mb->rtype, &buf, error);
361 for (i = 0; i < nparams; ++i) {
362 MonoArray *modreq = NULL;
363 MonoArray *modopt = NULL;
364 MonoReflectionType *pt;
366 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
367 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
368 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
369 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
370 encode_custom_modifiers (assembly, modreq, modopt, &buf, error);
373 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
374 encode_reflection_type (assembly, pt, &buf, error);
379 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
380 for (i = 0; i < notypes; ++i) {
381 MonoReflectionType *pt;
383 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
384 encode_reflection_type (assembly, pt, &buf, error);
389 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
391 sigbuffer_free (&buf);
396 mono_dynimage_encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
398 MONO_REQ_GC_UNSAFE_MODE;
400 mono_error_init (error);
402 MonoDynamicTable *table;
404 guint32 idx, sig_idx;
405 guint nl = mono_array_length (ilgen->locals);
409 sigbuffer_init (&buf, 32);
410 sigbuffer_add_value (&buf, 0x07);
411 sigbuffer_add_value (&buf, nl);
412 for (i = 0; i < nl; ++i) {
413 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
416 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
418 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
419 if (!is_ok (error)) {
420 sigbuffer_free (&buf);
424 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
425 sigbuffer_free (&buf);
427 if (assembly->standalonesig_cache == NULL)
428 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
429 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
433 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
434 idx = table->next_idx ++;
436 alloc_table (table, table->rows);
437 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
439 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
441 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
448 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
449 * dest may be misaligned.
452 swap_with_size (char *dest, const char* val, int len, int nelem) {
453 MONO_REQ_GC_NEUTRAL_MODE;
454 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
457 for (elem = 0; elem < nelem; ++elem) {
483 g_assert_not_reached ();
489 memcpy (dest, val, len * nelem);
495 mono_dynimage_encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
497 MONO_REQ_GC_UNSAFE_MODE;
503 guint32 idx = 0, len = 0, dummy = 0;
505 buf = (char *)g_malloc (64);
507 *ret_type = MONO_TYPE_CLASS;
509 box_val = (char*)&dummy;
511 box_val = ((char*)val) + sizeof (MonoObject);
512 *ret_type = val->vtable->klass->byval_arg.type;
516 case MONO_TYPE_BOOLEAN:
538 case MONO_TYPE_VALUETYPE: {
539 MonoClass *klass = val->vtable->klass;
541 if (klass->enumtype) {
542 *ret_type = mono_class_enum_basetype (klass)->type;
544 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
547 g_error ("we can't encode valuetypes, we should have never reached this line");
550 case MONO_TYPE_CLASS:
552 case MONO_TYPE_STRING: {
553 MonoString *str = (MonoString*)val;
554 /* there is no signature */
555 len = str->length * 2;
556 mono_metadata_encode_value (len, b, &b);
557 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
559 char *swapped = g_malloc (2 * mono_string_length (str));
560 const char *p = (const char*)mono_string_chars (str);
562 swap_with_size (swapped, p, 2, mono_string_length (str));
563 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
567 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
573 case MONO_TYPE_GENERICINST:
574 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
577 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
580 /* there is no signature */
581 mono_metadata_encode_value (len, b, &b);
582 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
583 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
584 swap_with_size (blob_size, box_val, len, 1);
585 mono_image_add_stream_data (&assembly->blob, blob_size, len);
587 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
596 mono_dynimage_encode_field_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
598 MONO_REQ_GC_UNSAFE_MODE;
600 mono_error_init (error);
604 guint32 typespec = 0;
608 mono_reflection_init_type_builder_generics (fb->type, error);
609 return_val_if_nok (error, 0);
611 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
612 return_val_if_nok (error, 0);
613 klass = mono_class_from_mono_type (type);
615 sigbuffer_init (&buf, 32);
617 sigbuffer_add_value (&buf, 0x06);
618 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
621 /* encode custom attributes before the type */
623 if (klass->generic_container)
624 typespec = create_typespec (assembly, type);
627 MonoGenericClass *gclass;
628 gclass = mono_metadata_lookup_generic_class (klass, klass->generic_container->context.class_inst, TRUE);
629 encode_generic_class (assembly, gclass, &buf);
631 encode_type (assembly, type, &buf);
633 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
634 sigbuffer_free (&buf);
637 sigbuffer_free (&buf);
641 #ifndef DISABLE_REFLECTION_EMIT
642 /*field_image is the image to which the eventual custom mods have been encoded against*/
644 mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
646 MONO_REQ_GC_NEUTRAL_MODE;
649 guint32 idx, i, token;
654 sigbuffer_init (&buf, 32);
656 sigbuffer_add_value (&buf, 0x06);
657 /* encode custom attributes before the type */
658 if (type->num_mods) {
659 for (i = 0; i < type->num_mods; ++i) {
662 MonoClass *klass = mono_class_get_checked (field_image, type->modifiers [i].token, &error);
663 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
665 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
667 token = type->modifiers [i].token;
670 if (type->modifiers [i].required)
671 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
673 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
675 sigbuffer_add_value (&buf, token);
678 encode_type (assembly, type, &buf);
679 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
680 sigbuffer_free (&buf);
683 #else /* DISABLE_REFLECTION_EMIT */
685 mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
687 g_assert_not_reached ();
690 #endif /* DISABLE_REFLECTION_EMIT */
693 create_typespec (MonoDynamicImage *assembly, MonoType *type)
695 MONO_REQ_GC_NEUTRAL_MODE;
697 MonoDynamicTable *table;
702 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
705 sigbuffer_init (&buf, 32);
706 switch (type->type) {
707 case MONO_TYPE_FNPTR:
709 case MONO_TYPE_SZARRAY:
710 case MONO_TYPE_ARRAY:
713 case MONO_TYPE_GENERICINST:
714 encode_type (assembly, type, &buf);
716 case MONO_TYPE_CLASS:
717 case MONO_TYPE_VALUETYPE: {
718 MonoClass *k = mono_class_from_mono_type (type);
719 if (!k || !k->generic_container) {
720 sigbuffer_free (&buf);
723 encode_type (assembly, type, &buf);
727 sigbuffer_free (&buf);
731 table = &assembly->tables [MONO_TABLE_TYPESPEC];
732 if (assembly->save) {
733 token = sigbuffer_add_to_blob_cached (assembly, &buf);
734 alloc_table (table, table->rows + 1);
735 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
736 values [MONO_TYPESPEC_SIGNATURE] = token;
738 sigbuffer_free (&buf);
740 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
741 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
747 mono_dynimage_encode_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
749 MONO_REQ_GC_UNSAFE_MODE;
751 MonoDynamicTable *table;
753 guint32 token, scope, enclosing;
756 /* if the type requires a typespec, we must try that first*/
757 if (try_typespec && (token = create_typespec (assembly, type)))
759 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
762 klass = mono_class_from_mono_type (type);
764 klass = mono_class_from_mono_type (type);
767 * If it's in the same module and not a generic type parameter:
769 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
770 (type->type != MONO_TYPE_MVAR)) {
771 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (klass);
772 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
773 mono_dynamic_image_register_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
777 if (klass->nested_in) {
778 enclosing = mono_dynimage_encode_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
779 /* get the typeref idx of the enclosing type */
780 enclosing >>= MONO_TYPEDEFORREF_BITS;
781 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
783 scope = mono_reflection_resolution_scope_from_image (assembly, klass->image);
785 table = &assembly->tables [MONO_TABLE_TYPEREF];
786 if (assembly->save) {
787 alloc_table (table, table->rows + 1);
788 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
789 values [MONO_TYPEREF_SCOPE] = scope;
790 values [MONO_TYPEREF_NAME] = mono_dynstream_insert_string (&assembly->sheap, klass->name);
791 values [MONO_TYPEREF_NAMESPACE] = mono_dynstream_insert_string (&assembly->sheap, klass->name_space);
793 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
794 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
796 mono_dynamic_image_register_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
801 * Despite the name, we handle also TypeSpec (with the above helper).
804 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
806 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
810 mono_dynimage_encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
814 guint32 nparams = mono_array_length (mb->generic_params);
820 sigbuffer_init (&buf, 32);
822 sigbuffer_add_value (&buf, 0xa);
823 sigbuffer_add_value (&buf, nparams);
825 for (i = 0; i < nparams; i++) {
826 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
827 sigbuffer_add_value (&buf, i);
830 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
831 sigbuffer_free (&buf);
836 mono_dynimage_encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
840 guint32 nparams = context->method_inst->type_argc;
846 sigbuffer_init (&buf, 32);
848 * FIXME: vararg, explicit_this, differenc call_conv values...
850 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
851 sigbuffer_add_value (&buf, nparams);
853 for (i = 0; i < nparams; i++)
854 encode_type (assembly, context->method_inst->type_argv [i], &buf);
856 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
857 sigbuffer_free (&buf);
861 #ifndef DISABLE_REFLECTION_EMIT
863 mono_dynimage_encode_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
865 MonoDynamicTable *table;
874 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
875 * ie. what we'd normally use as the generic type in a TypeSpec signature.
876 * Because of this, we must not insert it into the `typeref' hash table.
878 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
879 return_val_if_nok (error, 0);
880 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
884 sigbuffer_init (&buf, 32);
886 g_assert (tb->generic_params);
887 klass = mono_class_from_mono_type (type);
889 if (tb->generic_container) {
890 if (!mono_reflection_create_generic_class (tb, error))
894 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
895 g_assert (klass->generic_container);
896 sigbuffer_add_value (&buf, klass->byval_arg.type);
897 sigbuffer_add_value (&buf, mono_dynimage_encode_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
899 count = mono_array_length (tb->generic_params);
900 sigbuffer_add_value (&buf, count);
901 for (i = 0; i < count; i++) {
902 MonoReflectionGenericParam *gparam;
904 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
905 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
909 encode_type (assembly, gparam_type, &buf);
912 table = &assembly->tables [MONO_TABLE_TYPESPEC];
914 if (assembly->save) {
915 token = sigbuffer_add_to_blob_cached (assembly, &buf);
916 alloc_table (table, table->rows + 1);
917 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
918 values [MONO_TYPESPEC_SIGNATURE] = token;
920 sigbuffer_free (&buf);
922 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
923 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
927 sigbuffer_free (&buf);
930 #else /*DISABLE_REFLECTION_EMIT*/
932 mono_dynimage_encode_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
934 g_assert_not_reached ();
937 #endif /*DISABLE_REFLECTION_EMIT*/
939 #ifndef DISABLE_REFLECTION_EMIT
941 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
947 mono_error_init (error);
952 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
953 g_assert (helper->type == 2);
955 if (helper->arguments)
956 nargs = mono_array_length (helper->arguments);
960 sigbuffer_init (&buf, 32);
962 /* Encode calling convention */
963 /* Change Any to Standard */
964 if ((helper->call_conv & 0x03) == 0x03)
965 helper->call_conv = 0x01;
966 /* explicit_this implies has_this */
967 if (helper->call_conv & 0x40)
968 helper->call_conv &= 0x20;
970 if (helper->call_conv == 0) { /* Unmanaged */
971 idx = helper->unmanaged_call_conv - 1;
974 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
975 if (helper->call_conv & 0x02) /* varargs */
979 sigbuffer_add_byte (&buf, idx);
980 sigbuffer_add_value (&buf, nargs);
981 encode_reflection_type (assembly, helper->return_type, &buf, error);
984 for (i = 0; i < nargs; ++i) {
985 MonoArray *modreqs = NULL;
986 MonoArray *modopts = NULL;
987 MonoReflectionType *pt;
989 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
990 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
991 if (helper->modopts && (i < mono_array_length (helper->modopts)))
992 modopts = mono_array_get (helper->modopts, MonoArray*, i);
994 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
997 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
998 encode_reflection_type (assembly, pt, &buf, error);
1002 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1003 sigbuffer_free (&buf);
1007 sigbuffer_free (&buf);
1010 #else /* DISABLE_REFLECTION_EMIT */
1012 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
1014 g_assert_not_reached ();
1017 #endif /* DISABLE_REFLECTION_EMIT */
1020 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
1022 MonoReflectionModuleBuilder *module = sig->module;
1023 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
1024 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
1029 mono_error_init (error);
1031 sigbuffer_init (&buf, 32);
1033 sigbuffer_add_value (&buf, 0x07);
1034 sigbuffer_add_value (&buf, na);
1035 if (assembly != NULL){
1036 for (i = 0; i < na; ++i) {
1037 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
1038 encode_reflection_type (assembly, type, &buf, error);
1039 if (!is_ok (error)) goto fail;
1043 buflen = buf.p - buf.buf;
1044 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
1045 if (!is_ok (error)) goto fail;
1046 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
1047 sigbuffer_free (&buf);
1050 sigbuffer_free (&buf);
1055 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
1057 MonoDynamicImage *assembly = sig->module->dynamic_image;
1058 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
1063 mono_error_init (error);
1065 sigbuffer_init (&buf, 32);
1067 sigbuffer_add_value (&buf, 0x06);
1068 for (i = 0; i < na; ++i) {
1069 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
1070 encode_reflection_type (assembly, type, &buf, error);
1075 buflen = buf.p - buf.buf;
1076 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
1077 if (!is_ok (error)) goto fail;
1078 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
1079 sigbuffer_free (&buf);
1083 sigbuffer_free (&buf);
1088 type_get_fully_qualified_name (MonoType *type)
1090 MONO_REQ_GC_NEUTRAL_MODE;
1092 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1095 #ifndef DISABLE_REFLECTION_EMIT_SAVE
1097 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
1099 MONO_REQ_GC_UNSAFE_MODE;
1101 mono_error_init (error);
1107 sigbuffer_init (&buf, 32);
1109 sigbuffer_add_value (&buf, minfo->type);
1111 switch (minfo->type) {
1112 case MONO_NATIVE_BYVALTSTR:
1113 case MONO_NATIVE_BYVALARRAY:
1114 sigbuffer_add_value (&buf, minfo->count);
1116 case MONO_NATIVE_LPARRAY:
1117 if (minfo->eltype || minfo->has_size) {
1118 sigbuffer_add_value (&buf, minfo->eltype);
1119 if (minfo->has_size) {
1120 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1121 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1123 /* LAMESPEC: ElemMult is undocumented */
1124 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1128 case MONO_NATIVE_SAFEARRAY:
1130 sigbuffer_add_value (&buf, minfo->eltype);
1132 case MONO_NATIVE_CUSTOM:
1134 str = mono_string_to_utf8_checked (minfo->guid, error);
1135 if (!is_ok (error)) {
1136 sigbuffer_free (&buf);
1140 sigbuffer_add_value (&buf, len);
1141 sigbuffer_add_mem (&buf, str, len);
1144 sigbuffer_add_value (&buf, 0);
1146 /* native type name */
1147 sigbuffer_add_value (&buf, 0);
1148 /* custom marshaler type name */
1149 if (minfo->marshaltype || minfo->marshaltyperef) {
1150 if (minfo->marshaltyperef) {
1151 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
1152 if (!is_ok (error)) {
1153 sigbuffer_free (&buf);
1156 str = type_get_fully_qualified_name (marshaltype);
1158 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
1159 if (!is_ok (error)) {
1160 sigbuffer_free (&buf);
1165 sigbuffer_add_value (&buf, len);
1166 sigbuffer_add_mem (&buf, str, len);
1169 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1170 sigbuffer_add_value (&buf, 0);
1172 if (minfo->mcookie) {
1173 str = mono_string_to_utf8_checked (minfo->mcookie, error);
1174 if (!is_ok (error)) {
1175 sigbuffer_free (&buf);
1179 sigbuffer_add_value (&buf, len);
1180 sigbuffer_add_mem (&buf, str, len);
1183 sigbuffer_add_value (&buf, 0);
1189 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1190 sigbuffer_free (&buf);
1195 mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
1197 MONO_REQ_GC_UNSAFE_MODE;
1199 mono_error_init (error);
1202 guint32 nparams = 0;
1203 MonoReflectionMethodBuilder *mb = fb->get_method;
1204 MonoReflectionMethodBuilder *smb = fb->set_method;
1207 if (mb && mb->parameters)
1208 nparams = mono_array_length (mb->parameters);
1209 if (!mb && smb && smb->parameters)
1210 nparams = mono_array_length (smb->parameters) - 1;
1211 sigbuffer_init (&buf, 32);
1212 if (fb->call_conv & 0x20)
1213 sigbuffer_add_byte (&buf, 0x28);
1215 sigbuffer_add_byte (&buf, 0x08);
1216 sigbuffer_add_value (&buf, nparams);
1218 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
1221 for (i = 0; i < nparams; ++i) {
1222 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1223 encode_reflection_type (assembly, pt, &buf, error);
1227 } else if (smb && smb->parameters) {
1228 /* the property type is the last param */
1229 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
1233 for (i = 0; i < nparams; ++i) {
1234 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1235 encode_reflection_type (assembly, pt, &buf, error);
1240 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
1245 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1246 sigbuffer_free (&buf);
1249 sigbuffer_free (&buf);
1254 #else /*DISABLE_REFLECTION_EMIT_SAVE*/
1256 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
1258 g_assert_not_reached ();
1263 mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
1265 g_assert_not_reached ();
1268 #endif /*DISABLE_REFLECTION_EMIT_SAVE*/
1270 #ifndef DISABLE_REFLECTION_EMIT
1272 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
1275 MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
1276 mono_error_set_pending_exception (&error);
1281 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
1284 MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
1285 mono_error_set_pending_exception (&error);
1288 #else /* DISABLE_REFLECTION_EMIT */
1290 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
1292 g_assert_not_reached ();
1297 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
1299 g_assert_not_reached ();
1303 #endif /* DISABLE_REFLECTION_EMIT */