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