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 alloc_table (MonoDynamicTable *table, guint nrows)
42 mono_dynimage_alloc_table (table, nrows);
46 sigbuffer_init (SigBuffer *buf, int size)
48 MONO_REQ_GC_NEUTRAL_MODE;
50 buf->buf = (char *)g_malloc (size);
52 buf->end = buf->buf + size;
56 sigbuffer_make_room (SigBuffer *buf, int size)
58 MONO_REQ_GC_NEUTRAL_MODE;
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;
66 buf->end = buf->buf + new_size;
71 sigbuffer_add_value (SigBuffer *buf, guint32 val)
73 MONO_REQ_GC_NEUTRAL_MODE;
75 sigbuffer_make_room (buf, 6);
76 mono_metadata_encode_value (val, buf->p, &buf->p);
80 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
82 MONO_REQ_GC_NEUTRAL_MODE;
84 sigbuffer_make_room (buf, 1);
90 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
92 MONO_REQ_GC_NEUTRAL_MODE;
94 sigbuffer_make_room (buf, size);
95 memcpy (buf->p, p, size);
100 sigbuffer_free (SigBuffer *buf)
102 MONO_REQ_GC_NEUTRAL_MODE;
108 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
110 MONO_REQ_GC_NEUTRAL_MODE;
114 guint32 size = buf->p - buf->buf;
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);
123 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
125 MONO_REQ_GC_NEUTRAL_MODE;
128 MonoGenericInst *class_inst;
133 class_inst = gclass->context.class_inst;
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));
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);
147 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
149 MONO_REQ_GC_NEUTRAL_MODE;
152 g_assert_not_reached ();
157 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
161 case MONO_TYPE_BOOLEAN:
175 case MONO_TYPE_STRING:
176 case MONO_TYPE_OBJECT:
177 case MONO_TYPE_TYPEDBYREF:
178 sigbuffer_add_value (buf, type->type);
181 sigbuffer_add_value (buf, type->type);
182 encode_type (assembly, type->data.type, buf);
184 case MONO_TYPE_SZARRAY:
185 sigbuffer_add_value (buf, type->type);
186 encode_type (assembly, &type->data.klass->byval_arg, buf);
188 case MONO_TYPE_VALUETYPE:
189 case MONO_TYPE_CLASS: {
190 MonoClass *k = mono_class_from_mono_type (type);
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);
197 * Make sure we use the correct type.
199 sigbuffer_add_value (buf, k->byval_arg.type);
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.
205 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
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);
216 case MONO_TYPE_GENERICINST:
217 encode_generic_class (assembly, type->data.generic_class, buf);
221 sigbuffer_add_value (buf, type->type);
222 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
225 g_error ("need to encode type %x", type->type);
230 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf, MonoError *error)
232 MONO_REQ_GC_UNSAFE_MODE;
234 mono_error_init (error);
237 sigbuffer_add_value (buf, MONO_TYPE_VOID);
241 MonoType *t = mono_reflection_type_get_handle (type, error);
242 return_if_nok (error);
243 encode_type (assembly, t, buf);
247 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf, MonoError *error)
249 MONO_REQ_GC_UNSAFE_MODE;
253 mono_error_init (error);
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));
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));
273 #ifndef DISABLE_REFLECTION_EMIT
275 mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
277 MONO_REQ_GC_UNSAFE_MODE;
281 guint32 nparams = sig->param_count;
287 sigbuffer_init (&buf, 32);
289 * FIXME: vararg, explicit_this, differenc call_conv values...
291 idx = sig->call_convention;
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);
306 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
307 sigbuffer_free (&buf);
310 #else /* DISABLE_REFLECTION_EMIT */
312 mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
314 g_assert_not_reached ();
320 mono_dynimage_encode_method_builder_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
322 MONO_REQ_GC_UNSAFE_MODE;
324 mono_error_init (error);
327 * FIXME: reuse code from method_encode_signature().
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;
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 */
344 idx |= 0x10; /* generic */
345 sigbuffer_add_byte (&buf, idx);
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);
352 encode_reflection_type (assembly, mb->rtype, &buf, error);
355 for (i = 0; i < nparams; ++i) {
356 MonoArray *modreq = NULL;
357 MonoArray *modopt = NULL;
358 MonoReflectionType *pt;
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);
367 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
368 encode_reflection_type (assembly, pt, &buf, error);
373 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
374 for (i = 0; i < notypes; ++i) {
375 MonoReflectionType *pt;
377 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
378 encode_reflection_type (assembly, pt, &buf, error);
383 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
385 sigbuffer_free (&buf);
390 mono_dynimage_encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
392 MONO_REQ_GC_UNSAFE_MODE;
394 mono_error_init (error);
396 MonoDynamicTable *table;
398 guint32 idx, sig_idx;
399 guint nl = mono_array_length (ilgen->locals);
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);
410 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
412 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf, error);
413 if (!is_ok (error)) {
414 sigbuffer_free (&buf);
418 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
419 sigbuffer_free (&buf);
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)));
427 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
428 idx = table->next_idx ++;
430 alloc_table (table, table->rows);
431 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
433 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
435 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
443 mono_dynimage_encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
445 MONO_REQ_GC_UNSAFE_MODE;
451 guint32 idx = 0, len = 0, dummy = 0;
453 buf = (char *)g_malloc (64);
455 *ret_type = MONO_TYPE_CLASS;
457 box_val = (char*)&dummy;
459 box_val = ((char*)val) + sizeof (MonoObject);
460 *ret_type = val->vtable->klass->byval_arg.type;
464 case MONO_TYPE_BOOLEAN:
486 case MONO_TYPE_VALUETYPE: {
487 MonoClass *klass = val->vtable->klass;
489 if (klass->enumtype) {
490 *ret_type = mono_class_enum_basetype (klass)->type;
492 } else if (mono_is_corlib_image (klass->image) && strcmp (klass->name_space, "System") == 0 && strcmp (klass->name, "DateTime") == 0) {
495 g_error ("we can't encode valuetypes, we should have never reached this line");
498 case MONO_TYPE_CLASS:
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
507 char *swapped = g_malloc (2 * mono_string_length (str));
508 const char *p = (const char*)mono_string_chars (str);
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);
515 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
521 case MONO_TYPE_GENERICINST:
522 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
525 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
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);
535 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
544 mono_dynimage_encode_field_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
546 MONO_REQ_GC_UNSAFE_MODE;
548 mono_error_init (error);
552 guint32 typespec = 0;
556 mono_reflection_init_type_builder_generics (fb->type, error);
557 return_val_if_nok (error, 0);
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);
563 sigbuffer_init (&buf, 32);
565 sigbuffer_add_value (&buf, 0x06);
566 encode_custom_modifiers (assembly, fb->modreq, fb->modopt, &buf, error);
569 /* encode custom attributes before the type */
571 if (klass->generic_container)
572 typespec = create_typespec (assembly, type);
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);
579 encode_type (assembly, type, &buf);
581 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
582 sigbuffer_free (&buf);
585 sigbuffer_free (&buf);
589 #ifndef DISABLE_REFLECTION_EMIT
590 /*field_image is the image to which the eventual custom mods have been encoded against*/
592 mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
594 MONO_REQ_GC_NEUTRAL_MODE;
597 guint32 idx, i, token;
602 sigbuffer_init (&buf, 32);
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) {
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 */
613 token = mono_image_typedef_or_ref (assembly, &klass->byval_arg);
615 token = type->modifiers [i].token;
618 if (type->modifiers [i].required)
619 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
621 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
623 sigbuffer_add_value (&buf, token);
626 encode_type (assembly, type, &buf);
627 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
628 sigbuffer_free (&buf);
631 #else /* DISABLE_REFLECTION_EMIT */
633 mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
635 g_assert_not_reached ();
638 #endif /* DISABLE_REFLECTION_EMIT */
641 create_typespec (MonoDynamicImage *assembly, MonoType *type)
643 MONO_REQ_GC_NEUTRAL_MODE;
645 MonoDynamicTable *table;
650 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
653 sigbuffer_init (&buf, 32);
654 switch (type->type) {
655 case MONO_TYPE_FNPTR:
657 case MONO_TYPE_SZARRAY:
658 case MONO_TYPE_ARRAY:
661 case MONO_TYPE_GENERICINST:
662 encode_type (assembly, type, &buf);
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);
671 encode_type (assembly, type, &buf);
675 sigbuffer_free (&buf);
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;
686 sigbuffer_free (&buf);
688 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
689 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
695 mono_dynimage_encode_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
697 MONO_REQ_GC_UNSAFE_MODE;
699 MonoDynamicTable *table;
701 guint32 token, scope, enclosing;
704 /* if the type requires a typespec, we must try that first*/
705 if (try_typespec && (token = create_typespec (assembly, type)))
707 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
710 klass = mono_class_from_mono_type (type);
712 klass = mono_class_from_mono_type (type);
715 * If it's in the same module and not a generic type parameter:
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));
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;
731 scope = mono_reflection_resolution_scope_from_image (assembly, klass->image);
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);
741 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
742 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
744 mono_dynamic_image_register_token (assembly, token, (MonoObject *)mono_class_get_ref_info (klass));
749 * Despite the name, we handle also TypeSpec (with the above helper).
752 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
754 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
758 mono_dynimage_encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
762 guint32 nparams = mono_array_length (mb->generic_params);
768 sigbuffer_init (&buf, 32);
770 sigbuffer_add_value (&buf, 0xa);
771 sigbuffer_add_value (&buf, nparams);
773 for (i = 0; i < nparams; i++) {
774 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
775 sigbuffer_add_value (&buf, i);
778 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
779 sigbuffer_free (&buf);
784 mono_dynimage_encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
788 guint32 nparams = context->method_inst->type_argc;
794 sigbuffer_init (&buf, 32);
796 * FIXME: vararg, explicit_this, differenc call_conv values...
798 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
799 sigbuffer_add_value (&buf, nparams);
801 for (i = 0; i < nparams; i++)
802 encode_type (assembly, context->method_inst->type_argv [i], &buf);
804 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
805 sigbuffer_free (&buf);
809 #ifndef DISABLE_REFLECTION_EMIT
811 mono_dynimage_encode_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
813 MonoDynamicTable *table;
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.
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));
832 sigbuffer_init (&buf, 32);
834 g_assert (tb->generic_params);
835 klass = mono_class_from_mono_type (type);
837 if (tb->generic_container) {
838 if (!mono_reflection_create_generic_class (tb, error))
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));
847 count = mono_array_length (tb->generic_params);
848 sigbuffer_add_value (&buf, count);
849 for (i = 0; i < count; i++) {
850 MonoReflectionGenericParam *gparam;
852 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
853 MonoType *gparam_type = mono_reflection_type_get_handle ((MonoReflectionType*)gparam, error);
857 encode_type (assembly, gparam_type, &buf);
860 table = &assembly->tables [MONO_TABLE_TYPESPEC];
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;
868 sigbuffer_free (&buf);
870 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
871 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
875 sigbuffer_free (&buf);
878 #else /*DISABLE_REFLECTION_EMIT*/
880 mono_dynimage_encode_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb, MonoError *error)
882 g_assert_not_reached ();
885 #endif /*DISABLE_REFLECTION_EMIT*/
887 #ifndef DISABLE_REFLECTION_EMIT
889 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
895 mono_error_init (error);
900 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
901 g_assert (helper->type == 2);
903 if (helper->arguments)
904 nargs = mono_array_length (helper->arguments);
908 sigbuffer_init (&buf, 32);
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;
918 if (helper->call_conv == 0) { /* Unmanaged */
919 idx = helper->unmanaged_call_conv - 1;
922 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
923 if (helper->call_conv & 0x02) /* varargs */
927 sigbuffer_add_byte (&buf, idx);
928 sigbuffer_add_value (&buf, nargs);
929 encode_reflection_type (assembly, helper->return_type, &buf, error);
932 for (i = 0; i < nargs; ++i) {
933 MonoArray *modreqs = NULL;
934 MonoArray *modopts = NULL;
935 MonoReflectionType *pt;
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);
942 encode_custom_modifiers (assembly, modreqs, modopts, &buf, error);
945 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
946 encode_reflection_type (assembly, pt, &buf, error);
950 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
951 sigbuffer_free (&buf);
955 sigbuffer_free (&buf);
958 #else /* DISABLE_REFLECTION_EMIT */
960 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper, MonoError *error)
962 g_assert_not_reached ();
965 #endif /* DISABLE_REFLECTION_EMIT */
968 reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig, MonoError *error)
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;
977 mono_error_init (error);
979 mono_reflection_check_array_for_usertypes (sig->arguments, error);
980 return_val_if_nok (error, NULL);
982 sigbuffer_init (&buf, 32);
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;
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);
1001 sigbuffer_free (&buf);
1006 reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig, MonoError *error)
1008 MonoDynamicImage *assembly = sig->module->dynamic_image;
1009 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
1014 mono_error_init (error);
1016 mono_reflection_check_array_for_usertypes (sig->arguments, error);
1017 return_val_if_nok (error, NULL);
1019 sigbuffer_init (&buf, 32);
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);
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);
1037 sigbuffer_free (&buf);
1042 type_get_fully_qualified_name (MonoType *type)
1044 MONO_REQ_GC_NEUTRAL_MODE;
1046 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1049 #ifndef DISABLE_REFLECTION_EMIT_SAVE
1051 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
1053 MONO_REQ_GC_UNSAFE_MODE;
1055 mono_error_init (error);
1061 sigbuffer_init (&buf, 32);
1063 sigbuffer_add_value (&buf, minfo->type);
1065 switch (minfo->type) {
1066 case MONO_NATIVE_BYVALTSTR:
1067 case MONO_NATIVE_BYVALARRAY:
1068 sigbuffer_add_value (&buf, minfo->count);
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);
1077 /* LAMESPEC: ElemMult is undocumented */
1078 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1082 case MONO_NATIVE_SAFEARRAY:
1084 sigbuffer_add_value (&buf, minfo->eltype);
1086 case MONO_NATIVE_CUSTOM:
1088 str = mono_string_to_utf8_checked (minfo->guid, error);
1089 if (!is_ok (error)) {
1090 sigbuffer_free (&buf);
1094 sigbuffer_add_value (&buf, len);
1095 sigbuffer_add_mem (&buf, str, len);
1098 sigbuffer_add_value (&buf, 0);
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);
1110 str = type_get_fully_qualified_name (marshaltype);
1112 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
1113 if (!is_ok (error)) {
1114 sigbuffer_free (&buf);
1119 sigbuffer_add_value (&buf, len);
1120 sigbuffer_add_mem (&buf, str, len);
1123 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1124 sigbuffer_add_value (&buf, 0);
1126 if (minfo->mcookie) {
1127 str = mono_string_to_utf8_checked (minfo->mcookie, error);
1128 if (!is_ok (error)) {
1129 sigbuffer_free (&buf);
1133 sigbuffer_add_value (&buf, len);
1134 sigbuffer_add_mem (&buf, str, len);
1137 sigbuffer_add_value (&buf, 0);
1143 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1144 sigbuffer_free (&buf);
1149 mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
1151 MONO_REQ_GC_UNSAFE_MODE;
1153 mono_error_init (error);
1156 guint32 nparams = 0;
1157 MonoReflectionMethodBuilder *mb = fb->get_method;
1158 MonoReflectionMethodBuilder *smb = fb->set_method;
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);
1169 sigbuffer_add_byte (&buf, 0x08);
1170 sigbuffer_add_value (&buf, nparams);
1172 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
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);
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);
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);
1194 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf, error);
1199 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1200 sigbuffer_free (&buf);
1203 sigbuffer_free (&buf);
1208 #else /*DISABLE_REFLECTION_EMIT_SAVE*/
1210 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
1212 g_assert_not_reached ();
1217 mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
1219 g_assert_not_reached ();
1222 #endif /*DISABLE_REFLECTION_EMIT_SAVE*/
1224 #ifndef DISABLE_REFLECTION_EMIT
1226 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
1229 MonoArray *result = reflection_sighelper_get_signature_local (sig, &error);
1230 mono_error_set_pending_exception (&error);
1235 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
1238 MonoArray *result = reflection_sighelper_get_signature_field (sig, &error);
1239 mono_error_set_pending_exception (&error);
1242 #else /* DISABLE_REFLECTION_EMIT */
1244 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelper *sig)
1246 g_assert_not_reached ();
1251 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelper *sig)
1253 g_assert_not_reached ();
1257 #endif /* DISABLE_REFLECTION_EMIT */