[sdks] Fixes llvm branch name (#8926)
[mono-project.git] / mono / metadata / sre-encode.c
blob420e611c49d03fbfa9b2dd2f4baf613109de02de
1 /**
2 * \file
3 * Routines for encoding SRE builders into a
4 * MonoDynamicImage and generating tokens.
5 *
6 *
7 * Author:
8 * Paolo Molaro (lupus@ximian.com)
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.
17 #include <config.h>
18 #include <glib.h>
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"
29 typedef struct {
30 char *p;
31 char *buf;
32 char *end;
33 } SigBuffer;
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);
39 static guint32
40 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
42 return mono_dynstream_add_data (stream, data, len);
45 static void
46 alloc_table (MonoDynamicTable *table, guint nrows)
48 mono_dynimage_alloc_table (table, nrows);
51 static void
52 sigbuffer_init (SigBuffer *buf, int size)
54 MONO_REQ_GC_NEUTRAL_MODE;
56 buf->buf = (char *)g_malloc (size);
57 buf->p = buf->buf;
58 buf->end = buf->buf + size;
61 static void
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;
70 buf->buf = p;
71 buf->p = p + size;
72 buf->end = buf->buf + new_size;
76 static void
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);
85 static void
86 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
88 MONO_REQ_GC_NEUTRAL_MODE;
90 sigbuffer_make_room (buf, 1);
91 buf->p [0] = val;
92 buf->p++;
95 static void
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);
102 buf->p += size;
105 static void
106 sigbuffer_free (SigBuffer *buf)
108 MONO_REQ_GC_NEUTRAL_MODE;
110 g_free (buf->buf);
113 static guint32
114 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
116 MONO_REQ_GC_NEUTRAL_MODE;
118 char blob_size [8];
119 char *b = blob_size;
120 guint32 size = buf->p - buf->buf;
121 /* store length */
122 g_assert (size <= (buf->end - buf->buf));
123 mono_metadata_encode_value (size, b, &b);
124 return mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
128 static void
129 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
131 MONO_REQ_GC_NEUTRAL_MODE;
133 int i;
134 MonoGenericInst *class_inst;
135 MonoClass *klass;
137 g_assert (gclass);
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, m_class_get_byval_arg (klass)->type);
144 sigbuffer_add_value (buf, mono_dynimage_encode_typedef_or_ref_full (assembly, m_class_get_byval_arg (klass), 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);
152 static void
153 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
155 MONO_REQ_GC_NEUTRAL_MODE;
157 if (!type) {
158 g_assert_not_reached ();
159 return;
162 if (type->byref)
163 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
165 switch (type->type){
166 case MONO_TYPE_VOID:
167 case MONO_TYPE_BOOLEAN:
168 case MONO_TYPE_CHAR:
169 case MONO_TYPE_I1:
170 case MONO_TYPE_U1:
171 case MONO_TYPE_I2:
172 case MONO_TYPE_U2:
173 case MONO_TYPE_I4:
174 case MONO_TYPE_U4:
175 case MONO_TYPE_I8:
176 case MONO_TYPE_U8:
177 case MONO_TYPE_R4:
178 case MONO_TYPE_R8:
179 case MONO_TYPE_I:
180 case MONO_TYPE_U:
181 case MONO_TYPE_STRING:
182 case MONO_TYPE_OBJECT:
183 case MONO_TYPE_TYPEDBYREF:
184 sigbuffer_add_value (buf, type->type);
185 break;
186 case MONO_TYPE_PTR:
187 sigbuffer_add_value (buf, type->type);
188 encode_type (assembly, type->data.type, buf);
189 break;
190 case MONO_TYPE_SZARRAY:
191 sigbuffer_add_value (buf, type->type);
192 encode_type (assembly, m_class_get_byval_arg (type->data.klass), buf);
193 break;
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);
201 } else {
203 * Make sure we use the correct type.
205 sigbuffer_add_value (buf, m_class_get_byval_arg (k)->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, m_class_get_byval_arg (k)));
213 break;
215 case MONO_TYPE_ARRAY:
216 sigbuffer_add_value (buf, type->type);
217 encode_type (assembly, m_class_get_byval_arg (type->data.array->eklass), buf);
218 sigbuffer_add_value (buf, type->data.array->rank);
219 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
220 sigbuffer_add_value (buf, 0);
221 break;
222 case MONO_TYPE_GENERICINST:
223 encode_generic_class (assembly, type->data.generic_class, buf);
224 break;
225 case MONO_TYPE_VAR:
226 case MONO_TYPE_MVAR:
227 sigbuffer_add_value (buf, type->type);
228 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
229 break;
230 default:
231 g_error ("need to encode type %x", type->type);
235 static void
236 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionTypeHandle type, SigBuffer *buf, MonoError *error)
238 MONO_REQ_GC_UNSAFE_MODE;
240 error_init (error);
242 if (!type) {
243 sigbuffer_add_value (buf, MONO_TYPE_VOID);
244 return;
247 MonoType *t = mono_reflection_type_handle_mono_type (type, error);
248 return_if_nok (error);
249 encode_type (assembly, t, buf);
252 static void
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 */
256 error_init (error);
257 MONO_HANDLE_DCL (MonoReflectionType, type);
258 encode_reflection_type (assembly, type, buf, error);
259 HANDLE_FUNCTION_RETURN ();
263 static void
264 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArrayHandle modreq, MonoArrayHandle modopt, SigBuffer *buf, MonoError *error)
266 HANDLE_FUNCTION_ENTER ();
267 MONO_REQ_GC_UNSAFE_MODE;
269 int i;
271 error_init (error);
273 if (!MONO_HANDLE_IS_NULL (modreq)) {
274 for (i = 0; i < mono_array_handle_length (modreq); ++i) {
275 MonoType *mod = mono_type_array_get_and_resolve (modreq, i, error);
276 goto_if_nok (error, leave);
277 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
278 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
281 if (!MONO_HANDLE_IS_NULL (modopt)) {
282 for (i = 0; i < mono_array_handle_length (modopt); ++i) {
283 MonoType *mod = mono_type_array_get_and_resolve (modopt, i, error);
284 goto_if_nok (error, leave);
285 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
286 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
289 leave:
290 HANDLE_FUNCTION_RETURN ();
293 static void
294 encode_custom_modifiers_raw (MonoDynamicImage *assembly, MonoArray *modreq_raw, MonoArray *modopt_raw, SigBuffer *buf, MonoError *error)
296 HANDLE_FUNCTION_ENTER (); /* FIXME callers of encode_custom_modifiers_raw should use handles */
297 error_init (error);
298 MONO_HANDLE_DCL (MonoArray, modreq);
299 MONO_HANDLE_DCL (MonoArray, modopt);
300 encode_custom_modifiers (assembly, modreq, modopt, buf, error);
301 HANDLE_FUNCTION_RETURN ();
305 #ifndef DISABLE_REFLECTION_EMIT
306 guint32
307 mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
309 MONO_REQ_GC_UNSAFE_MODE;
311 SigBuffer buf;
312 int i;
313 guint32 nparams = sig->param_count;
314 guint32 idx;
316 if (!assembly->save)
317 return 0;
319 sigbuffer_init (&buf, 32);
321 * FIXME: vararg, explicit_this, differenc call_conv values...
323 idx = sig->call_convention;
324 if (sig->hasthis)
325 idx |= 0x20; /* hasthis */
326 if (sig->generic_param_count)
327 idx |= 0x10; /* generic */
328 sigbuffer_add_byte (&buf, idx);
329 if (sig->generic_param_count)
330 sigbuffer_add_value (&buf, sig->generic_param_count);
331 sigbuffer_add_value (&buf, nparams);
332 encode_type (assembly, sig->ret, &buf);
333 for (i = 0; i < nparams; ++i) {
334 if (i == sig->sentinelpos)
335 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
336 encode_type (assembly, sig->params [i], &buf);
338 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
339 sigbuffer_free (&buf);
340 return idx;
342 #else /* DISABLE_REFLECTION_EMIT */
343 guint32
344 mono_dynimage_encode_method_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
346 g_assert_not_reached ();
347 return 0;
349 #endif
351 guint32
352 mono_dynimage_encode_method_builder_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb, MonoError *error)
354 MONO_REQ_GC_UNSAFE_MODE;
356 error_init (error);
359 * FIXME: reuse code from method_encode_signature().
361 SigBuffer buf;
362 int i;
363 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
364 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
365 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
366 guint32 idx;
368 sigbuffer_init (&buf, 32);
369 /* LAMESPEC: all the call conv spec is foobared */
370 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
371 if (mb->call_conv & 2)
372 idx |= 0x5; /* vararg */
373 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
374 idx |= 0x20; /* hasthis */
375 if (ngparams)
376 idx |= 0x10; /* generic */
377 sigbuffer_add_byte (&buf, idx);
378 if (ngparams)
379 sigbuffer_add_value (&buf, ngparams);
380 sigbuffer_add_value (&buf, nparams + notypes);
381 encode_custom_modifiers_raw (assembly, mb->return_modreq, mb->return_modopt, &buf, error);
382 goto_if_nok (error, leave);
383 encode_reflection_type_raw (assembly, mb->rtype, &buf, error);
384 goto_if_nok (error, leave);
385 for (i = 0; i < nparams; ++i) {
386 MonoArray *modreq = NULL;
387 MonoArray *modopt = NULL;
388 MonoReflectionType *pt;
390 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
391 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
392 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
393 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
394 encode_custom_modifiers_raw (assembly, modreq, modopt, &buf, error);
395 goto_if_nok (error, leave);
396 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
397 encode_reflection_type_raw (assembly, pt, &buf, error);
398 goto_if_nok (error, leave);
400 if (notypes)
401 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
402 for (i = 0; i < notypes; ++i) {
403 MonoReflectionType *pt;
405 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
406 encode_reflection_type_raw (assembly, pt, &buf, error);
407 goto_if_nok (error, leave);
410 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
411 leave:
412 sigbuffer_free (&buf);
413 return idx;
416 guint32
417 mono_dynimage_encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, MonoError *error)
419 MONO_REQ_GC_UNSAFE_MODE;
421 error_init (error);
423 MonoDynamicTable *table;
424 guint32 *values;
425 guint32 idx, sig_idx;
426 guint nl = mono_array_length (ilgen->locals);
427 SigBuffer buf;
428 int i;
430 sigbuffer_init (&buf, 32);
431 sigbuffer_add_value (&buf, 0x07);
432 sigbuffer_add_value (&buf, nl);
433 for (i = 0; i < nl; ++i) {
434 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
436 if (lb->is_pinned)
437 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
439 encode_reflection_type_raw (assembly, (MonoReflectionType*)lb->type, &buf, error);
440 if (!is_ok (error)) {
441 sigbuffer_free (&buf);
442 return 0;
445 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
446 sigbuffer_free (&buf);
448 if (assembly->standalonesig_cache == NULL)
449 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
450 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
451 if (idx)
452 return idx;
454 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
455 idx = table->next_idx ++;
456 table->rows ++;
457 alloc_table (table, table->rows);
458 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
460 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
462 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
464 return idx;
469 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
470 * dest may be misaligned.
472 static void
473 swap_with_size (char *dest, const char* val, int len, int nelem) {
474 MONO_REQ_GC_NEUTRAL_MODE;
475 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
476 int elem;
478 for (elem = 0; elem < nelem; ++elem) {
479 switch (len) {
480 case 1:
481 *dest = *val;
482 break;
483 case 2:
484 dest [0] = val [1];
485 dest [1] = val [0];
486 break;
487 case 4:
488 dest [0] = val [3];
489 dest [1] = val [2];
490 dest [2] = val [1];
491 dest [3] = val [0];
492 break;
493 case 8:
494 dest [0] = val [7];
495 dest [1] = val [6];
496 dest [2] = val [5];
497 dest [3] = val [4];
498 dest [4] = val [3];
499 dest [5] = val [2];
500 dest [6] = val [1];
501 dest [7] = val [0];
502 break;
503 default:
504 g_assert_not_reached ();
506 dest += len;
507 val += len;
509 #else
510 memcpy (dest, val, len * nelem);
511 #endif
515 guint32
516 mono_dynimage_encode_constant (MonoDynamicImage *assembly, MonoObject *val, MonoTypeEnum *ret_type)
518 MONO_REQ_GC_UNSAFE_MODE;
520 char blob_size [64];
521 char *b = blob_size;
522 char *box_val;
523 char* buf;
524 guint32 idx = 0, len = 0, dummy = 0;
526 buf = (char *)g_malloc (64);
527 if (!val) {
528 *ret_type = MONO_TYPE_CLASS;
529 len = 4;
530 box_val = (char*)&dummy;
531 } else {
532 box_val = ((char*)val) + sizeof (MonoObject);
533 *ret_type = m_class_get_byval_arg (val->vtable->klass)->type;
535 handle_enum:
536 switch (*ret_type) {
537 case MONO_TYPE_BOOLEAN:
538 case MONO_TYPE_U1:
539 case MONO_TYPE_I1:
540 len = 1;
541 break;
542 case MONO_TYPE_CHAR:
543 case MONO_TYPE_U2:
544 case MONO_TYPE_I2:
545 len = 2;
546 break;
547 case MONO_TYPE_U4:
548 case MONO_TYPE_I4:
549 case MONO_TYPE_R4:
550 len = 4;
551 break;
552 case MONO_TYPE_U8:
553 case MONO_TYPE_I8:
554 len = 8;
555 break;
556 case MONO_TYPE_R8:
557 len = 8;
558 break;
559 case MONO_TYPE_VALUETYPE: {
560 MonoClass *klass = val->vtable->klass;
562 if (m_class_is_enumtype (klass)) {
563 *ret_type = mono_class_enum_basetype (klass)->type;
564 goto handle_enum;
565 } else if (mono_is_corlib_image (m_class_get_image (klass)) && strcmp (m_class_get_name_space (klass), "System") == 0 && strcmp (m_class_get_name (klass), "DateTime") == 0) {
566 len = 8;
567 } else
568 g_error ("we can't encode valuetypes, we should have never reached this line");
569 break;
571 case MONO_TYPE_CLASS:
572 break;
573 case MONO_TYPE_STRING: {
574 MonoString *str = (MonoString*)val;
575 /* there is no signature */
576 len = str->length * 2;
577 mono_metadata_encode_value (len, b, &b);
578 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
580 char *swapped = g_malloc (2 * mono_string_length (str));
581 const char *p = (const char*)mono_string_chars (str);
583 swap_with_size (swapped, p, 2, mono_string_length (str));
584 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
585 g_free (swapped);
587 #else
588 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
589 #endif
591 g_free (buf);
592 return idx;
594 case MONO_TYPE_GENERICINST:
595 *ret_type = m_class_get_byval_arg (mono_class_get_generic_class (val->vtable->klass)->container_class)->type;
596 goto handle_enum;
597 default:
598 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
601 /* there is no signature */
602 mono_metadata_encode_value (len, b, &b);
603 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
604 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
605 swap_with_size (blob_size, box_val, len, 1);
606 mono_image_add_stream_data (&assembly->blob, blob_size, len);
607 #else
608 idx = mono_dynamic_image_add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
609 #endif
611 g_free (buf);
612 return idx;
615 guint32
616 mono_dynimage_encode_field_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb, MonoError *error)
618 MONO_REQ_GC_UNSAFE_MODE;
620 error_init (error);
622 SigBuffer buf;
623 guint32 idx;
624 guint32 typespec = 0;
625 MonoType *type;
626 MonoClass *klass;
628 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
629 return_val_if_nok (error, 0);
630 klass = mono_class_from_mono_type (type);
632 sigbuffer_init (&buf, 32);
634 sigbuffer_add_value (&buf, 0x06);
635 encode_custom_modifiers_raw (assembly, fb->modreq, fb->modopt, &buf, error);
636 goto_if_nok (error, fail);
637 /* encode custom attributes before the type */
639 if (mono_class_is_gtd (klass))
640 typespec = create_typespec (assembly, type);
642 if (typespec) {
643 MonoGenericClass *gclass;
644 gclass = mono_metadata_lookup_generic_class (klass, mono_class_get_generic_container (klass)->context.class_inst, TRUE);
645 encode_generic_class (assembly, gclass, &buf);
646 } else {
647 encode_type (assembly, type, &buf);
649 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
650 sigbuffer_free (&buf);
651 return idx;
652 fail:
653 sigbuffer_free (&buf);
654 return 0;
657 #ifndef DISABLE_REFLECTION_EMIT
658 /*field_image is the image to which the eventual custom mods have been encoded against*/
659 guint32
660 mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
662 MONO_REQ_GC_NEUTRAL_MODE;
664 SigBuffer buf;
665 guint32 idx, i, token;
667 if (!assembly->save)
668 return 0;
670 sigbuffer_init (&buf, 32);
672 sigbuffer_add_value (&buf, 0x06);
673 /* encode custom attributes before the type */
674 if (type->has_cmods) {
675 MonoCustomModContainer *cmods = mono_type_get_cmods (type);
676 for (i = 0; i < cmods->count; ++i) {
677 if (field_image) {
678 ERROR_DECL (error);
679 MonoClass *klass = mono_class_get_checked (field_image, cmods->modifiers [i].token, error);
680 g_assert (mono_error_ok (error)); /* FIXME don't swallow the error */
682 token = mono_image_typedef_or_ref (assembly, m_class_get_byval_arg (klass));
683 } else {
684 token = cmods->modifiers [i].token;
687 if (cmods->modifiers [i].required)
688 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
689 else
690 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
692 sigbuffer_add_value (&buf, token);
695 encode_type (assembly, type, &buf);
696 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
697 sigbuffer_free (&buf);
698 return idx;
700 #else /* DISABLE_REFLECTION_EMIT */
701 guint32
702 mono_dynimage_encode_fieldref_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
704 g_assert_not_reached ();
705 return 0;
707 #endif /* DISABLE_REFLECTION_EMIT */
709 static guint32
710 create_typespec (MonoDynamicImage *assembly, MonoType *type)
712 MONO_REQ_GC_NEUTRAL_MODE;
714 MonoDynamicTable *table;
715 guint32 *values;
716 guint32 token;
717 SigBuffer buf;
719 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
720 return token;
722 sigbuffer_init (&buf, 32);
723 switch (type->type) {
724 case MONO_TYPE_FNPTR:
725 case MONO_TYPE_PTR:
726 case MONO_TYPE_SZARRAY:
727 case MONO_TYPE_ARRAY:
728 case MONO_TYPE_VAR:
729 case MONO_TYPE_MVAR:
730 case MONO_TYPE_GENERICINST:
731 encode_type (assembly, type, &buf);
732 break;
733 case MONO_TYPE_CLASS:
734 case MONO_TYPE_VALUETYPE: {
735 MonoClass *k = mono_class_from_mono_type (type);
736 if (!k || !mono_class_is_gtd (k)) {
737 sigbuffer_free (&buf);
738 return 0;
740 encode_type (assembly, type, &buf);
741 break;
743 default:
744 sigbuffer_free (&buf);
745 return 0;
748 table = &assembly->tables [MONO_TABLE_TYPESPEC];
749 if (assembly->save) {
750 token = sigbuffer_add_to_blob_cached (assembly, &buf);
751 alloc_table (table, table->rows + 1);
752 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
753 values [MONO_TYPESPEC_SIGNATURE] = token;
755 sigbuffer_free (&buf);
757 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
758 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
759 table->next_idx ++;
760 return token;
763 guint32
764 mono_dynimage_encode_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
766 MONO_REQ_GC_UNSAFE_MODE;
767 HANDLE_FUNCTION_ENTER ();
769 MonoDynamicTable *table;
770 guint32 *values;
771 guint32 token, scope, enclosing;
772 MonoClass *klass;
774 /* if the type requires a typespec, we must try that first*/
775 if (try_typespec && (token = create_typespec (assembly, type)))
776 goto leave;
777 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
778 if (token)
779 goto leave;
780 klass = mono_class_from_mono_type (type);
782 MonoReflectionTypeBuilderHandle tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, mono_class_get_ref_info (klass));
784 * If it's in the same module and not a generic type parameter:
786 if ((m_class_get_image (klass) == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
787 (type->type != MONO_TYPE_MVAR)) {
788 token = MONO_TYPEDEFORREF_TYPEDEF | (MONO_HANDLE_GETVAL (tb, table_idx) << MONO_TYPEDEFORREF_BITS);
789 /* This function is called multiple times from sre and sre-save, so same object is okay */
790 mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, tb), MONO_DYN_IMAGE_TOK_SAME_OK);
791 goto leave;
794 if (m_class_get_nested_in (klass)) {
795 enclosing = mono_dynimage_encode_typedef_or_ref_full (assembly, m_class_get_byval_arg (m_class_get_nested_in (klass)), FALSE);
796 /* get the typeref idx of the enclosing type */
797 enclosing >>= MONO_TYPEDEFORREF_BITS;
798 scope = (enclosing << MONO_RESOLUTION_SCOPE_BITS) | MONO_RESOLUTION_SCOPE_TYPEREF;
799 } else {
800 scope = mono_reflection_resolution_scope_from_image (assembly, m_class_get_image (klass));
802 table = &assembly->tables [MONO_TABLE_TYPEREF];
803 if (assembly->save) {
804 alloc_table (table, table->rows + 1);
805 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
806 values [MONO_TYPEREF_SCOPE] = scope;
807 values [MONO_TYPEREF_NAME] = mono_dynstream_insert_string (&assembly->sheap, m_class_get_name (klass));
808 values [MONO_TYPEREF_NAMESPACE] = mono_dynstream_insert_string (&assembly->sheap, m_class_get_name_space (klass));
810 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
811 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
812 table->next_idx ++;
815 if (!MONO_HANDLE_IS_NULL (tb)) {
816 /* This function is called multiple times from sre and sre-save, so same object is okay */
817 mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, tb), MONO_DYN_IMAGE_TOK_SAME_OK);
820 leave:
821 HANDLE_FUNCTION_RETURN_VAL (token);
825 * Despite the name, we handle also TypeSpec (with the above helper).
827 static guint32
828 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
830 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
833 guint32
834 mono_dynimage_encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
836 SigBuffer buf;
837 int i;
838 guint32 nparams = context->method_inst->type_argc;
839 guint32 idx;
841 if (!assembly->save)
842 return 0;
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);
856 return idx;
859 #ifndef DISABLE_REFLECTION_EMIT
860 static gboolean
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();
864 error_init (error);
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);
874 goto_if_nok (error, leave);
875 MonoReflectionTypeHandle pt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
876 MONO_HANDLE_ARRAY_GETREF (pt, helper_arguments, i);
877 encode_reflection_type (assembly, pt, buf, error);
878 goto_if_nok (error, leave);
879 leave:
880 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
883 guint32
884 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error)
886 SigBuffer buf;
887 guint32 nargs;
888 guint32 i, idx;
890 error_init (error);
892 if (!assembly->save)
893 return 0;
895 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
896 g_assert (MONO_HANDLE_GETVAL (helper, type) == 2);
898 MonoArrayHandle arguments = MONO_HANDLE_NEW_GET (MonoArray, helper, arguments);
899 if (!MONO_HANDLE_IS_NULL (arguments))
900 nargs = mono_array_handle_length (arguments);
901 else
902 nargs = 0;
904 sigbuffer_init (&buf, 32);
906 /* Encode calling convention */
907 /* Change Any to Standard */
908 if ((MONO_HANDLE_GETVAL (helper, call_conv) & 0x03) == 0x03)
909 MONO_HANDLE_SETVAL (helper, call_conv, guint32, 0x01);
910 /* explicit_this implies has_this */
911 if (MONO_HANDLE_GETVAL (helper, call_conv) & 0x40)
912 MONO_HANDLE_SETVAL (helper, call_conv, guint32, MONO_HANDLE_GETVAL (helper, call_conv) & 0x20);
914 if (MONO_HANDLE_GETVAL (helper, call_conv) == 0) { /* Unmanaged */
915 idx = MONO_HANDLE_GETVAL (helper, unmanaged_call_conv) - 1;
916 } else {
917 /* Managed */
918 idx = MONO_HANDLE_GETVAL (helper, call_conv) & 0x60; /* has_this + explicit_this */
919 if (MONO_HANDLE_GETVAL (helper, call_conv) & 0x02) /* varargs */
920 idx += 0x05;
923 sigbuffer_add_byte (&buf, idx);
924 sigbuffer_add_value (&buf, nargs);
925 encode_reflection_type (assembly, MONO_HANDLE_NEW_GET (MonoReflectionType, helper, return_type), &buf, error);
926 goto_if_nok (error, fail);
927 MonoArrayHandle modreqs = MONO_HANDLE_NEW_GET (MonoArray, helper, modreqs);
928 MonoArrayHandle modopts = MONO_HANDLE_NEW_GET (MonoArray, helper, modopts);
929 for (i = 0; i < nargs; ++i) {
930 if (!encode_sighelper_arg (assembly, i, arguments, modreqs, modopts, &buf, error))
931 goto fail;
933 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
934 sigbuffer_free (&buf);
936 return idx;
937 fail:
938 sigbuffer_free (&buf);
939 return 0;
941 #else /* DISABLE_REFLECTION_EMIT */
942 guint32
943 mono_dynimage_encode_reflection_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error)
945 g_assert_not_reached ();
946 return 0;
948 #endif /* DISABLE_REFLECTION_EMIT */
950 static gboolean
951 encode_reflection_types (MonoDynamicImage *assembly, MonoArrayHandle sig_arguments, int i, SigBuffer *buf, MonoError *error)
953 HANDLE_FUNCTION_ENTER ();
954 error_init (error);
955 MonoReflectionTypeHandle type = MONO_HANDLE_NEW (MonoReflectionType, NULL);
956 MONO_HANDLE_ARRAY_GETREF (type, sig_arguments, i);
957 encode_reflection_type (assembly, type, buf, error);
958 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
961 static MonoArrayHandle
962 reflection_sighelper_get_signature_local (MonoReflectionSigHelperHandle sig, MonoError *error)
964 MonoReflectionModuleBuilderHandle module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, sig, module);
965 MonoDynamicImage *assembly = MONO_HANDLE_IS_NULL (module) ? NULL : MONO_HANDLE_GETVAL (module, dynamic_image);
966 MonoArrayHandle sig_arguments = MONO_HANDLE_NEW_GET (MonoArray, sig, arguments);
967 guint32 na = MONO_HANDLE_IS_NULL (sig_arguments) ? 0 : mono_array_handle_length (sig_arguments);
968 guint32 buflen, i;
969 SigBuffer buf;
971 error_init (error);
973 sigbuffer_init (&buf, 32);
975 sigbuffer_add_value (&buf, 0x07);
976 sigbuffer_add_value (&buf, na);
977 if (assembly != NULL){
978 for (i = 0; i < na; ++i) {
979 if (!encode_reflection_types (assembly, sig_arguments, i, &buf, error))
980 goto fail;
984 buflen = buf.p - buf.buf;
985 MonoArrayHandle result = mono_array_new_handle (mono_domain_get (), mono_defaults.byte_class, buflen, error);
986 goto_if_nok (error, fail);
987 uint32_t gchandle;
988 void *base = MONO_ARRAY_HANDLE_PIN (result, char, 0, &gchandle);
989 memcpy (base, buf.buf, buflen);
990 sigbuffer_free (&buf);
991 mono_gchandle_free (gchandle);
992 return result;
993 fail:
994 sigbuffer_free (&buf);
995 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
998 static MonoArrayHandle
999 reflection_sighelper_get_signature_field (MonoReflectionSigHelperHandle sig, MonoError *error)
1001 MonoReflectionModuleBuilderHandle module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, sig, module);
1002 MonoDynamicImage *assembly = MONO_HANDLE_GETVAL (module, dynamic_image);
1003 MonoArrayHandle sig_arguments = MONO_HANDLE_NEW_GET (MonoArray, sig, arguments);
1004 guint32 na = MONO_HANDLE_IS_NULL (sig_arguments) ? 0 : mono_array_handle_length (sig_arguments);
1005 guint32 buflen, i;
1006 SigBuffer buf;
1008 error_init (error);
1010 sigbuffer_init (&buf, 32);
1012 sigbuffer_add_value (&buf, 0x06);
1013 for (i = 0; i < na; ++i) {
1014 if (! encode_reflection_types (assembly, sig_arguments, i, &buf, error))
1015 goto fail;
1018 buflen = buf.p - buf.buf;
1019 MonoArrayHandle result = mono_array_new_handle (mono_domain_get (), mono_defaults.byte_class, buflen, error);
1020 goto_if_nok (error, fail);
1021 uint32_t gchandle;
1022 void *base = MONO_ARRAY_HANDLE_PIN (result, char, 0, &gchandle);
1023 memcpy (base, buf.buf, buflen);
1024 sigbuffer_free (&buf);
1025 mono_gchandle_free (gchandle);
1027 return result;
1028 fail:
1029 sigbuffer_free (&buf);
1030 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
1033 static char*
1034 type_get_fully_qualified_name (MonoType *type)
1036 MONO_REQ_GC_NEUTRAL_MODE;
1038 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1041 #ifndef DISABLE_REFLECTION_EMIT_SAVE
1042 guint32
1043 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
1045 MONO_REQ_GC_UNSAFE_MODE;
1047 error_init (error);
1049 char *str;
1050 SigBuffer buf;
1051 guint32 idx, len;
1053 sigbuffer_init (&buf, 32);
1055 sigbuffer_add_value (&buf, minfo->type);
1057 switch (minfo->type) {
1058 case MONO_NATIVE_BYVALTSTR:
1059 case MONO_NATIVE_BYVALARRAY:
1060 sigbuffer_add_value (&buf, minfo->count);
1061 break;
1062 case MONO_NATIVE_LPARRAY:
1063 if (minfo->eltype || minfo->has_size) {
1064 sigbuffer_add_value (&buf, minfo->eltype);
1065 if (minfo->has_size) {
1066 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1067 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1069 /* LAMESPEC: ElemMult is undocumented */
1070 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1073 break;
1074 case MONO_NATIVE_SAFEARRAY:
1075 if (minfo->eltype)
1076 sigbuffer_add_value (&buf, minfo->eltype);
1077 break;
1078 case MONO_NATIVE_CUSTOM:
1079 if (minfo->guid) {
1080 str = mono_string_to_utf8_checked (minfo->guid, error);
1081 if (!is_ok (error)) {
1082 sigbuffer_free (&buf);
1083 return 0;
1085 len = strlen (str);
1086 sigbuffer_add_value (&buf, len);
1087 sigbuffer_add_mem (&buf, str, len);
1088 g_free (str);
1089 } else {
1090 sigbuffer_add_value (&buf, 0);
1092 /* native type name */
1093 sigbuffer_add_value (&buf, 0);
1094 /* custom marshaler type name */
1095 if (minfo->marshaltype || minfo->marshaltyperef) {
1096 if (minfo->marshaltyperef) {
1097 MonoType *marshaltype = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
1098 if (!is_ok (error)) {
1099 sigbuffer_free (&buf);
1100 return 0;
1102 str = type_get_fully_qualified_name (marshaltype);
1103 } else {
1104 str = mono_string_to_utf8_checked (minfo->marshaltype, error);
1105 if (!is_ok (error)) {
1106 sigbuffer_free (&buf);
1107 return 0;
1110 len = strlen (str);
1111 sigbuffer_add_value (&buf, len);
1112 sigbuffer_add_mem (&buf, str, len);
1113 g_free (str);
1114 } else {
1115 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1116 sigbuffer_add_value (&buf, 0);
1118 if (minfo->mcookie) {
1119 str = mono_string_to_utf8_checked (minfo->mcookie, error);
1120 if (!is_ok (error)) {
1121 sigbuffer_free (&buf);
1122 return 0;
1124 len = strlen (str);
1125 sigbuffer_add_value (&buf, len);
1126 sigbuffer_add_mem (&buf, str, len);
1127 g_free (str);
1128 } else {
1129 sigbuffer_add_value (&buf, 0);
1131 break;
1132 default:
1133 break;
1135 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1136 sigbuffer_free (&buf);
1137 return idx;
1140 guint32
1141 mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
1143 MONO_REQ_GC_UNSAFE_MODE;
1145 error_init (error);
1147 SigBuffer buf;
1148 guint32 nparams = 0;
1149 MonoReflectionMethodBuilder *mb = fb->get_method;
1150 MonoReflectionMethodBuilder *smb = fb->set_method;
1151 guint32 idx, i;
1153 if (mb && mb->parameters)
1154 nparams = mono_array_length (mb->parameters);
1155 if (!mb && smb && smb->parameters)
1156 nparams = mono_array_length (smb->parameters) - 1;
1157 sigbuffer_init (&buf, 32);
1158 if (fb->call_conv & 0x20)
1159 sigbuffer_add_byte (&buf, 0x28);
1160 else
1161 sigbuffer_add_byte (&buf, 0x08);
1162 sigbuffer_add_value (&buf, nparams);
1163 if (mb) {
1164 encode_reflection_type_raw (assembly, (MonoReflectionType*)mb->rtype, &buf, error);
1165 if (!is_ok (error))
1166 goto fail;
1167 for (i = 0; i < nparams; ++i) {
1168 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1169 encode_reflection_type_raw (assembly, pt, &buf, error);
1170 if (!is_ok (error))
1171 goto fail;
1173 } else if (smb && smb->parameters) {
1174 /* the property type is the last param */
1175 encode_reflection_type_raw (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf, error);
1176 if (!is_ok (error))
1177 goto fail;
1179 for (i = 0; i < nparams; ++i) {
1180 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1181 encode_reflection_type_raw (assembly, pt, &buf, error);
1182 if (!is_ok (error))
1183 goto fail;
1185 } else {
1186 encode_reflection_type_raw (assembly, (MonoReflectionType*)fb->type, &buf, error);
1187 if (!is_ok (error))
1188 goto fail;
1191 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1192 sigbuffer_free (&buf);
1193 return idx;
1194 fail:
1195 sigbuffer_free (&buf);
1196 return 0;
1200 #else /*DISABLE_REFLECTION_EMIT_SAVE*/
1201 guint32
1202 mono_dynimage_save_encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo, MonoError *error)
1204 g_assert_not_reached ();
1205 return 0;
1208 guint32
1209 mono_dynimage_save_encode_property_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb, MonoError *error)
1211 g_assert_not_reached ();
1212 return 0;
1214 #endif /*DISABLE_REFLECTION_EMIT_SAVE*/
1216 #ifndef DISABLE_REFLECTION_EMIT
1217 MonoArrayHandle
1218 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelperHandle sig, MonoError *error)
1220 error_init (error);
1221 return reflection_sighelper_get_signature_local (sig, error);
1224 MonoArrayHandle
1225 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelperHandle sig, MonoError *error)
1227 error_init (error);
1228 return reflection_sighelper_get_signature_field (sig, error);
1230 #else /* DISABLE_REFLECTION_EMIT */
1231 MonoArrayHandle
1232 ves_icall_SignatureHelper_get_signature_local (MonoReflectionSigHelperHandle sig, MonoError *error)
1234 error_init (error);
1235 g_assert_not_reached ();
1236 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
1239 MonoArrayHandle
1240 ves_icall_SignatureHelper_get_signature_field (MonoReflectionSigHelperHandle sig, MonoError *error)
1242 error_init (error);
1243 g_assert_not_reached ();
1244 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
1247 #endif /* DISABLE_REFLECTION_EMIT */