3 * Routines for encoding SRE builders into a
4 * MonoDynamicImage and generating tokens.
8 * Paolo Molaro (lupus@ximian.com)
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
15 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
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"
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);
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 (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);
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, MonoReflectionTypeHandle type, SigBuffer *buf, MonoError *error)
238 MONO_REQ_GC_UNSAFE_MODE;
243 sigbuffer_add_value (buf, MONO_TYPE_VOID);
247 MonoType *t = mono_reflection_type_handle_mono_type (type, error);
248 return_if_nok (error);
249 encode_type (assembly, t, buf);
253 encode_reflection_type_raw (MonoDynamicImage *assembly, MonoReflectionType* type_raw, SigBuffer *buf, MonoError *error)
255 HANDLE_FUNCTION_ENTER (); /* FIXME callers of encode_reflection_type_raw should use handles */
257 MONO_HANDLE_DCL (MonoReflectionType, type);
258 encode_reflection_type (assembly, type, buf, error);
259 HANDLE_FUNCTION_RETURN ();
264 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArrayHandle modreq, MonoArrayHandle modopt, SigBuffer *buf, MonoError *error)
266 HANDLE_FUNCTION_ENTER ();
267 MONO_REQ_GC_UNSAFE_MODE;
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);
278 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
279 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
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);
287 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
288 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
292 HANDLE_FUNCTION_RETURN ();
296 encode_custom_modifiers_raw (MonoDynamicImage *assembly, MonoArray *modreq_raw, MonoArray *modopt_raw, SigBuffer *buf, MonoError *error)
298 HANDLE_FUNCTION_ENTER (); /* FIXME callers of encode_custom_modifiers_raw should use handles */
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 ();
307 #ifndef DISABLE_REFLECTION_EMIT
309 mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
311 MONO_REQ_GC_UNSAFE_MODE;
315 guint32 nparams = sig->param_count;
321 sigbuffer_init (&buf, 32);
323 * FIXME: vararg, explicit_this, differenc call_conv values...
325 idx = sig->call_convention;
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);
340 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
341 sigbuffer_free (&buf);
344 #else /* DISABLE_REFLECTION_EMIT */
346 mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
348 g_assert_not_reached ();
354 mono_dynimage_encode_method_builder_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
356 MONO_REQ_GC_UNSAFE_MODE;
361 * FIXME: reuse code from method_encode_signature().
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;
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 */
378 idx |= 0x10; /* generic */
379 sigbuffer_add_byte (&buf, idx);
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);
386 encode_reflection_type_raw (assembly, mb->rtype, &buf, error);
389 for (i = 0; i < nparams; ++i) {
390 MonoArray *modreq = NULL;
391 MonoArray *modopt = NULL;
392 MonoReflectionType *pt;
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);
401 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
402 encode_reflection_type_raw (assembly, pt, &buf, error);
407 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
408 for (i = 0; i < notypes; ++i) {
409 MonoReflectionType *pt;
411 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
412 encode_reflection_type_raw (assembly, pt, &buf, error);
417 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
419 sigbuffer_free (&buf);
424 mono_dynimage_encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
426 MONO_REQ_GC_UNSAFE_MODE;
430 MonoDynamicTable *table;
432 guint32 idx, sig_idx;
433 guint nl = mono_array_length (ilgen->locals);
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);
444 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
446 encode_reflection_type_raw (assembly, (MonoReflectionType*)lb->type, &buf, error);
447 if (!is_ok (error)) {
448 sigbuffer_free (&buf);
452 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
453 sigbuffer_free (&buf);
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)));
461 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
462 idx = table->next_idx ++;
464 alloc_table (table, table->rows);
465 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
467 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
469 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
476 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
477 * dest may be misaligned.
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
485 for (elem = 0; elem < nelem; ++elem) {
511 g_assert_not_reached ();
517 memcpy (dest, val, len * nelem);
523 mono_dynimage_encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
525 MONO_REQ_GC_UNSAFE_MODE;
531 guint32 idx = 0, len = 0, dummy = 0;
533 buf = (char *)g_malloc (64);
535 *ret_type = MONO_TYPE_CLASS;
537 box_val = (char*)&dummy;
539 box_val = ((char*)val) + sizeof (MonoObject);
540 *ret_type = val->vtable->klass->byval_arg.type;
544 case MONO_TYPE_BOOLEAN:
566 case MONO_TYPE_VALUETYPE: {
567 MonoClass *klass = val->vtable->klass;
569 if (klass->enumtype) {
570 *ret_type = mono_class_enum_basetype (klass)->type;
572 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
575 g_error ("we can't encode valuetypes, we should have never reached this line");
578 case MONO_TYPE_CLASS:
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
587 char *swapped = g_malloc (2 * mono_string_length (str));
588 const char *p = (const char*)mono_string_chars (str);
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);
595 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
601 case MONO_TYPE_GENERICINST:
602 *ret_type = mono_class_get_generic_class (val->vtable->klass)->container_class->byval_arg.type;
605 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
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);
615 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
623 mono_dynimage_encode_field_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
625 MONO_REQ_GC_UNSAFE_MODE;
631 guint32 typespec = 0;
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);
639 sigbuffer_init (&buf, 32);
641 sigbuffer_add_value (&buf, 0x06);
642 encode_custom_modifiers_raw (assembly, fb->modreq, fb->modopt, &buf, error);
645 /* encode custom attributes before the type */
647 if (mono_class_is_gtd (klass))
648 typespec = create_typespec (assembly, type);
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);
655 encode_type (assembly, type, &buf);
657 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
658 sigbuffer_free (&buf);
661 sigbuffer_free (&buf);
665 #ifndef DISABLE_REFLECTION_EMIT
666 /*field_image is the image to which the eventual custom mods have been encoded against*/
668 mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
670 MONO_REQ_GC_NEUTRAL_MODE;
673 guint32 idx, i, token;
678 sigbuffer_init (&buf, 32);
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) {
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 */
689 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
691 token = type->modifiers [i].token;
694 if (type->modifiers [i].required)
695 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
697 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
699 sigbuffer_add_value (&buf, token);
702 encode_type (assembly, type, &buf);
703 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
704 sigbuffer_free (&buf);
707 #else /* DISABLE_REFLECTION_EMIT */
709 mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
711 g_assert_not_reached ();
714 #endif /* DISABLE_REFLECTION_EMIT */
717 create_typespec (MonoDynamicImage *assembly, MonoType *type)
719 MONO_REQ_GC_NEUTRAL_MODE;
721 MonoDynamicTable *table;
726 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
729 sigbuffer_init (&buf, 32);
730 switch (type->type) {
731 case MONO_TYPE_FNPTR:
733 case MONO_TYPE_SZARRAY:
734 case MONO_TYPE_ARRAY:
737 case MONO_TYPE_GENERICINST:
738 encode_type (assembly, type, &buf);
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);
747 encode_type (assembly, type, &buf);
751 sigbuffer_free (&buf);
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;
762 sigbuffer_free (&buf);
764 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
765 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
771 mono_dynimage_encode_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
773 MONO_REQ_GC_UNSAFE_MODE;
774 HANDLE_FUNCTION_ENTER ();
776 MonoDynamicTable *table;
778 guint32 token, scope, enclosing;
781 /* if the type requires a typespec, we must try that first*/
782 if (try_typespec && (token = create_typespec (assembly, type)))
784 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
787 klass = mono_class_from_mono_type (type);
789 MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, mono_class_get_ref_info (klass));
791 * If it's in the same module and not a generic type parameter:
793 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
794 (type->type != MONO_TYPE_MVAR)) {
795 token = MONO_TYPEDEFORREF_TYPEDEF | (MONO_HANDLE_GETVAL (tb, table_idx) << MONO_TYPEDEFORREF_BITS);
796 mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, tb));
800 if (klass->nested_in) {
801 enclosing = mono_dynimage_encode_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
802 /* get the typeref idx of the enclosing type */
803 enclosing >>= MONO_TYPEDEFORREF_BITS;
804 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
806 scope = mono_reflection_resolution_scope_from_image (assembly, klass->image);
808 table = &assembly->tables [MONO_TABLE_TYPEREF];
809 if (assembly->save) {
810 alloc_table (table, table->rows + 1);
811 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
812 values [MONO_TYPEREF_SCOPE] = scope;
813 values [MONO_TYPEREF_NAME] = mono_dynstream_insert_string (&assembly->sheap, klass->name);
814 values [MONO_TYPEREF_NAMESPACE] = mono_dynstream_insert_string (&assembly->sheap, klass->name_space);
816 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
817 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
819 mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, tb));
821 HANDLE_FUNCTION_RETURN_VAL (token);
825 * Despite the name, we handle also TypeSpec (with the above helper).
828 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
830 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
834 mono_dynimage_encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
838 guint32 nparams = context->method_inst->type_argc;
844 sigbuffer_init (&buf, 32);
846 * FIXME: vararg, explicit_this, differenc call_conv values...
848 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
849 sigbuffer_add_value (&buf, nparams);
851 for (i = 0; i < nparams; i++)
852 encode_type (assembly, context->method_inst->type_argv [i], &buf);
854 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
855 sigbuffer_free (&buf);
859 #ifndef DISABLE_REFLECTION_EMIT
861 encode_sighelper_arg (MonoDynamicImage *assembly, int i, MonoArrayHandle helper_arguments, MonoArrayHandle helper_modreqs, MonoArrayHandle helper_modopts, SigBuffer* buf, MonoError *error)
863 HANDLE_FUNCTION_ENTER();
865 MonoArrayHandle modreqs = MONO_HANDLE_NEW (MonoArray, NULL);
866 MonoArrayHandle modopts = MONO_HANDLE_NEW (MonoArray, NULL);
868 if (!MONO_HANDLE_IS_NULL (helper_modreqs) && (i < mono_array_handle_length (helper_modreqs)))
869 MONO_HANDLE_ARRAY_GETREF (modreqs, helper_modreqs, i);
870 if (!MONO_HANDLE_IS_NULL (helper_modopts) && (i < mono_array_handle_length (helper_modopts)))
871 MONO_HANDLE_ARRAY_GETREF (modopts, helper_modopts, i);
873 encode_custom_modifiers (assembly, modreqs, modopts, buf, error);
876 MonoReflectionTypeHandle pt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
877 MONO_HANDLE_ARRAY_GETREF (pt, helper_arguments, i);
878 encode_reflection_type (assembly, pt, buf, error);
882 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
886 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error)
897 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
898 g_assert (MONO_HANDLE_GETVAL (helper, type) == 2);
900 MonoArrayHandle arguments = MONO_HANDLE_NEW_GET (MonoArray, helper, arguments);
901 if (!MONO_HANDLE_IS_NULL (arguments))
902 nargs = mono_array_handle_length (arguments);
906 sigbuffer_init (&buf, 32);
908 /* Encode calling convention */
909 /* Change Any to Standard */
910 if ((MONO_HANDLE_GETVAL (helper, call_conv) & 0x03) == 0x03)
911 MONO_HANDLE_SETVAL (helper, call_conv, guint32, 0x01);
912 /* explicit_this implies has_this */
913 if (MONO_HANDLE_GETVAL (helper, call_conv) & 0x40)
914 MONO_HANDLE_SETVAL (helper, call_conv, guint32, MONO_HANDLE_GETVAL (helper, call_conv) & 0x20);
916 if (MONO_HANDLE_GETVAL (helper, call_conv) == 0) { /* Unmanaged */
917 idx = MONO_HANDLE_GETVAL (helper, unmanaged_call_conv) - 1;
920 idx = MONO_HANDLE_GETVAL (helper, call_conv) & 0x60; /* has_this + explicit_this */
921 if (MONO_HANDLE_GETVAL (helper, call_conv) & 0x02) /* varargs */
925 sigbuffer_add_byte (&buf, idx);
926 sigbuffer_add_value (&buf, nargs);
927 encode_reflection_type (assembly, MONO_HANDLE_NEW_GET (MonoReflectionType, helper, return_type), &buf, error);
930 MonoArrayHandle modreqs = MONO_HANDLE_NEW_GET (MonoArray, helper, modreqs);
931 MonoArrayHandle modopts = MONO_HANDLE_NEW_GET (MonoArray, helper, modopts);
932 for (i = 0; i < nargs; ++i) {
933 if (!encode_sighelper_arg (assembly, i, arguments, modreqs, modopts, &buf, error))
936 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
937 sigbuffer_free (&buf);
941 sigbuffer_free (&buf);
944 #else /* DISABLE_REFLECTION_EMIT */
946 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error)
948 g_assert_not_reached ();
951 #endif /* DISABLE_REFLECTION_EMIT */
954 encode_reflection_types (MonoDynamicImage *assembly, MonoArrayHandle sig_arguments, int i, SigBuffer *buf, MonoError *error)
956 HANDLE_FUNCTION_ENTER ();
958 MonoReflectionTypeHandle type = MONO_HANDLE_NEW (MonoReflectionType, NULL);
959 MONO_HANDLE_ARRAY_GETREF (type, sig_arguments, i);
960 encode_reflection_type (assembly, type, buf, error);
961 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
964 static MonoArrayHandle
965 reflection_sighelper_get_signature_local (MonoReflectionSigHelperHandle sig, MonoError *error)
967 MonoReflectionModuleBuilderHandle module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, sig, module);
968 MonoDynamicImage *assembly = MONO_HANDLE_IS_NULL (module) ? NULL : MONO_HANDLE_GETVAL (module, dynamic_image);
969 MonoArrayHandle sig_arguments = MONO_HANDLE_NEW_GET (MonoArray, sig, arguments);
970 guint32 na = MONO_HANDLE_IS_NULL (sig_arguments) ? 0 : mono_array_handle_length (sig_arguments);
976 sigbuffer_init (&buf, 32);
978 sigbuffer_add_value (&buf, 0x07);
979 sigbuffer_add_value (&buf, na);
980 if (assembly != NULL){
981 for (i = 0; i < na; ++i) {
982 if (!encode_reflection_types (assembly, sig_arguments, i, &buf, error))
987 buflen = buf.p - buf.buf;
988 MonoArrayHandle result = mono_array_new_handle (mono_domain_get (), mono_defaults.byte_class, buflen, error);
989 if (!is_ok (error)) goto fail;
991 void *base = MONO_ARRAY_HANDLE_PIN (result, char, 0, &gchandle);
992 memcpy (base, buf.buf, buflen);
993 sigbuffer_free (&buf);
994 mono_gchandle_free (gchandle);
997 sigbuffer_free (&buf);
998 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
1001 static MonoArrayHandle
1002 reflection_sighelper_get_signature_field (MonoReflectionSigHelperHandle sig, MonoError *error)
1004 MonoReflectionModuleBuilderHandle module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, sig, module);
1005 MonoDynamicImage *assembly = MONO_HANDLE_GETVAL (module, dynamic_image);
1006 MonoArrayHandle sig_arguments = MONO_HANDLE_NEW_GET (MonoArray, sig, arguments);
1007 guint32 na = MONO_HANDLE_IS_NULL (sig_arguments) ? 0 : mono_array_handle_length (sig_arguments);
1013 sigbuffer_init (&buf, 32);
1015 sigbuffer_add_value (&buf, 0x06);
1016 for (i = 0; i < na; ++i) {
1017 if (! encode_reflection_types (assembly, sig_arguments, i, &buf, error))
1021 buflen = buf.p - buf.buf;
1022 MonoArrayHandle result = mono_array_new_handle (mono_domain_get (), mono_defaults.byte_class, buflen, error);
1023 if (!is_ok (error)) goto fail;
1025 void *base = MONO_ARRAY_HANDLE_PIN (result, char, 0, &gchandle);
1026 memcpy (base, buf.buf, buflen);
1027 sigbuffer_free (&buf);
1028 mono_gchandle_free (gchandle);
1032 sigbuffer_free (&buf);
1033 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
1037 type_get_fully_qualified_name (MonoType *type)
1039 MONO_REQ_GC_NEUTRAL_MODE;
1041 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1044 #ifndef DISABLE_REFLECTION_EMIT_SAVE
1046 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
1048 MONO_REQ_GC_UNSAFE_MODE;
1056 sigbuffer_init (&buf, 32);
1058 sigbuffer_add_value (&buf, minfo->type);
1060 switch (minfo->type) {
1061 case MONO_NATIVE_BYVALTSTR:
1062 case MONO_NATIVE_BYVALARRAY:
1063 sigbuffer_add_value (&buf, minfo->count);
1065 case MONO_NATIVE_LPARRAY:
1066 if (minfo->eltype || minfo->has_size) {
1067 sigbuffer_add_value (&buf, minfo->eltype);
1068 if (minfo->has_size) {
1069 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1070 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1072 /* LAMESPEC: ElemMult is undocumented */
1073 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1077 case MONO_NATIVE_SAFEARRAY:
1079 sigbuffer_add_value (&buf, minfo->eltype);
1081 case MONO_NATIVE_CUSTOM:
1083 str = mono_string_to_utf8_checked (minfo->guid, error);
1084 if (!is_ok (error)) {
1085 sigbuffer_free (&buf);
1089 sigbuffer_add_value (&buf, len);
1090 sigbuffer_add_mem (&buf, str, len);
1093 sigbuffer_add_value (&buf, 0);
1095 /* native type name */
1096 sigbuffer_add_value (&buf, 0);
1097 /* custom marshaler type name */
1098 if (minfo->marshaltype || minfo->marshaltyperef) {
1099 if (minfo->marshaltyperef) {
1100 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
1101 if (!is_ok (error)) {
1102 sigbuffer_free (&buf);
1105 str = type_get_fully_qualified_name (marshaltype);
1107 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
1108 if (!is_ok (error)) {
1109 sigbuffer_free (&buf);
1114 sigbuffer_add_value (&buf, len);
1115 sigbuffer_add_mem (&buf, str, len);
1118 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1119 sigbuffer_add_value (&buf, 0);
1121 if (minfo->mcookie) {
1122 str = mono_string_to_utf8_checked (minfo->mcookie, error);
1123 if (!is_ok (error)) {
1124 sigbuffer_free (&buf);
1128 sigbuffer_add_value (&buf, len);
1129 sigbuffer_add_mem (&buf, str, len);
1132 sigbuffer_add_value (&buf, 0);
1138 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1139 sigbuffer_free (&buf);
1144 mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
1146 MONO_REQ_GC_UNSAFE_MODE;
1151 guint32 nparams = 0;
1152 MonoReflectionMethodBuilder *mb = fb->get_method;
1153 MonoReflectionMethodBuilder *smb = fb->set_method;
1156 if (mb && mb->parameters)
1157 nparams = mono_array_length (mb->parameters);
1158 if (!mb && smb && smb->parameters)
1159 nparams = mono_array_length (smb->parameters) - 1;
1160 sigbuffer_init (&buf, 32);
1161 if (fb->call_conv & 0x20)
1162 sigbuffer_add_byte (&buf, 0x28);
1164 sigbuffer_add_byte (&buf, 0x08);
1165 sigbuffer_add_value (&buf, nparams);
1167 encode_reflection_type_raw (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
1170 for (i = 0; i < nparams; ++i) {
1171 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1172 encode_reflection_type_raw (assembly, pt, &buf, error);
1176 } else if (smb && smb->parameters) {
1177 /* the property type is the last param */
1178 encode_reflection_type_raw (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
1182 for (i = 0; i < nparams; ++i) {
1183 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1184 encode_reflection_type_raw (assembly, pt, &buf, error);
1189 encode_reflection_type_raw (assembly, (MonoReflectionType*)fb->type, &buf, error);
1194 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1195 sigbuffer_free (&buf);
1198 sigbuffer_free (&buf);
1203 #else /*DISABLE_REFLECTION_EMIT_SAVE*/
1205 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
1207 g_assert_not_reached ();
1212 mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
1214 g_assert_not_reached ();
1217 #endif /*DISABLE_REFLECTION_EMIT_SAVE*/
1219 #ifndef DISABLE_REFLECTION_EMIT
1221 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelperHandle sig, MonoError *error)
1224 return reflection_sighelper_get_signature_local (sig, error);
1228 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelperHandle sig, MonoError *error)
1231 return reflection_sighelper_get_signature_field (sig, error);
1233 #else /* DISABLE_REFLECTION_EMIT */
1235 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelperHandle sig, MonoError *error)
1238 g_assert_not_reached ();
1239 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
1243 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelperHandle sig, MonoError *error)
1246 g_assert_not_reached ();
1247 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
1250 #endif /* DISABLE_REFLECTION_EMIT */