[sre] Emit a memberref token for fields,methods of a gtd
[mono-project.git] / mono / metadata / sre.c
blob2c59ff766bc815c8bd030c9a307604587e8dd849
1 /**
2 * \file
3 * Routines for creating an image at runtime
4 * and related System.Reflection.Emit icalls
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>
19 #include "mono/metadata/assembly.h"
20 #include "mono/metadata/debug-helpers.h"
21 #include "mono/metadata/dynamic-image-internals.h"
22 #include "mono/metadata/dynamic-stream-internals.h"
23 #include "mono/metadata/exception.h"
24 #include "mono/metadata/gc-internals.h"
25 #include "mono/metadata/mono-ptr-array.h"
26 #include "mono/metadata/object-internals.h"
27 #include "mono/metadata/profiler-private.h"
28 #include "mono/metadata/reflection-internals.h"
29 #include "mono/metadata/reflection-cache.h"
30 #include "mono/metadata/sre-internals.h"
31 #include "mono/metadata/custom-attrs-internals.h"
32 #include "mono/metadata/security-manager.h"
33 #include "mono/metadata/security-core-clr.h"
34 #include "mono/metadata/tabledefs.h"
35 #include "mono/metadata/tokentype.h"
36 #include "mono/utils/checked-build.h"
37 #include "mono/utils/mono-digest.h"
38 #include "mono/utils/w32api.h"
40 static GENERATE_GET_CLASS_WITH_CACHE (marshal_as_attribute, "System.Runtime.InteropServices", "MarshalAsAttribute");
41 static GENERATE_GET_CLASS_WITH_CACHE (module_builder, "System.Reflection.Emit", "ModuleBuilder");
43 static char* string_to_utf8_image_raw (MonoImage *image, MonoString *s, MonoError *error);
45 #ifndef DISABLE_REFLECTION_EMIT
46 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error);
47 static gboolean ensure_runtime_vtable (MonoClass *klass, MonoError *error);
48 static void reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb);
49 static gboolean reflection_setup_internal_class (MonoReflectionTypeBuilderHandle tb, MonoError *error);
50 static gboolean reflection_init_generic_class (MonoReflectionTypeBuilderHandle tb, MonoError *error);
51 static gboolean reflection_setup_class_hierarchy (GHashTable *unparented, MonoError *error);
54 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
55 #endif
57 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
58 static MonoReflectionTypeHandle mono_reflection_type_get_underlying_system_type (MonoReflectionTypeHandle t, MonoError *error);
59 static gboolean is_sre_array (MonoClass *klass);
60 static gboolean is_sre_byref (MonoClass *klass);
61 static gboolean is_sre_pointer (MonoClass *klass);
62 static gboolean is_sre_generic_instance (MonoClass *klass);
63 static gboolean is_sre_type_builder (MonoClass *klass);
64 static gboolean is_sre_method_builder (MonoClass *klass);
65 static gboolean is_sre_field_builder (MonoClass *klass);
66 static gboolean is_sre_gparam_builder (MonoClass *klass);
67 static gboolean is_sre_enum_builder (MonoClass *klass);
68 static gboolean is_sr_mono_method (MonoClass *klass);
69 static gboolean is_sr_mono_field (MonoClass *klass);
71 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
72 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
73 static guint32 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error);
76 #ifndef DISABLE_REFLECTION_EMIT
77 static MonoType* mono_type_array_get_and_resolve_raw (MonoArray* array, int idx, MonoError* error);
78 #endif
80 static gboolean mono_image_module_basic_init (MonoReflectionModuleBuilderHandle module, MonoError *error);
82 void
83 mono_reflection_emit_init (void)
85 mono_dynamic_images_init ();
88 char*
89 string_to_utf8_image_raw (MonoImage *image, MonoString *s_raw, MonoError *error)
91 /* FIXME all callers to string_to_utf8_image_raw should use handles */
92 HANDLE_FUNCTION_ENTER ();
93 char* result = NULL;
94 error_init (error);
95 MONO_HANDLE_DCL (MonoString, s);
96 result = mono_string_to_utf8_image (image, s, error);
97 HANDLE_FUNCTION_RETURN_VAL (result);
100 static char*
101 type_get_fully_qualified_name (MonoType *type)
103 MONO_REQ_GC_NEUTRAL_MODE;
105 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
108 static char*
109 type_get_qualified_name (MonoType *type, MonoAssembly *ass)
111 MONO_REQ_GC_UNSAFE_MODE;
113 MonoClass *klass;
114 MonoAssembly *ta;
116 klass = mono_class_from_mono_type (type);
117 if (!klass)
118 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
119 ta = klass->image->assembly;
120 if (assembly_is_dynamic (ta) || (ta == ass)) {
121 if (mono_class_is_ginst (klass) || mono_class_is_gtd (klass))
122 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
123 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
124 else
125 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
128 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
131 #ifndef DISABLE_REFLECTION_EMIT
133 * mp_g_alloc:
135 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
136 * from the C heap.
138 static gpointer
139 image_g_malloc (MonoImage *image, guint size)
141 MONO_REQ_GC_NEUTRAL_MODE;
143 if (image)
144 return mono_image_alloc (image, size);
145 else
146 return g_malloc (size);
148 #endif /* !DISABLE_REFLECTION_EMIT */
151 * image_g_alloc0:
153 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
154 * from the C heap.
156 gpointer
157 mono_image_g_malloc0 (MonoImage *image, guint size)
159 MONO_REQ_GC_NEUTRAL_MODE;
161 if (image)
162 return mono_image_alloc0 (image, size);
163 else
164 return g_malloc0 (size);
168 * image_g_free:
169 * @image: a MonoImage
170 * @ptr: pointer
172 * If @image is NULL, free @ptr, otherwise do nothing.
174 static void
175 image_g_free (MonoImage *image, gpointer ptr)
177 if (image == NULL)
178 g_free (ptr);
181 #ifndef DISABLE_REFLECTION_EMIT
182 static char*
183 image_strdup (MonoImage *image, const char *s)
185 MONO_REQ_GC_NEUTRAL_MODE;
187 if (image)
188 return mono_image_strdup (image, s);
189 else
190 return g_strdup (s);
192 #endif
194 #define image_g_new(image,struct_type, n_structs) \
195 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
197 #define image_g_new0(image,struct_type, n_structs) \
198 ((struct_type *) mono_image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
201 static void
202 alloc_table (MonoDynamicTable *table, guint nrows)
204 mono_dynimage_alloc_table (table, nrows);
207 static guint32
208 string_heap_insert (MonoDynamicStream *sh, const char *str)
210 return mono_dynstream_insert_string (sh, str);
213 static guint32
214 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
216 return mono_dynstream_add_data (stream, data, len);
220 * Despite the name, we handle also TypeSpec (with the above helper).
222 static guint32
223 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
225 return mono_dynimage_encode_typedef_or_ref_full (assembly, type, TRUE);
229 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
230 * dest may be misaligned.
232 static void
233 swap_with_size (char *dest, const char* val, int len, int nelem) {
234 MONO_REQ_GC_NEUTRAL_MODE;
235 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
236 int elem;
238 for (elem = 0; elem < nelem; ++elem) {
239 switch (len) {
240 case 1:
241 *dest = *val;
242 break;
243 case 2:
244 dest [0] = val [1];
245 dest [1] = val [0];
246 break;
247 case 4:
248 dest [0] = val [3];
249 dest [1] = val [2];
250 dest [2] = val [1];
251 dest [3] = val [0];
252 break;
253 case 8:
254 dest [0] = val [7];
255 dest [1] = val [6];
256 dest [2] = val [5];
257 dest [3] = val [4];
258 dest [4] = val [3];
259 dest [5] = val [2];
260 dest [6] = val [1];
261 dest [7] = val [0];
262 break;
263 default:
264 g_assert_not_reached ();
266 dest += len;
267 val += len;
269 #else
270 memcpy (dest, val, len * nelem);
271 #endif
274 guint32
275 mono_reflection_method_count_clauses (MonoReflectionILGen *ilgen)
277 MONO_REQ_GC_UNSAFE_MODE;
279 guint32 num_clauses = 0;
280 int i;
282 MonoILExceptionInfo *ex_info;
283 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
284 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
285 if (ex_info->handlers)
286 num_clauses += mono_array_length (ex_info->handlers);
287 else
288 num_clauses++;
291 return num_clauses;
294 #ifndef DISABLE_REFLECTION_EMIT
295 static MonoExceptionClause*
296 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses, MonoError *error)
298 MONO_REQ_GC_UNSAFE_MODE;
300 error_init (error);
302 MonoExceptionClause *clauses;
303 MonoExceptionClause *clause;
304 MonoILExceptionInfo *ex_info;
305 MonoILExceptionBlock *ex_block;
306 guint32 finally_start;
307 int i, j, clause_index;;
309 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
311 clause_index = 0;
312 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
313 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
314 finally_start = ex_info->start + ex_info->len;
315 if (!ex_info->handlers)
316 continue;
317 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
318 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
319 clause = &(clauses [clause_index]);
321 clause->flags = ex_block->type;
322 clause->try_offset = ex_info->start;
324 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
325 clause->try_len = finally_start - ex_info->start;
326 else
327 clause->try_len = ex_info->len;
328 clause->handler_offset = ex_block->start;
329 clause->handler_len = ex_block->len;
330 if (ex_block->extype) {
331 MonoType *extype = mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype, error);
333 if (!is_ok (error)) {
334 image_g_free (image, clauses);
335 return NULL;
337 clause->data.catch_class = mono_class_from_mono_type (extype);
338 } else {
339 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
340 clause->data.filter_offset = ex_block->filter_offset;
341 else
342 clause->data.filter_offset = 0;
344 finally_start = ex_block->start + ex_block->len;
346 clause_index ++;
350 return clauses;
352 #endif /* !DISABLE_REFLECTION_EMIT */
354 #ifndef DISABLE_REFLECTION_EMIT
356 * LOCKING: Acquires the loader lock.
358 static void
359 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
361 MONO_REQ_GC_UNSAFE_MODE;
363 MonoCustomAttrInfo *ainfo, *tmp;
365 if (!cattrs || !mono_array_length (cattrs))
366 return;
368 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
370 mono_loader_lock ();
371 tmp = (MonoCustomAttrInfo *)mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
372 if (tmp)
373 mono_custom_attrs_free (tmp);
374 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
375 mono_loader_unlock ();
378 #else
379 //FIXME some code compiled under DISABLE_REFLECTION_EMIT depends on this function, we should be more aggressively disabling things
380 static void
381 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
384 #endif
386 guint32
387 mono_reflection_resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
389 MONO_REQ_GC_UNSAFE_MODE;
391 MonoDynamicTable *table;
392 guint32 token;
393 guint32 *values;
394 guint32 cols [MONO_ASSEMBLY_SIZE];
395 const char *pubkey;
396 guint32 publen;
398 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
399 return token;
401 if (assembly_is_dynamic (image->assembly) && (image->assembly == assembly->image.assembly)) {
402 table = &assembly->tables [MONO_TABLE_MODULEREF];
403 token = table->next_idx ++;
404 table->rows ++;
405 alloc_table (table, table->rows);
406 values = table->values + token * MONO_MODULEREF_SIZE;
407 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
409 token <<= MONO_RESOLUTION_SCOPE_BITS;
410 token |= MONO_RESOLUTION_SCOPE_MODULEREF;
411 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
413 return token;
416 if (assembly_is_dynamic (image->assembly))
417 /* FIXME: */
418 memset (cols, 0, sizeof (cols));
419 else {
420 /* image->assembly->image is the manifest module */
421 image = image->assembly->image;
422 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
425 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
426 token = table->next_idx ++;
427 table->rows ++;
428 alloc_table (table, table->rows);
429 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
430 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
431 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
432 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
433 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
434 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
435 values [MONO_ASSEMBLYREF_FLAGS] = 0;
436 values [MONO_ASSEMBLYREF_CULTURE] = 0;
437 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
439 if (strcmp ("", image->assembly->aname.culture)) {
440 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
441 image->assembly->aname.culture);
444 if ((pubkey = mono_image_get_public_key (image, &publen))) {
445 guchar pubtoken [9];
446 pubtoken [0] = 8;
447 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
448 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
449 } else {
450 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
452 token <<= MONO_RESOLUTION_SCOPE_BITS;
453 token |= MONO_RESOLUTION_SCOPE_ASSEMBLYREF;
454 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
455 return token;
458 #ifndef DISABLE_REFLECTION_EMIT
459 gboolean
460 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error)
462 MONO_REQ_GC_UNSAFE_MODE;
464 error_init (error);
465 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
467 rmb->ilgen = mb->ilgen;
468 rmb->rtype = (MonoReflectionType*)mb->rtype;
469 return_val_if_nok (error, FALSE);
470 rmb->parameters = mb->parameters;
471 rmb->generic_params = mb->generic_params;
472 rmb->generic_container = mb->generic_container;
473 rmb->opt_types = NULL;
474 rmb->pinfo = mb->pinfo;
475 rmb->attrs = mb->attrs;
476 rmb->iattrs = mb->iattrs;
477 rmb->call_conv = mb->call_conv;
478 rmb->code = mb->code;
479 rmb->type = mb->type;
480 rmb->name = mb->name;
481 rmb->table_idx = &mb->table_idx;
482 rmb->init_locals = mb->init_locals;
483 rmb->skip_visibility = FALSE;
484 rmb->return_modreq = mb->return_modreq;
485 rmb->return_modopt = mb->return_modopt;
486 rmb->param_modreq = mb->param_modreq;
487 rmb->param_modopt = mb->param_modopt;
488 rmb->permissions = mb->permissions;
489 rmb->mhandle = mb->mhandle;
490 rmb->nrefs = 0;
491 rmb->refs = NULL;
493 if (mb->dll) {
494 rmb->charset = mb->charset;
495 rmb->extra_flags = mb->extra_flags;
496 rmb->native_cc = mb->native_cc;
497 rmb->dllentry = mb->dllentry;
498 rmb->dll = mb->dll;
501 return TRUE;
504 gboolean
505 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
507 MONO_REQ_GC_UNSAFE_MODE;
509 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
511 error_init (error);
513 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
515 rmb->ilgen = mb->ilgen;
516 rmb->rtype = mono_type_get_object_checked (mono_domain_get (), &mono_defaults.void_class->byval_arg, error);
517 return_val_if_nok (error, FALSE);
518 rmb->parameters = mb->parameters;
519 rmb->generic_params = NULL;
520 rmb->generic_container = NULL;
521 rmb->opt_types = NULL;
522 rmb->pinfo = mb->pinfo;
523 rmb->attrs = mb->attrs;
524 rmb->iattrs = mb->iattrs;
525 rmb->call_conv = mb->call_conv;
526 rmb->code = NULL;
527 rmb->type = mb->type;
528 rmb->name = mono_string_new_checked (mono_domain_get (), name, error);
529 return_val_if_nok (error, FALSE);
530 rmb->table_idx = &mb->table_idx;
531 rmb->init_locals = mb->init_locals;
532 rmb->skip_visibility = FALSE;
533 rmb->return_modreq = NULL;
534 rmb->return_modopt = NULL;
535 rmb->param_modreq = mb->param_modreq;
536 rmb->param_modopt = mb->param_modopt;
537 rmb->permissions = mb->permissions;
538 rmb->mhandle = mb->mhandle;
539 rmb->nrefs = 0;
540 rmb->refs = NULL;
542 return TRUE;
545 static void
546 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
548 MONO_REQ_GC_UNSAFE_MODE;
550 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
552 rmb->ilgen = mb->ilgen;
553 rmb->rtype = mb->rtype;
554 rmb->parameters = mb->parameters;
555 rmb->generic_params = NULL;
556 rmb->generic_container = NULL;
557 rmb->opt_types = NULL;
558 rmb->pinfo = NULL;
559 rmb->attrs = mb->attrs;
560 rmb->iattrs = 0;
561 rmb->call_conv = mb->call_conv;
562 rmb->code = NULL;
563 rmb->type = (MonoObject *) mb->owner;
564 rmb->name = mb->name;
565 rmb->table_idx = NULL;
566 rmb->init_locals = mb->init_locals;
567 rmb->skip_visibility = mb->skip_visibility;
568 rmb->return_modreq = NULL;
569 rmb->return_modopt = NULL;
570 rmb->param_modreq = NULL;
571 rmb->param_modopt = NULL;
572 rmb->permissions = NULL;
573 rmb->mhandle = mb->mhandle;
574 rmb->nrefs = 0;
575 rmb->refs = NULL;
577 #else /* DISABLE_REFLECTION_EMIT */
578 gboolean
579 mono_reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb, MonoError *error) {
580 g_assert_not_reached ();
581 return FALSE;
583 gboolean
584 mono_reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb, MonoError *error)
586 g_assert_not_reached ();
587 return FALSE;
589 #endif /* DISABLE_REFLECTION_EMIT */
591 #ifndef DISABLE_REFLECTION_EMIT
592 static guint32
593 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
595 MONO_REQ_GC_NEUTRAL_MODE;
597 MonoDynamicTable *table;
598 guint32 *values;
599 guint32 token, pclass;
601 switch (parent & MONO_TYPEDEFORREF_MASK) {
602 case MONO_TYPEDEFORREF_TYPEREF:
603 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
604 break;
605 case MONO_TYPEDEFORREF_TYPESPEC:
606 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
607 break;
608 case MONO_TYPEDEFORREF_TYPEDEF:
609 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
610 break;
611 default:
612 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
613 return 0;
615 /* extract the index */
616 parent >>= MONO_TYPEDEFORREF_BITS;
618 table = &assembly->tables [MONO_TABLE_MEMBERREF];
620 if (assembly->save) {
621 alloc_table (table, table->rows + 1);
622 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
623 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
624 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
625 values [MONO_MEMBERREF_SIGNATURE] = sig;
628 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
629 table->next_idx ++;
631 return token;
635 * Insert a memberef row into the metadata: the token that point to the memberref
636 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
637 * mono_image_get_fieldref_token()).
638 * The sig param is an index to an already built signature.
640 static guint32
641 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
643 MONO_REQ_GC_NEUTRAL_MODE;
645 guint32 parent = mono_image_typedef_or_ref (assembly, type);
646 return mono_image_add_memberef_row (assembly, parent, name, sig);
650 guint32
651 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
653 MONO_REQ_GC_NEUTRAL_MODE;
655 guint32 token;
656 MonoMethodSignature *sig;
658 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
660 if (create_typespec) {
661 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
662 if (token)
663 return token;
666 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
667 if (token && !create_typespec)
668 return token;
670 g_assert (!method->is_inflated);
671 if (!token) {
673 * A methodref signature can't contain an unmanaged calling convention.
675 sig = mono_metadata_signature_dup (mono_method_signature (method));
676 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
677 sig->call_convention = MONO_CALL_DEFAULT;
678 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
679 method->name, mono_dynimage_encode_method_signature (assembly, sig));
680 g_free (sig);
681 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
684 if (create_typespec) {
685 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
686 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
687 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
689 if (assembly->save) {
690 guint32 *values;
692 alloc_table (table, table->rows + 1);
693 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
694 values [MONO_METHODSPEC_METHOD] = token;
695 values [MONO_METHODSPEC_SIGNATURE] = mono_dynimage_encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
698 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
699 table->next_idx ++;
700 /*methodspec and memberef tokens are diferent, */
701 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
702 return token;
704 return token;
707 static guint32
708 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
709 const gchar *name, guint32 sig)
711 MonoDynamicTable *table;
712 guint32 token;
713 guint32 *values;
715 table = &assembly->tables [MONO_TABLE_MEMBERREF];
717 if (assembly->save) {
718 alloc_table (table, table->rows + 1);
719 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
720 values [MONO_MEMBERREF_CLASS] = original;
721 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
722 values [MONO_MEMBERREF_SIGNATURE] = sig;
725 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
726 table->next_idx ++;
728 return token;
731 #else /* DISABLE_REFLECTION_EMIT */
733 guint32
734 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
736 g_assert_not_reached ();
737 return -1;
739 #endif
741 static gboolean
742 is_field_on_inst (MonoClassField *field)
744 return mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->is_dynamic;
747 static gboolean
748 is_field_on_gtd (MonoClassField *field)
750 return mono_class_is_gtd (field->parent);
753 #ifndef DISABLE_REFLECTION_EMIT
754 static guint32
755 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoClassField *field)
757 MonoType *type;
758 guint32 token;
760 g_assert (field);
761 g_assert (field->parent);
763 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, field));
764 if (token)
765 return token;
767 if (mono_class_is_ginst (field->parent) && mono_class_get_generic_class (field->parent)->container_class && mono_class_get_generic_class (field->parent)->container_class->fields) {
768 int index = field - field->parent->fields;
769 type = mono_field_get_type (&mono_class_get_generic_class (field->parent)->container_class->fields [index]);
770 } else {
771 type = mono_field_get_type (field);
773 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
774 mono_field_get_name (field),
775 mono_dynimage_encode_fieldref_signature (assembly, field->parent->image, type));
776 g_hash_table_insert (assembly->handleref, field, GUINT_TO_POINTER(token));
777 return token;
780 static guint32
781 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
783 MonoDynamicTable *table;
784 guint32 *values;
785 guint32 token, mtoken = 0, sig;
786 MonoMethodInflated *imethod;
787 MonoMethod *declaring;
789 table = &assembly->tables [MONO_TABLE_METHODSPEC];
791 g_assert (method->is_inflated);
792 imethod = (MonoMethodInflated *) method;
793 declaring = imethod->declaring;
795 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (declaring));
796 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
798 if (!mono_method_signature (declaring)->generic_param_count)
799 return mtoken;
801 switch (mono_metadata_token_table (mtoken)) {
802 case MONO_TABLE_MEMBERREF:
803 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
804 break;
805 case MONO_TABLE_METHOD:
806 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
807 break;
808 default:
809 g_assert_not_reached ();
812 sig = mono_dynimage_encode_generic_method_sig (assembly, mono_method_get_context (method));
814 if (assembly->save) {
815 alloc_table (table, table->rows + 1);
816 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
817 values [MONO_METHODSPEC_METHOD] = mtoken;
818 values [MONO_METHODSPEC_SIGNATURE] = sig;
821 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
822 table->next_idx ++;
824 return token;
827 static guint32
828 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
830 MonoMethodInflated *imethod;
831 guint32 token;
833 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
834 if (token)
835 return token;
837 g_assert (method->is_inflated);
838 imethod = (MonoMethodInflated *) method;
840 if (mono_method_signature (imethod->declaring)->generic_param_count) {
841 token = method_encode_methodspec (assembly, method);
842 } else {
843 guint32 sig = mono_dynimage_encode_method_signature (
844 assembly, mono_method_signature (imethod->declaring));
845 token = mono_image_get_memberref_token (
846 assembly, &method->klass->byval_arg, method->name, sig);
849 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
850 return token;
853 static guint32
854 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
856 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
857 guint32 sig, token;
859 sig = mono_dynimage_encode_method_signature (assembly, mono_method_signature (imethod->declaring));
860 token = mono_image_get_memberref_token (
861 assembly, &m->klass->byval_arg, m->name, sig);
863 return token;
866 static guint32
867 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelperHandle helper, MonoError *error)
869 guint32 idx;
870 MonoDynamicTable *table;
871 guint32 *values;
873 error_init (error);
875 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
876 idx = table->next_idx ++;
877 table->rows ++;
878 alloc_table (table, table->rows);
879 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
881 values [MONO_STAND_ALONE_SIGNATURE] =
882 mono_dynimage_encode_reflection_sighelper (assembly, helper, error);
883 return_val_if_nok (error, 0);
885 return idx;
888 static int
889 reflection_cc_to_file (int call_conv) {
890 switch (call_conv & 0x3) {
891 case 0:
892 case 1: return MONO_CALL_DEFAULT;
893 case 2: return MONO_CALL_VARARG;
894 default:
895 g_assert_not_reached ();
897 return 0;
899 #endif /* !DISABLE_REFLECTION_EMIT */
901 struct _ArrayMethod {
902 MonoType *parent;
903 MonoMethodSignature *sig;
904 char *name;
905 guint32 token;
908 void
909 mono_sre_array_method_free (ArrayMethod *am)
911 g_free (am->sig);
912 g_free (am->name);
913 g_free (am);
916 #ifndef DISABLE_REFLECTION_EMIT
917 static guint32
918 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethodHandle m, MonoError *error)
920 MonoMethodSignature *sig = NULL;
921 char *name = NULL;
923 error_init (error);
925 MonoArrayHandle parameters = MONO_HANDLE_NEW_GET (MonoArray, m, parameters);
926 guint32 nparams = mono_array_handle_length (parameters);
927 sig = (MonoMethodSignature *)g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
928 sig->hasthis = 1;
929 sig->sentinelpos = -1;
930 sig->call_convention = reflection_cc_to_file (MONO_HANDLE_GETVAL (m, call_conv));
931 sig->param_count = nparams;
932 MonoReflectionTypeHandle ret = MONO_HANDLE_NEW_GET (MonoReflectionType, m, ret);
933 if (!MONO_HANDLE_IS_NULL (ret)) {
934 sig->ret = mono_reflection_type_handle_mono_type (ret, error);
935 goto_if_nok (error, fail);
936 } else
937 sig->ret = &mono_defaults.void_class->byval_arg;
939 MonoReflectionTypeHandle parent = MONO_HANDLE_NEW_GET (MonoReflectionType, m, parent);
940 MonoType *mtype = mono_reflection_type_handle_mono_type (parent, error);
941 goto_if_nok (error, fail);
943 for (int i = 0; i < nparams; ++i) {
944 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
945 goto_if_nok (error, fail);
948 MonoStringHandle mname = MONO_HANDLE_NEW_GET (MonoString, m, name);
949 name = mono_string_handle_to_utf8 (mname, error);
950 goto_if_nok (error, fail);
952 ArrayMethod *am = NULL;
953 for (GList *tmp = assembly->array_methods; tmp; tmp = tmp->next) {
954 am = (ArrayMethod *)tmp->data;
955 if (strcmp (name, am->name) == 0 &&
956 mono_metadata_type_equal (am->parent, mtype) &&
957 mono_metadata_signature_equal (am->sig, sig)) {
958 g_free (name);
959 g_free (sig);
960 MONO_HANDLE_SETVAL (m, table_idx, guint32, am->token & 0xffffff);
961 return am->token;
964 am = g_new0 (ArrayMethod, 1);
965 am->name = name;
966 am->sig = sig;
967 am->parent = mtype;
968 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
969 mono_dynimage_encode_method_signature (assembly, sig));
970 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
971 MONO_HANDLE_SETVAL (m, table_idx, guint32, am->token & 0xffffff);
972 return am->token;
973 fail:
974 g_free (name);
975 g_free (sig);
976 return 0;
979 #endif
981 #ifndef DISABLE_REFLECTION_EMIT
984 * mono_image_insert_string:
985 * @module: module builder object
986 * @str: a string
988 * Insert @str into the user string stream of @module.
990 guint32
991 mono_image_insert_string (MonoReflectionModuleBuilderHandle ref_module, MonoStringHandle str, MonoError *error)
993 HANDLE_FUNCTION_ENTER ();
994 guint32 idx;
995 char buf [16];
996 char *b = buf;
997 guint32 token = 0;
999 MonoDynamicImage *assembly = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
1000 if (!assembly) {
1001 if (!mono_image_module_basic_init (ref_module, error))
1002 goto leave;
1004 assembly = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
1006 g_assert (assembly != NULL);
1008 if (assembly->save) {
1009 int32_t length = mono_string_length (MONO_HANDLE_RAW (str));
1010 mono_metadata_encode_value (1 | (length * 2), b, &b);
1011 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
1012 /* pinned */
1013 uint32_t gchandle = mono_gchandle_from_handle (MONO_HANDLE_CAST (MonoObject, str), TRUE);
1014 const char *p = (const char*)mono_string_chars (MONO_HANDLE_RAW (str));
1015 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1017 char *swapped = g_malloc (2 * length);
1019 swap_with_size (swapped, p, 2, length);
1020 mono_image_add_stream_data (&assembly->us, swapped, length * 2);
1021 g_free (swapped);
1023 #else
1024 mono_image_add_stream_data (&assembly->us, p, length * 2);
1025 #endif
1026 mono_gchandle_free (gchandle);
1027 mono_image_add_stream_data (&assembly->us, "", 1);
1028 } else {
1029 idx = assembly->us.index ++;
1032 token = MONO_TOKEN_STRING | idx;
1033 mono_dynamic_image_register_token (assembly, token, MONO_HANDLE_CAST (MonoObject, str), MONO_DYN_IMAGE_TOK_NEW);
1035 leave:
1036 HANDLE_FUNCTION_RETURN_VAL (token);
1039 static guint32
1040 create_method_token (MonoDynamicImage *assembly, MonoMethod *method, MonoArrayHandle opt_param_types, MonoError *error)
1042 guint32 sig_token, parent;
1045 int nargs = mono_array_handle_length (opt_param_types);
1046 MonoMethodSignature *old = mono_method_signature (method);
1047 MonoMethodSignature *sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
1049 sig->hasthis = old->hasthis;
1050 sig->explicit_this = old->explicit_this;
1051 sig->call_convention = old->call_convention;
1052 sig->generic_param_count = old->generic_param_count;
1053 sig->param_count = old->param_count + nargs;
1054 sig->sentinelpos = old->param_count;
1055 sig->ret = old->ret;
1057 for (int i = 0; i < old->param_count; i++)
1058 sig->params [i] = old->params [i];
1060 MonoReflectionTypeHandle rt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1061 for (int i = 0; i < nargs; i++) {
1062 MONO_HANDLE_ARRAY_GETREF (rt, opt_param_types, i);
1063 sig->params [old->param_count + i] = mono_reflection_type_handle_mono_type (rt, error);
1064 goto_if_nok (error, fail);
1067 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
1068 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
1069 parent >>= MONO_TYPEDEFORREF_BITS;
1071 parent <<= MONO_MEMBERREF_PARENT_BITS;
1072 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
1074 sig_token = mono_dynimage_encode_method_signature (assembly, sig);
1075 guint32 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
1076 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
1077 return token;
1078 fail:
1079 return 0;
1082 guint32
1083 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error)
1085 guint32 token = 0;
1087 error_init (error);
1089 MonoClass *klass = mono_handle_class (obj);
1090 if (strcmp (klass->name, "MonoMethod") == 0 || strcmp (klass->name, "MonoCMethod") == 0) {
1091 MonoReflectionMethodHandle ref_method = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
1092 MonoMethod *method = MONO_HANDLE_GETVAL (ref_method, method);
1093 g_assert (!MONO_HANDLE_IS_NULL (opt_param_types) && (mono_method_signature (method)->sentinelpos >= 0));
1094 token = create_method_token (assembly, method, opt_param_types, error);
1095 goto_if_nok (error, fail);
1096 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
1097 g_assert_not_reached ();
1098 } else {
1099 g_error ("requested method token for %s\n", klass->name);
1102 mono_dynamic_image_register_token (assembly, token, obj, MONO_DYN_IMAGE_TOK_NEW);
1103 return token;
1104 fail:
1105 g_assert (!mono_error_ok (error));
1106 return 0;
1110 * mono_image_create_token:
1111 * @assembly: a dynamic assembly
1112 * @obj:
1113 * @register_token: Whenever to register the token in the assembly->tokens hash.
1115 * Get a token to insert in the IL code stream for the given MemberInfo.
1116 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
1117 * the table_idx-es were recomputed, so registering the token would overwrite an existing
1118 * entry.
1120 guint32
1121 mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
1122 gboolean create_open_instance, gboolean register_token,
1123 MonoError *error)
1125 HANDLE_FUNCTION_ENTER ();
1126 guint32 token = 0;
1128 error_init (error);
1130 MonoClass *klass = mono_handle_class (obj);
1131 MonoObjectHandle register_obj = MONO_HANDLE_NEW (MonoObject, NULL);
1132 MONO_HANDLE_ASSIGN (register_obj, obj);
1134 /* Check for user defined reflection objects */
1135 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
1136 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0)) {
1137 mono_error_set_not_supported (error, "User defined subclasses of System.Type are not yet supported");
1138 goto leave;
1141 /* This function is called from ModuleBuilder:getToken multiple times for the same objects */
1142 int how_collide = MONO_DYN_IMAGE_TOK_SAME_OK;
1144 if (strcmp (klass->name, "RuntimeType") == 0) {
1145 MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, obj), error);
1146 goto_if_nok (error, leave);
1147 MonoClass *mc = mono_class_from_mono_type (type);
1148 token = mono_metadata_token_from_dor (
1149 mono_dynimage_encode_typedef_or_ref_full (assembly, type, !mono_class_is_gtd (mc) || create_open_instance));
1150 /* If it's a RuntimeType now, we could have registered a
1151 * TypeBuilder for it before, so replacing is okay. */
1152 how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
1153 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
1154 strcmp (klass->name, "MonoMethod") == 0) {
1155 MonoReflectionMethodHandle m = MONO_HANDLE_CAST (MonoReflectionMethod, obj);
1156 MonoMethod *method = MONO_HANDLE_GETVAL (m, method);
1157 if (method->is_inflated) {
1158 if (create_open_instance) {
1159 guint32 methodspec_token = mono_image_get_methodspec_token (assembly, method);
1160 MonoReflectionMethodHandle canonical_obj =
1161 mono_method_get_object_handle (MONO_HANDLE_DOMAIN (obj), method, NULL, error);
1162 goto_if_nok (error, leave);
1163 MONO_HANDLE_ASSIGN (register_obj, canonical_obj);
1164 token = methodspec_token;
1165 } else
1166 token = mono_image_get_inflated_method_token (assembly, method);
1167 } else if ((method->klass->image == &assembly->image) &&
1168 !mono_class_is_ginst (method->klass) &&
1169 !mono_class_is_gtd (method->klass)) {
1170 static guint32 method_table_idx = 0xffffff;
1171 if (method->klass->wastypebuilder) {
1172 /* we use the same token as the one that was assigned
1173 * to the Methodbuilder.
1174 * FIXME: do the equivalent for Fields.
1176 token = method->token;
1177 how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
1178 } else {
1180 * Each token should have a unique index, but the indexes are
1181 * assigned by managed code, so we don't know about them. An
1182 * easy solution is to count backwards...
1184 method_table_idx --;
1185 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
1186 how_collide = MONO_DYN_IMAGE_TOK_NEW;
1188 } else {
1189 guint32 methodref_token = mono_image_get_methodref_token (assembly, method, create_open_instance);
1190 /* We need to register a 'canonical' object. The same
1191 * MonoMethod could have been reflected via different
1192 * classes so the MonoReflectionMethod:reftype could be
1193 * different, and the object lookup in
1194 * dynamic_image_register_token would assert assert. So
1195 * we pick the MonoReflectionMethod object that has the
1196 * reflected type as NULL (ie, take the declaring type
1197 * of the method) */
1198 MonoReflectionMethodHandle canonical_obj =
1199 mono_method_get_object_handle (MONO_HANDLE_DOMAIN (obj), method, NULL, error);
1200 goto_if_nok (error, leave);
1201 MONO_HANDLE_ASSIGN (register_obj, canonical_obj);
1202 token = methodref_token;
1204 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
1205 } else if (strcmp (klass->name, "MonoField") == 0) {
1206 MonoReflectionFieldHandle f = MONO_HANDLE_CAST (MonoReflectionField, obj);
1207 MonoClassField *field = MONO_HANDLE_GETVAL (f, field);
1208 if ((field->parent->image == &assembly->image) &&
1209 !is_field_on_gtd (field) &&
1210 !is_field_on_inst (field)) {
1211 static guint32 field_table_idx = 0xffffff;
1212 field_table_idx --;
1213 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
1214 g_assert (!mono_class_is_gtd (field->parent));
1215 how_collide = MONO_DYN_IMAGE_TOK_NEW;
1216 } else {
1217 guint32 fieldref_token = mono_image_get_fieldref_token (assembly, field);
1218 /* Same as methodref: get a canonical object to
1219 * register with the token. */
1220 MonoReflectionFieldHandle canonical_obj =
1221 mono_field_get_object_handle (MONO_HANDLE_DOMAIN (obj), field->parent, field, error);
1222 goto_if_nok (error, leave);
1223 MONO_HANDLE_ASSIGN (register_obj, canonical_obj);
1224 token = fieldref_token;
1226 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
1227 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
1228 MonoReflectionArrayMethodHandle m = MONO_HANDLE_CAST (MonoReflectionArrayMethod, obj);
1229 /* mono_image_get_array_token caches tokens by signature */
1230 guint32 array_token = mono_image_get_array_token (assembly, m, error);
1231 goto_if_nok (error, leave);
1232 token = array_token;
1233 /* ModuleBuilder:GetArrayMethod() always returns a fresh
1234 * MonoArrayMethod instance even given the same method name and
1235 * signature. But they're all interchangeable, so it's okay to
1236 * replace.
1238 how_collide = MONO_DYN_IMAGE_TOK_REPLACE;
1239 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
1240 MonoReflectionSigHelperHandle s = MONO_HANDLE_CAST (MonoReflectionSigHelper, obj);
1241 /* always returns a fresh token */
1242 guint32 sig_token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s, error);
1243 goto_if_nok (error, leave);
1244 token = sig_token;
1245 how_collide = MONO_DYN_IMAGE_TOK_NEW;
1246 } else {
1247 g_error ("requested token for %s\n", klass->name);
1250 if (register_token)
1251 mono_dynamic_image_register_token (assembly, token, register_obj, how_collide);
1253 leave:
1254 HANDLE_FUNCTION_RETURN_VAL (token);
1258 #endif
1260 #ifndef DISABLE_REFLECTION_EMIT
1262 static gboolean
1263 assemblybuilderaccess_can_refonlyload (guint32 access)
1265 return (access & 0x4) != 0;
1268 static gboolean
1269 assemblybuilderaccess_can_run (guint32 access)
1271 return (access & MonoAssemblyBuilderAccess_Run) != 0;
1274 static gboolean
1275 assemblybuilderaccess_can_save (guint32 access)
1277 return (access & MonoAssemblyBuilderAccess_Save) != 0;
1282 * mono_reflection_dynimage_basic_init:
1283 * @assembly: an assembly builder object
1285 * Create the MonoImage that represents the assembly builder and setup some
1286 * of the helper hash table and the basic metadata streams.
1288 void
1289 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
1291 MonoError error;
1292 MonoDynamicAssembly *assembly;
1293 MonoDynamicImage *image;
1294 MonoDomain *domain = mono_object_domain (assemblyb);
1296 if (assemblyb->dynamic_assembly)
1297 return;
1299 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
1301 MONO_PROFILER_RAISE (assembly_loading, (&assembly->assembly));
1303 assembly->assembly.ref_count = 1;
1304 assembly->assembly.dynamic = TRUE;
1305 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
1306 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
1307 assembly->assembly.basedir = mono_string_to_utf8_checked (assemblyb->dir, &error);
1308 if (mono_error_set_pending_exception (&error))
1309 return;
1310 if (assemblyb->culture) {
1311 assembly->assembly.aname.culture = mono_string_to_utf8_checked (assemblyb->culture, &error);
1312 if (mono_error_set_pending_exception (&error))
1313 return;
1314 } else
1315 assembly->assembly.aname.culture = g_strdup ("");
1317 if (assemblyb->version) {
1318 char *vstr = mono_string_to_utf8_checked (assemblyb->version, &error);
1319 if (mono_error_set_pending_exception (&error))
1320 return;
1321 char **version = g_strsplit (vstr, ".", 4);
1322 char **parts = version;
1323 assembly->assembly.aname.major = atoi (*parts++);
1324 assembly->assembly.aname.minor = atoi (*parts++);
1325 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
1326 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
1328 g_strfreev (version);
1329 g_free (vstr);
1330 } else {
1331 assembly->assembly.aname.major = 0;
1332 assembly->assembly.aname.minor = 0;
1333 assembly->assembly.aname.build = 0;
1334 assembly->assembly.aname.revision = 0;
1337 assembly->assembly.ref_only = assemblybuilderaccess_can_refonlyload (assemblyb->access);
1338 assembly->run = assemblybuilderaccess_can_run (assemblyb->access);
1339 assembly->save = assemblybuilderaccess_can_save (assemblyb->access);
1340 assembly->domain = domain;
1342 char *assembly_name = mono_string_to_utf8_checked (assemblyb->name, &error);
1343 if (mono_error_set_pending_exception (&error))
1344 return;
1345 image = mono_dynamic_image_create (assembly, assembly_name, g_strdup ("RefEmit_YouForgotToDefineAModule"));
1346 image->initial_image = TRUE;
1347 assembly->assembly.aname.name = image->image.name;
1348 assembly->assembly.image = &image->image;
1349 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
1350 /* -1 to correct for the trailing NULL byte */
1351 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
1352 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
1354 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
1357 mono_domain_assemblies_lock (domain);
1358 domain->domain_assemblies = g_slist_append (domain->domain_assemblies, assembly);
1359 mono_domain_assemblies_unlock (domain);
1361 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
1363 MONO_PROFILER_RAISE (assembly_loaded, (&assembly->assembly));
1365 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
1368 #endif /* !DISABLE_REFLECTION_EMIT */
1370 #ifndef DISABLE_REFLECTION_EMIT
1371 static gpointer
1372 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
1374 return CACHE_OBJECT (MonoReflectionAssembly *, assembly, &res->object, NULL);
1377 static MonoReflectionModuleBuilderHandle
1378 register_module (MonoDomain *domain, MonoReflectionModuleBuilderHandle res, MonoDynamicImage *module)
1380 return CACHE_OBJECT_HANDLE (MonoReflectionModuleBuilderHandle, module, MONO_HANDLE_CAST (MonoObject, res), NULL);
1383 static gboolean
1384 image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
1386 error_init (error);
1387 MonoDomain *domain = MONO_HANDLE_DOMAIN (moduleb);
1388 MonoDynamicImage *image = MONO_HANDLE_GETVAL (moduleb, dynamic_image);
1389 MonoReflectionAssemblyBuilderHandle ab = MONO_HANDLE_NEW (MonoReflectionAssemblyBuilder, NULL);
1390 MONO_HANDLE_GET (ab, moduleb, assemblyb);
1391 if (!image) {
1393 * FIXME: we already created an image in mono_reflection_dynimage_basic_init (), but
1394 * we don't know which module it belongs to, since that is only
1395 * determined at assembly save time.
1397 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
1398 MonoStringHandle abname = MONO_HANDLE_NEW_GET (MonoString, ab, name);
1399 char *name = mono_string_handle_to_utf8 (abname, error);
1400 return_val_if_nok (error, FALSE);
1401 MonoStringHandle modfqname = MONO_HANDLE_NEW_GET (MonoString, MONO_HANDLE_CAST (MonoReflectionModule, moduleb), fqname);
1402 char *fqname = mono_string_handle_to_utf8 (modfqname, error);
1403 if (!is_ok (error)) {
1404 g_free (name);
1405 return FALSE;
1407 MonoDynamicAssembly *dynamic_assembly = MONO_HANDLE_GETVAL (ab, dynamic_assembly);
1408 image = mono_dynamic_image_create (dynamic_assembly, name, fqname);
1410 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionModule, moduleb), image, MonoImage*, &image->image);
1411 MONO_HANDLE_SETVAL (moduleb, dynamic_image, MonoDynamicImage*, image);
1412 register_module (domain, moduleb, image);
1414 /* register the module with the assembly */
1415 MonoImage *ass = dynamic_assembly->assembly.image;
1416 int module_count = ass->module_count;
1417 MonoImage **new_modules = g_new0 (MonoImage *, module_count + 1);
1419 if (ass->modules)
1420 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
1421 new_modules [module_count] = &image->image;
1422 mono_image_addref (&image->image);
1424 g_free (ass->modules);
1425 ass->modules = new_modules;
1426 ass->module_count ++;
1428 return TRUE;
1431 static gboolean
1432 mono_image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
1434 error_init (error);
1435 return image_module_basic_init (moduleb, error);
1438 #endif
1440 static gboolean
1441 is_corlib_type (MonoClass *klass)
1443 return klass->image == mono_defaults.corlib;
1446 #define check_corlib_type_cached(_class, _namespace, _name) do { \
1447 static MonoClass *cached_class; \
1448 if (cached_class) \
1449 return cached_class == _class; \
1450 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
1451 cached_class = _class; \
1452 return TRUE; \
1454 return FALSE; \
1455 } while (0) \
1458 MonoType*
1459 mono_type_array_get_and_resolve (MonoArrayHandle array, int idx, MonoError *error)
1461 HANDLE_FUNCTION_ENTER();
1462 error_init (error);
1463 MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1464 MONO_HANDLE_ARRAY_GETREF (t, array, idx);
1465 MonoType *result = mono_reflection_type_handle_mono_type (t, error);
1466 HANDLE_FUNCTION_RETURN_VAL (result);
1470 #ifndef DISABLE_REFLECTION_EMIT
1471 static gboolean
1472 is_sre_array (MonoClass *klass)
1474 check_corlib_type_cached (klass, "System.Reflection.Emit", "ArrayType");
1477 static gboolean
1478 is_sre_byref (MonoClass *klass)
1480 check_corlib_type_cached (klass, "System.Reflection.Emit", "ByRefType");
1483 static gboolean
1484 is_sre_pointer (MonoClass *klass)
1486 check_corlib_type_cached (klass, "System.Reflection.Emit", "PointerType");
1489 static gboolean
1490 is_sre_generic_instance (MonoClass *klass)
1492 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilderInstantiation");
1495 static gboolean
1496 is_sre_type_builder (MonoClass *klass)
1498 check_corlib_type_cached (klass, "System.Reflection.Emit", "TypeBuilder");
1501 static gboolean
1502 is_sre_method_builder (MonoClass *klass)
1504 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodBuilder");
1507 gboolean
1508 mono_is_sre_ctor_builder (MonoClass *klass)
1510 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorBuilder");
1513 static gboolean
1514 is_sre_field_builder (MonoClass *klass)
1516 check_corlib_type_cached (klass, "System.Reflection.Emit", "FieldBuilder");
1519 static gboolean
1520 is_sre_gparam_builder (MonoClass *klass)
1522 check_corlib_type_cached (klass, "System.Reflection.Emit", "GenericTypeParameterBuilder");
1525 static gboolean
1526 is_sre_enum_builder (MonoClass *klass)
1528 check_corlib_type_cached (klass, "System.Reflection.Emit", "EnumBuilder");
1531 gboolean
1532 mono_is_sre_method_on_tb_inst (MonoClass *klass)
1534 check_corlib_type_cached (klass, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
1537 gboolean
1538 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
1540 check_corlib_type_cached (klass, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
1543 static MonoReflectionTypeHandle
1544 mono_reflection_type_get_underlying_system_type (MonoReflectionTypeHandle t, MonoError *error)
1546 static MonoMethod *method_get_underlying_system_type = NULL;
1547 HANDLE_FUNCTION_ENTER ();
1549 error_init (error);
1551 if (!method_get_underlying_system_type)
1552 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
1554 MonoReflectionTypeHandle rt = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1556 MonoMethod *usertype_method = mono_object_handle_get_virtual_method (MONO_HANDLE_CAST (MonoObject, t), method_get_underlying_system_type, error);
1557 goto_if_nok (error, leave);
1559 MONO_HANDLE_ASSIGN (rt, MONO_HANDLE_NEW (MonoReflectionType, mono_runtime_invoke_checked (usertype_method, MONO_HANDLE_RAW (t), NULL, error)));
1561 leave:
1562 HANDLE_FUNCTION_RETURN_REF (MonoReflectionType, rt);
1565 MonoType*
1566 mono_reflection_type_get_handle (MonoReflectionType* ref_raw, MonoError *error)
1568 HANDLE_FUNCTION_ENTER ();
1569 error_init (error);
1570 MONO_HANDLE_DCL (MonoReflectionType, ref);
1571 MonoType *result = mono_reflection_type_handle_mono_type (ref, error);
1572 HANDLE_FUNCTION_RETURN_VAL (result);
1575 static MonoType*
1576 reflection_instance_handle_mono_type (MonoReflectionGenericClassHandle ref_gclass, MonoError *error)
1578 HANDLE_FUNCTION_ENTER ();
1579 MonoType *result = NULL;
1580 MonoType **types = NULL;
1582 MonoArrayHandle typeargs = MONO_HANDLE_NEW_GET (MonoArray, ref_gclass, type_arguments);
1583 int count = mono_array_handle_length (typeargs);
1584 types = g_new0 (MonoType*, count);
1585 MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
1586 for (int i = 0; i < count; ++i) {
1587 MONO_HANDLE_ARRAY_GETREF (t, typeargs, i);
1588 types [i] = mono_reflection_type_handle_mono_type (t, error);
1589 if (!types[i] || !is_ok (error)) {
1590 goto leave;
1593 /* Need to resolve the generic_type in order for it to create its generic context. */
1594 MonoReflectionTypeHandle ref_gtd = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_gclass, generic_type);
1595 MonoType *gtd = mono_reflection_type_handle_mono_type (ref_gtd, error);
1596 goto_if_nok (error, leave);
1597 MonoClass *gtd_klass = mono_class_from_mono_type (gtd);
1598 if (is_sre_type_builder (mono_handle_class (ref_gtd))) {
1599 reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_gtd), error);
1600 goto_if_nok (error, leave);
1602 g_assert (count == 0 || mono_class_is_gtd (gtd_klass));
1603 result = mono_reflection_bind_generic_parameters (ref_gtd, count, types, error);
1604 goto_if_nok (error, leave);
1605 g_assert (result);
1606 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_gclass), type, MonoType*, result);
1607 leave:
1608 g_free (types);
1609 HANDLE_FUNCTION_RETURN_VAL (result);
1612 static MonoType*
1613 reflection_param_handle_mono_type (MonoReflectionGenericParamHandle ref_gparam, MonoError *error)
1615 HANDLE_FUNCTION_ENTER ();
1616 error_init (error);
1617 MonoType *result = NULL;
1620 MonoReflectionTypeBuilderHandle ref_tbuilder = MONO_HANDLE_NEW_GET (MonoReflectionTypeBuilder, ref_gparam, tbuilder);
1621 MonoReflectionModuleBuilderHandle ref_module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tbuilder, module);
1622 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
1623 MonoImage *image = &dynamic_image->image;
1625 MonoGenericParamFull *param = mono_image_new0 (image, MonoGenericParamFull, 1);
1627 MonoStringHandle ref_name = MONO_HANDLE_NEW_GET (MonoString, ref_gparam, name);
1628 param->info.name = mono_string_to_utf8_image (image, ref_name, error);
1629 mono_error_assert_ok (error);
1630 param->param.num = MONO_HANDLE_GETVAL (ref_gparam, index);
1632 MonoReflectionMethodBuilderHandle ref_mbuilder = MONO_HANDLE_NEW_GET (MonoReflectionMethodBuilder, ref_gparam, mbuilder);
1633 if (!MONO_HANDLE_IS_NULL (ref_mbuilder)) {
1634 MonoGenericContainer *generic_container = MONO_HANDLE_GETVAL (ref_mbuilder, generic_container);
1635 if (!generic_container) {
1636 generic_container = (MonoGenericContainer *)mono_image_alloc0 (image, sizeof (MonoGenericContainer));
1637 generic_container->is_method = TRUE;
1639 * Cannot set owner.method, since the MonoMethod is not created yet.
1640 * Set the image field instead, so type_in_image () works.
1642 generic_container->is_anonymous = TRUE;
1643 generic_container->owner.image = image;
1644 MONO_HANDLE_SETVAL (ref_mbuilder, generic_container, MonoGenericContainer*, generic_container);
1646 param->param.owner = generic_container;
1647 } else {
1648 MonoType *type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, ref_tbuilder), error);
1649 goto_if_nok (error, leave);
1650 MonoClass *owner = mono_class_from_mono_type (type);
1651 g_assert (mono_class_is_gtd (owner));
1652 param->param.owner = mono_class_get_generic_container (owner);
1655 MonoClass *pklass = mono_class_from_generic_parameter_internal ((MonoGenericParam *) param);
1657 result = &pklass->byval_arg;
1659 mono_class_set_ref_info (pklass, MONO_HANDLE_CAST (MonoObject, ref_gparam));
1660 mono_image_append_class_to_reflection_info_set (pklass);
1662 MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_gparam), type, MonoType*, result);
1664 leave:
1665 HANDLE_FUNCTION_RETURN_VAL (result);
1668 static MonoType*
1669 mono_type_array_get_and_resolve_raw (MonoArray* array_raw, int idx, MonoError *error)
1671 HANDLE_FUNCTION_ENTER(); /* FIXME callers of mono_type_array_get_and_resolve_raw should use handles */
1672 error_init (error);
1673 MONO_HANDLE_DCL (MonoArray, array);
1674 MonoType *result = mono_type_array_get_and_resolve (array, idx, error);
1675 HANDLE_FUNCTION_RETURN_VAL (result);
1678 MonoType*
1679 mono_reflection_type_handle_mono_type (MonoReflectionTypeHandle ref, MonoError *error)
1681 HANDLE_FUNCTION_ENTER ();
1682 error_init (error);
1684 MonoType* result = NULL;
1686 g_assert (ref);
1687 if (MONO_HANDLE_IS_NULL (ref))
1688 goto leave;
1689 MonoType *t = MONO_HANDLE_GETVAL (ref, type);
1690 if (t) {
1691 result = t;
1692 goto leave;
1695 if (mono_reflection_is_usertype (ref)) {
1696 MONO_HANDLE_ASSIGN (ref, mono_reflection_type_get_underlying_system_type (ref, error));
1697 if (!is_ok (error) || MONO_HANDLE_IS_NULL (ref) || mono_reflection_is_usertype (ref))
1698 goto leave;
1699 t = MONO_HANDLE_GETVAL (ref, type);
1700 if (t) {
1701 result = t;
1702 goto leave;
1706 MonoClass *klass = mono_handle_class (ref);
1708 if (is_sre_array (klass)) {
1709 MonoReflectionArrayTypeHandle sre_array = MONO_HANDLE_CAST (MonoReflectionArrayType, ref);
1710 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_array, element_type);
1711 MonoType *base = mono_reflection_type_handle_mono_type (ref_element, error);
1712 goto_if_nok (error, leave);
1713 g_assert (base);
1714 gint32 rank = MONO_HANDLE_GETVAL (sre_array, rank);
1715 MonoClass *eclass = mono_class_from_mono_type (base);
1716 result = mono_image_new0 (eclass->image, MonoType, 1);
1717 if (rank == 0) {
1718 result->type = MONO_TYPE_SZARRAY;
1719 result->data.klass = eclass;
1720 } else {
1721 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (eclass->image, sizeof (MonoArrayType));
1722 result->type = MONO_TYPE_ARRAY;
1723 result->data.array = at;
1724 at->eklass = eclass;
1725 at->rank = rank;
1727 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1728 } else if (is_sre_byref (klass)) {
1729 MonoReflectionDerivedTypeHandle sre_byref = MONO_HANDLE_CAST (MonoReflectionDerivedType, ref);
1730 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_byref, element_type);
1731 MonoType *base = mono_reflection_type_handle_mono_type (ref_element, error);
1732 goto_if_nok (error, leave);
1733 g_assert (base);
1734 result = &mono_class_from_mono_type (base)->this_arg;
1735 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1736 } else if (is_sre_pointer (klass)) {
1737 MonoReflectionDerivedTypeHandle sre_pointer = MONO_HANDLE_CAST (MonoReflectionDerivedType, ref);
1738 MonoReflectionTypeHandle ref_element = MONO_HANDLE_NEW_GET (MonoReflectionType, sre_pointer, element_type);
1739 MonoType *base = mono_reflection_type_handle_mono_type (ref_element, error);
1740 goto_if_nok (error, leave);
1741 g_assert (base);
1742 result = &mono_ptr_class_get (base)->byval_arg;
1743 MONO_HANDLE_SETVAL (ref, type, MonoType*, result);
1744 } else if (is_sre_generic_instance (klass)) {
1745 result = reflection_instance_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionGenericClass, ref), error);
1746 } else if (is_sre_gparam_builder (klass)) {
1747 result = reflection_param_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionGenericParam, ref), error);
1748 } else if (is_sre_enum_builder (klass)) {
1749 MonoReflectionEnumBuilderHandle ref_ebuilder = MONO_HANDLE_CAST (MonoReflectionEnumBuilder, ref);
1751 MonoReflectionTypeHandle ref_tb = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_ebuilder, tb);
1752 result = mono_reflection_type_handle_mono_type (ref_tb, error);
1753 } else if (is_sre_type_builder (klass)) {
1754 MonoReflectionTypeBuilderHandle ref_tb = MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref);
1756 /* This happens when a finished type references an unfinished one. Have to create the minimal type */
1757 reflection_setup_internal_class (ref_tb, error);
1758 mono_error_assert_ok (error);
1759 result = MONO_HANDLE_GETVAL (ref, type);
1760 } else {
1761 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
1763 leave:
1764 HANDLE_FUNCTION_RETURN_VAL (result);
1768 * LOCKING: Assumes the loader lock is held.
1770 static MonoMethodSignature*
1771 parameters_to_signature (MonoImage *image, MonoArrayHandle parameters, MonoError *error) {
1772 MonoMethodSignature *sig;
1773 int count, i;
1775 error_init (error);
1777 count = MONO_HANDLE_IS_NULL (parameters) ? 0 : mono_array_handle_length (parameters);
1779 sig = (MonoMethodSignature *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
1780 sig->param_count = count;
1781 sig->sentinelpos = -1; /* FIXME */
1782 for (i = 0; i < count; ++i) {
1783 sig->params [i] = mono_type_array_get_and_resolve (parameters, i, error);
1784 if (!is_ok (error)) {
1785 image_g_free (image, sig);
1786 return NULL;
1789 return sig;
1793 * LOCKING: Assumes the loader lock is held.
1795 static MonoMethodSignature*
1796 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilderHandle ctor, MonoError *error) {
1797 MonoMethodSignature *sig;
1799 error_init (error);
1801 sig = parameters_to_signature (image, MONO_HANDLE_NEW_GET (MonoArray, ctor, parameters), error);
1802 return_val_if_nok (error, NULL);
1803 sig->hasthis = MONO_HANDLE_GETVAL (ctor, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1804 sig->ret = &mono_defaults.void_class->byval_arg;
1805 return sig;
1808 static MonoMethodSignature*
1809 ctor_builder_to_signature_raw (MonoImage *image, MonoReflectionCtorBuilder* ctor_raw, MonoError *error) {
1810 HANDLE_FUNCTION_ENTER();
1811 MONO_HANDLE_DCL (MonoReflectionCtorBuilder, ctor);
1812 MonoMethodSignature *sig = ctor_builder_to_signature (image, ctor, error);
1813 HANDLE_FUNCTION_RETURN_VAL (sig);
1816 * LOCKING: Assumes the loader lock is held.
1818 static MonoMethodSignature*
1819 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilderHandle method, MonoError *error) {
1820 MonoMethodSignature *sig;
1822 error_init (error);
1824 sig = parameters_to_signature (image, MONO_HANDLE_NEW_GET(MonoArray, method, parameters), error);
1825 return_val_if_nok (error, NULL);
1826 sig->hasthis = MONO_HANDLE_GETVAL (method, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1827 MonoReflectionTypeHandle rtype = MONO_HANDLE_NEW_GET (MonoReflectionType, method, rtype);
1828 if (!MONO_HANDLE_IS_NULL (rtype)) {
1829 sig->ret = mono_reflection_type_handle_mono_type (rtype, error);
1830 if (!is_ok (error)) {
1831 image_g_free (image, sig);
1832 return NULL;
1834 } else {
1835 sig->ret = &mono_defaults.void_class->byval_arg;
1837 MonoArrayHandle generic_params = MONO_HANDLE_NEW_GET (MonoArray, method, generic_params);
1838 sig->generic_param_count = MONO_HANDLE_IS_NULL (generic_params) ? 0 : mono_array_handle_length (generic_params);
1839 return sig;
1842 static MonoMethodSignature*
1843 dynamic_method_to_signature (MonoReflectionDynamicMethodHandle method, MonoError *error) {
1844 HANDLE_FUNCTION_ENTER ();
1845 MonoMethodSignature *sig = NULL;
1847 error_init (error);
1849 sig = parameters_to_signature (NULL, MONO_HANDLE_NEW_GET (MonoArray, method, parameters), error);
1850 goto_if_nok (error, leave);
1851 sig->hasthis = MONO_HANDLE_GETVAL (method, attrs) & METHOD_ATTRIBUTE_STATIC? 0: 1;
1852 MonoReflectionTypeHandle rtype = MONO_HANDLE_NEW_GET (MonoReflectionType, method, rtype);
1853 if (!MONO_HANDLE_IS_NULL (rtype)) {
1854 sig->ret = mono_reflection_type_handle_mono_type (rtype, error);
1855 if (!is_ok (error)) {
1856 g_free (sig);
1857 sig = NULL;
1858 goto leave;
1860 } else {
1861 sig->ret = &mono_defaults.void_class->byval_arg;
1863 sig->generic_param_count = 0;
1864 leave:
1865 HANDLE_FUNCTION_RETURN_VAL (sig);
1868 static void
1869 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type, MonoError *error)
1871 error_init (error);
1872 MonoClass *klass = mono_object_class (prop);
1873 if (strcmp (klass->name, "PropertyBuilder") == 0) {
1874 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
1875 *name = mono_string_to_utf8_checked (pb->name, error);
1876 return_if_nok (error);
1877 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type, error);
1878 } else {
1879 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
1880 *name = g_strdup (p->property->name);
1881 if (p->property->get)
1882 *type = mono_method_signature (p->property->get)->ret;
1883 else
1884 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
1888 static void
1889 get_field_name_and_type (MonoObject *field, char **name, MonoType **type, MonoError *error)
1891 error_init (error);
1892 MonoClass *klass = mono_object_class (field);
1893 if (strcmp (klass->name, "FieldBuilder") == 0) {
1894 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
1895 *name = mono_string_to_utf8_checked (fb->name, error);
1896 return_if_nok (error);
1897 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
1898 } else {
1899 MonoReflectionField *f = (MonoReflectionField *)field;
1900 *name = g_strdup (mono_field_get_name (f->field));
1901 *type = f->field->type;
1905 #else /* DISABLE_REFLECTION_EMIT */
1907 static gboolean
1908 is_sre_type_builder (MonoClass *klass)
1910 return FALSE;
1913 static gboolean
1914 is_sre_generic_instance (MonoClass *klass)
1916 return FALSE;
1919 gboolean
1920 mono_is_sre_ctor_builder (MonoClass *klass)
1922 return FALSE;
1925 gboolean
1926 mono_is_sre_method_on_tb_inst (MonoClass *klass)
1928 return FALSE;
1931 gboolean
1932 mono_is_sre_ctor_on_tb_inst (MonoClass *klass)
1934 return FALSE;
1937 #endif /* !DISABLE_REFLECTION_EMIT */
1940 static gboolean
1941 is_sr_mono_field (MonoClass *klass)
1943 check_corlib_type_cached (klass, "System.Reflection", "MonoField");
1946 gboolean
1947 mono_is_sr_mono_property (MonoClass *klass)
1949 check_corlib_type_cached (klass, "System.Reflection", "MonoProperty");
1952 static gboolean
1953 is_sr_mono_method (MonoClass *klass)
1955 check_corlib_type_cached (klass, "System.Reflection", "MonoMethod");
1958 gboolean
1959 mono_is_sr_mono_cmethod (MonoClass *klass)
1961 check_corlib_type_cached (klass, "System.Reflection", "MonoCMethod");
1964 gboolean
1965 mono_class_is_reflection_method_or_constructor (MonoClass *klass)
1967 return is_sr_mono_method (klass) || mono_is_sr_mono_cmethod (klass);
1970 gboolean
1971 mono_is_sre_type_builder (MonoClass *klass)
1973 return is_sre_type_builder (klass);
1976 gboolean
1977 mono_is_sre_generic_instance (MonoClass *klass)
1979 return is_sre_generic_instance (klass);
1985 * encode_cattr_value:
1986 * Encode a value in a custom attribute stream of bytes.
1987 * The value to encode is either supplied as an object in argument val
1988 * (valuetypes are boxed), or as a pointer to the data in the
1989 * argument argval.
1990 * @type represents the type of the value
1991 * @buffer is the start of the buffer
1992 * @p the current position in the buffer
1993 * @buflen contains the size of the buffer and is used to return the new buffer size
1994 * if this needs to be realloced.
1995 * @retbuffer and @retp return the start and the position of the buffer
1996 * @error set on error.
1998 static void
1999 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval, MonoError *error)
2001 MonoTypeEnum simple_type;
2003 error_init (error);
2004 if ((p-buffer) + 10 >= *buflen) {
2005 char *newbuf;
2006 *buflen *= 2;
2007 newbuf = (char *)g_realloc (buffer, *buflen);
2008 p = newbuf + (p-buffer);
2009 buffer = newbuf;
2011 if (!argval)
2012 argval = ((char*)arg + sizeof (MonoObject));
2013 simple_type = type->type;
2014 handle_enum:
2015 switch (simple_type) {
2016 case MONO_TYPE_BOOLEAN:
2017 case MONO_TYPE_U1:
2018 case MONO_TYPE_I1:
2019 *p++ = *argval;
2020 break;
2021 case MONO_TYPE_CHAR:
2022 case MONO_TYPE_U2:
2023 case MONO_TYPE_I2:
2024 swap_with_size (p, argval, 2, 1);
2025 p += 2;
2026 break;
2027 case MONO_TYPE_U4:
2028 case MONO_TYPE_I4:
2029 case MONO_TYPE_R4:
2030 swap_with_size (p, argval, 4, 1);
2031 p += 4;
2032 break;
2033 case MONO_TYPE_R8:
2034 swap_with_size (p, argval, 8, 1);
2035 p += 8;
2036 break;
2037 case MONO_TYPE_U8:
2038 case MONO_TYPE_I8:
2039 swap_with_size (p, argval, 8, 1);
2040 p += 8;
2041 break;
2042 case MONO_TYPE_VALUETYPE:
2043 if (type->data.klass->enumtype) {
2044 simple_type = mono_class_enum_basetype (type->data.klass)->type;
2045 goto handle_enum;
2046 } else {
2047 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
2049 break;
2050 case MONO_TYPE_STRING: {
2051 char *str;
2052 guint32 slen;
2053 if (!arg) {
2054 *p++ = 0xFF;
2055 break;
2057 str = mono_string_to_utf8_checked ((MonoString*)arg, error);
2058 return_if_nok (error);
2059 slen = strlen (str);
2060 if ((p-buffer) + 10 + slen >= *buflen) {
2061 char *newbuf;
2062 *buflen *= 2;
2063 *buflen += slen;
2064 newbuf = (char *)g_realloc (buffer, *buflen);
2065 p = newbuf + (p-buffer);
2066 buffer = newbuf;
2068 mono_metadata_encode_value (slen, p, &p);
2069 memcpy (p, str, slen);
2070 p += slen;
2071 g_free (str);
2072 break;
2074 case MONO_TYPE_CLASS: {
2075 char *str;
2076 guint32 slen;
2077 MonoType *arg_type;
2078 if (!arg) {
2079 *p++ = 0xFF;
2080 break;
2082 handle_type:
2083 arg_type = mono_reflection_type_get_handle ((MonoReflectionType*)arg, error);
2084 return_if_nok (error);
2086 str = type_get_qualified_name (arg_type, NULL);
2087 slen = strlen (str);
2088 if ((p-buffer) + 10 + slen >= *buflen) {
2089 char *newbuf;
2090 *buflen *= 2;
2091 *buflen += slen;
2092 newbuf = (char *)g_realloc (buffer, *buflen);
2093 p = newbuf + (p-buffer);
2094 buffer = newbuf;
2096 mono_metadata_encode_value (slen, p, &p);
2097 memcpy (p, str, slen);
2098 p += slen;
2099 g_free (str);
2100 break;
2102 case MONO_TYPE_SZARRAY: {
2103 int len, i;
2104 MonoClass *eclass, *arg_eclass;
2106 if (!arg) {
2107 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
2108 break;
2110 len = mono_array_length ((MonoArray*)arg);
2111 *p++ = len & 0xff;
2112 *p++ = (len >> 8) & 0xff;
2113 *p++ = (len >> 16) & 0xff;
2114 *p++ = (len >> 24) & 0xff;
2115 *retp = p;
2116 *retbuffer = buffer;
2117 eclass = type->data.klass;
2118 arg_eclass = mono_object_class (arg)->element_class;
2120 if (!eclass) {
2121 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
2122 eclass = mono_defaults.object_class;
2124 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
2125 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
2126 int elsize = mono_class_array_element_size (arg_eclass);
2127 for (i = 0; i < len; ++i) {
2128 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr, error);
2129 return_if_nok (error);
2130 elptr += elsize;
2132 } else if (eclass->valuetype && arg_eclass->valuetype) {
2133 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
2134 int elsize = mono_class_array_element_size (eclass);
2135 for (i = 0; i < len; ++i) {
2136 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr, error);
2137 return_if_nok (error);
2138 elptr += elsize;
2140 } else {
2141 for (i = 0; i < len; ++i) {
2142 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL, error);
2143 return_if_nok (error);
2146 break;
2148 case MONO_TYPE_OBJECT: {
2149 MonoClass *klass;
2150 char *str;
2151 guint32 slen;
2154 * The parameter type is 'object' but the type of the actual
2155 * argument is not. So we have to add type information to the blob
2156 * too. This is completely undocumented in the spec.
2159 if (arg == NULL) {
2160 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
2161 *p++ = 0xFF;
2162 break;
2165 klass = mono_object_class (arg);
2167 if (mono_object_isinst_checked (arg, mono_defaults.systemtype_class, error)) {
2168 *p++ = 0x50;
2169 goto handle_type;
2170 } else {
2171 return_if_nok (error);
2174 if (klass->enumtype) {
2175 *p++ = 0x55;
2176 } else if (klass == mono_defaults.string_class) {
2177 simple_type = MONO_TYPE_STRING;
2178 *p++ = 0x0E;
2179 goto handle_enum;
2180 } else if (klass->rank == 1) {
2181 *p++ = 0x1D;
2182 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
2183 /* See Partition II, Appendix B3 */
2184 *p++ = 0x51;
2185 else
2186 *p++ = klass->element_class->byval_arg.type;
2187 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL, error);
2188 return_if_nok (error);
2189 break;
2190 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
2191 *p++ = simple_type = klass->byval_arg.type;
2192 goto handle_enum;
2193 } else {
2194 g_error ("unhandled type in custom attr");
2196 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
2197 slen = strlen (str);
2198 if ((p-buffer) + 10 + slen >= *buflen) {
2199 char *newbuf;
2200 *buflen *= 2;
2201 *buflen += slen;
2202 newbuf = (char *)g_realloc (buffer, *buflen);
2203 p = newbuf + (p-buffer);
2204 buffer = newbuf;
2206 mono_metadata_encode_value (slen, p, &p);
2207 memcpy (p, str, slen);
2208 p += slen;
2209 g_free (str);
2210 simple_type = mono_class_enum_basetype (klass)->type;
2211 goto handle_enum;
2213 default:
2214 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
2216 *retp = p;
2217 *retbuffer = buffer;
2220 static void
2221 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
2223 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2224 char *str = type_get_qualified_name (type, NULL);
2225 int slen = strlen (str);
2227 *p++ = 0x55;
2229 * This seems to be optional...
2230 * *p++ = 0x80;
2232 mono_metadata_encode_value (slen, p, &p);
2233 memcpy (p, str, slen);
2234 p += slen;
2235 g_free (str);
2236 } else if (type->type == MONO_TYPE_OBJECT) {
2237 *p++ = 0x51;
2238 } else if (type->type == MONO_TYPE_CLASS) {
2239 /* it should be a type: encode_cattr_value () has the check */
2240 *p++ = 0x50;
2241 } else {
2242 mono_metadata_encode_value (type->type, p, &p);
2243 if (type->type == MONO_TYPE_SZARRAY)
2244 /* See the examples in Partition VI, Annex B */
2245 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
2248 *retp = p;
2251 #ifndef DISABLE_REFLECTION_EMIT
2252 static void
2253 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value, MonoError *error)
2255 int len;
2257 error_init (error);
2259 /* Preallocate a large enough buffer */
2260 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
2261 char *str = type_get_qualified_name (type, NULL);
2262 len = strlen (str);
2263 g_free (str);
2264 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
2265 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
2266 len = strlen (str);
2267 g_free (str);
2268 } else {
2269 len = 0;
2271 len += strlen (name);
2273 if ((p-buffer) + 20 + len >= *buflen) {
2274 char *newbuf;
2275 *buflen *= 2;
2276 *buflen += len;
2277 newbuf = (char *)g_realloc (buffer, *buflen);
2278 p = newbuf + (p-buffer);
2279 buffer = newbuf;
2282 encode_field_or_prop_type (type, p, &p);
2284 len = strlen (name);
2285 mono_metadata_encode_value (len, p, &p);
2286 memcpy (p, name, len);
2287 p += len;
2288 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL, error);
2289 return_if_nok (error);
2290 *retp = p;
2291 *retbuffer = buffer;
2295 * mono_reflection_get_custom_attrs_blob:
2296 * \param ctor custom attribute constructor
2297 * \param ctorArgs arguments o the constructor
2298 * \param properties
2299 * \param propValues
2300 * \param fields
2301 * \param fieldValues
2302 * Creates the blob of data that needs to be saved in the metadata and that represents
2303 * the custom attributed described by \p ctor, \p ctorArgs etc.
2304 * \returns a \c Byte array representing the blob of data.
2306 MonoArray*
2307 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
2309 MonoError error;
2310 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
2311 mono_error_cleanup (&error);
2312 return result;
2316 * mono_reflection_get_custom_attrs_blob_checked:
2317 * \param ctor custom attribute constructor
2318 * \param ctorArgs arguments o the constructor
2319 * \param properties
2320 * \param propValues
2321 * \param fields
2322 * \param fieldValues
2323 * \param error set on error
2324 * Creates the blob of data that needs to be saved in the metadata and that represents
2325 * the custom attributed described by \p ctor, \p ctorArgs etc.
2326 * \returns a \c Byte array representing the blob of data. On failure returns NULL and sets \p error.
2328 MonoArray*
2329 mono_reflection_get_custom_attrs_blob_checked (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues, MonoError *error)
2331 MonoArray *result = NULL;
2332 MonoMethodSignature *sig;
2333 MonoObject *arg;
2334 char *buffer, *p;
2335 guint32 buflen, i;
2337 error_init (error);
2339 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
2340 /* sig is freed later so allocate it in the heap */
2341 sig = ctor_builder_to_signature_raw (NULL, (MonoReflectionCtorBuilder*)ctor, error); /* FIXME use handles */
2342 if (!is_ok (error)) {
2343 g_free (sig);
2344 return NULL;
2346 } else {
2347 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
2350 g_assert (mono_array_length (ctorArgs) == sig->param_count);
2351 buflen = 256;
2352 p = buffer = (char *)g_malloc (buflen);
2353 /* write the prolog */
2354 *p++ = 1;
2355 *p++ = 0;
2356 for (i = 0; i < sig->param_count; ++i) {
2357 arg = mono_array_get (ctorArgs, MonoObject*, i);
2358 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL, error);
2359 goto_if_nok (error, leave);
2361 i = 0;
2362 if (properties)
2363 i += mono_array_length (properties);
2364 if (fields)
2365 i += mono_array_length (fields);
2366 *p++ = i & 0xff;
2367 *p++ = (i >> 8) & 0xff;
2368 if (properties) {
2369 MonoObject *prop;
2370 for (i = 0; i < mono_array_length (properties); ++i) {
2371 MonoType *ptype;
2372 char *pname;
2374 prop = (MonoObject *)mono_array_get (properties, gpointer, i);
2375 get_prop_name_and_type (prop, &pname, &ptype, error);
2376 goto_if_nok (error, leave);
2377 *p++ = 0x54; /* PROPERTY signature */
2378 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i), error);
2379 g_free (pname);
2380 goto_if_nok (error, leave);
2384 if (fields) {
2385 MonoObject *field;
2386 for (i = 0; i < mono_array_length (fields); ++i) {
2387 MonoType *ftype;
2388 char *fname;
2390 field = (MonoObject *)mono_array_get (fields, gpointer, i);
2391 get_field_name_and_type (field, &fname, &ftype, error);
2392 goto_if_nok (error, leave);
2393 *p++ = 0x53; /* FIELD signature */
2394 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i), error);
2395 g_free (fname);
2396 goto_if_nok (error, leave);
2400 g_assert (p - buffer <= buflen);
2401 buflen = p - buffer;
2402 result = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, buflen, error);
2403 goto_if_nok (error, leave);
2404 p = mono_array_addr (result, char, 0);
2405 memcpy (p, buffer, buflen);
2406 leave:
2407 g_free (buffer);
2408 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
2409 g_free (sig);
2410 return result;
2413 static gboolean
2414 reflection_setup_class_hierarchy (GHashTable *unparented, MonoError *error)
2416 error_init (error);
2418 mono_loader_lock ();
2420 MonoType *parent_type;
2421 MonoType *child_type;
2422 GHashTableIter iter;
2424 g_hash_table_iter_init (&iter, unparented);
2426 while (g_hash_table_iter_next (&iter, (gpointer *) &child_type, (gpointer *) &parent_type)) {
2427 MonoClass *child_class = mono_class_from_mono_type (child_type);
2428 if (parent_type != NULL) {
2429 MonoClass *parent_class = mono_class_from_mono_type (parent_type);
2430 child_class->parent = NULL;
2431 /* fool mono_class_setup_parent */
2432 child_class->supertypes = NULL;
2433 mono_class_setup_parent (child_class, parent_class);
2434 } else if (strcmp (child_class->name, "Object") == 0 && strcmp (child_class->name_space, "System") == 0) {
2435 const char *old_n = child_class->name;
2436 /* trick to get relative numbering right when compiling corlib */
2437 child_class->name = "BuildingObject";
2438 mono_class_setup_parent (child_class, mono_defaults.object_class);
2439 child_class->name = old_n;
2441 mono_class_setup_mono_type (child_class);
2442 mono_class_setup_supertypes (child_class);
2445 mono_loader_unlock ();
2446 return is_ok (error);
2449 static gboolean
2450 reflection_setup_internal_class_internal (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
2452 HANDLE_FUNCTION_ENTER ();
2453 error_init (error);
2455 mono_loader_lock ();
2457 gint32 entering_state = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_tb), state);
2458 if (entering_state != MonoTypeBuilderNew) {
2459 g_assert (MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type));
2460 goto leave;
2463 MONO_HANDLE_SETVAL (ref_tb, state, MonoTypeBuilderState, MonoTypeBuilderEntered);
2464 MonoReflectionModuleBuilderHandle module_ref = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
2465 GHashTable *unparented_classes = MONO_HANDLE_GETVAL(module_ref, unparented_classes);
2467 // If this type is already setup, exit. We'll fix the parenting later
2468 MonoType *type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
2469 if (type)
2470 goto leave;
2472 MonoReflectionModuleBuilderHandle ref_module = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
2473 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (ref_module, dynamic_image);
2475 MonoStringHandle ref_name = MONO_HANDLE_NEW_GET (MonoString, ref_tb, name);
2476 MonoStringHandle ref_nspace = MONO_HANDLE_NEW_GET (MonoString, ref_tb, nspace);
2478 guint32 table_idx = MONO_HANDLE_GETVAL (ref_tb, table_idx);
2480 * The size calculation here warrants some explaining.
2481 * reflection_setup_internal_class is called too early, well before we know whether the type will be a GTD or DEF,
2482 * meaning we need to alloc enough space to morth a def into a gtd.
2484 MonoClass *klass = (MonoClass *)mono_image_alloc0 (&dynamic_image->image, MAX (sizeof (MonoClassDef), sizeof (MonoClassGtd)));
2485 klass->class_kind = MONO_CLASS_DEF;
2487 klass->image = &dynamic_image->image;
2489 klass->inited = 1; /* we lie to the runtime */
2490 klass->name = mono_string_to_utf8_image (klass->image, ref_name, error);
2491 goto_if_nok (error, leave);
2492 klass->name_space = mono_string_to_utf8_image (klass->image, ref_nspace, error);
2493 goto_if_nok (error, leave);
2494 klass->type_token = MONO_TOKEN_TYPE_DEF | table_idx;
2495 mono_class_set_flags (klass, MONO_HANDLE_GETVAL (ref_tb, attrs));
2497 MONO_PROFILER_RAISE (class_loading, (klass));
2499 klass->element_class = klass;
2501 g_assert (!mono_class_has_ref_info (klass));
2502 mono_class_set_ref_info (klass, MONO_HANDLE_CAST (MonoObject, ref_tb));
2504 MonoReflectionTypeHandle ref_nesting_type = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_tb, nesting_type);
2505 /* Put into cache so mono_class_get_checked () will find it.
2506 Skip nested types as those should not be available on the global scope. */
2507 if (MONO_HANDLE_IS_NULL (ref_nesting_type))
2508 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, table_idx);
2511 We must register all types as we cannot rely on the name_cache hashtable since we find the class
2512 by performing a mono_class_get which does the full resolution.
2514 Working around this semantics would require us to write a lot of code for no clear advantage.
2516 mono_image_append_class_to_reflection_info_set (klass);
2518 mono_dynamic_image_register_token (dynamic_image, MONO_TOKEN_TYPE_DEF | table_idx, MONO_HANDLE_CAST (MonoObject, ref_tb), MONO_DYN_IMAGE_TOK_NEW);
2520 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
2521 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
2522 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
2523 klass->instance_size = sizeof (MonoObject);
2524 klass->size_inited = 1;
2525 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
2528 mono_class_setup_mono_type (klass);
2531 * FIXME: handle interfaces.
2533 MonoReflectionTypeHandle ref_tb_type = MONO_HANDLE_CAST (MonoReflectionType, ref_tb);
2534 MONO_HANDLE_SETVAL (ref_tb_type, type, MonoType*, &klass->byval_arg);
2535 MONO_HANDLE_SETVAL (ref_tb, state, gint32, MonoTypeBuilderFinished);
2537 reflection_init_generic_class (ref_tb, error);
2538 goto_if_nok (error, leave);
2540 // Do here so that the search inside of the parent can see the above type that's been set.
2541 MonoReflectionTypeHandle ref_parent = MONO_HANDLE_NEW_GET (MonoReflectionType, ref_tb, parent);
2542 MonoType *parent_type = NULL;
2543 if (!MONO_HANDLE_IS_NULL (ref_parent)) {
2544 MonoClass *parent_klass = mono_handle_class (ref_parent);
2545 gboolean recursive_init = TRUE;
2547 if (is_sre_type_builder (parent_klass)) {
2548 MonoTypeBuilderState parent_state = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_parent), state);
2550 if (parent_state != MonoTypeBuilderNew) {
2551 // Initialize types reachable from parent recursively
2552 // We'll fix the type hierarchy later
2553 recursive_init = FALSE;
2557 if (recursive_init) {
2558 // If we haven't encountered a cycle, force the creation of ref_parent's type
2559 mono_reflection_type_handle_mono_type (ref_parent, error);
2560 goto_if_nok (error, leave);
2563 parent_type = MONO_HANDLE_GETVAL (ref_parent, type);
2565 // If we failed to create the parent, fail the child
2566 if (!parent_type)
2567 goto leave;
2570 // Push the child type and parent type to process later
2571 // Note: parent_type may be null.
2572 g_assert (!g_hash_table_lookup (unparented_classes, &klass->byval_arg));
2573 g_hash_table_insert (unparented_classes, &klass->byval_arg, parent_type);
2575 if (!MONO_HANDLE_IS_NULL (ref_nesting_type)) {
2576 if (!reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, ref_nesting_type), error))
2577 goto leave;
2579 MonoType *nesting_type = mono_reflection_type_handle_mono_type (ref_nesting_type, error);
2580 goto_if_nok (error, leave);
2581 klass->nested_in = mono_class_from_mono_type (nesting_type);
2584 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
2586 MONO_PROFILER_RAISE (class_loaded, (klass));
2588 leave:
2589 mono_loader_unlock ();
2590 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2594 * reflection_init_generic_class:
2595 * @tb: a TypeBuilder object
2596 * @error: set on error
2598 * Creates the generic class after all generic parameters have been added.
2599 * On success returns TRUE, on failure returns FALSE and sets @error.
2601 * This assumes that reflection_setup_internal_class has already set up
2602 * ref_tb
2604 static gboolean
2605 reflection_init_generic_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
2607 HANDLE_FUNCTION_ENTER ();
2609 error_init (error);
2611 MonoTypeBuilderState ref_state = MONO_HANDLE_GETVAL (ref_tb, state);
2612 g_assert (ref_state == MonoTypeBuilderFinished);
2614 MonoType *type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
2615 MonoClass *klass = mono_class_from_mono_type (type);
2617 MonoArrayHandle generic_params = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, generic_params);
2618 int count = MONO_HANDLE_IS_NULL (generic_params) ? 0 : mono_array_handle_length (generic_params);
2620 if (count == 0)
2621 goto leave;
2623 if (mono_class_try_get_generic_container (klass) != NULL)
2624 goto leave; /* already setup */
2626 MonoGenericContainer *generic_container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
2628 generic_container->owner.klass = klass;
2629 generic_container->type_argc = count;
2630 generic_container->type_params = (MonoGenericParamFull *)mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
2632 klass->class_kind = MONO_CLASS_GTD;
2633 mono_class_set_generic_container (klass, generic_container);
2636 MonoReflectionGenericParamHandle ref_gparam = MONO_HANDLE_NEW (MonoReflectionGenericParam, NULL);
2637 for (int i = 0; i < count; i++) {
2638 MONO_HANDLE_ARRAY_GETREF (ref_gparam, generic_params, i);
2639 MonoType *param_type = mono_reflection_type_handle_mono_type (MONO_HANDLE_CAST (MonoReflectionType, ref_gparam), error);
2640 goto_if_nok (error, leave);
2641 MonoGenericParamFull *param = (MonoGenericParamFull *) param_type->data.generic_param;
2642 generic_container->type_params [i] = *param;
2643 /*Make sure we are a diferent type instance */
2644 generic_container->type_params [i].param.owner = generic_container;
2645 generic_container->type_params [i].info.pklass = NULL;
2646 generic_container->type_params [i].info.flags = MONO_HANDLE_GETVAL (ref_gparam, attrs);
2648 g_assert (generic_container->type_params [i].param.owner);
2651 generic_container->context.class_inst = mono_get_shared_generic_inst (generic_container);
2652 MonoGenericContext* context = &generic_container->context;
2653 MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
2654 canonical_inst->type = MONO_TYPE_GENERICINST;
2655 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
2657 leave:
2658 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
2661 static MonoMarshalSpec*
2662 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
2663 MonoReflectionMarshal *minfo, MonoError *error)
2665 MonoMarshalSpec *res;
2667 error_init (error);
2669 res = image_g_new0 (image, MonoMarshalSpec, 1);
2670 res->native = (MonoMarshalNative)minfo->type;
2672 switch (minfo->type) {
2673 case MONO_NATIVE_LPARRAY:
2674 res->data.array_data.elem_type = (MonoMarshalNative)minfo->eltype;
2675 if (minfo->has_size) {
2676 res->data.array_data.param_num = minfo->param_num;
2677 res->data.array_data.num_elem = minfo->count;
2678 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
2680 else {
2681 res->data.array_data.param_num = -1;
2682 res->data.array_data.num_elem = -1;
2683 res->data.array_data.elem_mult = -1;
2685 break;
2687 case MONO_NATIVE_BYVALTSTR:
2688 case MONO_NATIVE_BYVALARRAY:
2689 res->data.array_data.num_elem = minfo->count;
2690 break;
2692 case MONO_NATIVE_CUSTOM:
2693 if (minfo->marshaltyperef) {
2694 MonoType *marshaltyperef = mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef, error);
2695 if (!is_ok (error)) {
2696 image_g_free (image, res);
2697 return NULL;
2699 res->data.custom_data.custom_name =
2700 type_get_fully_qualified_name (marshaltyperef);
2702 if (minfo->mcookie) {
2703 res->data.custom_data.cookie = mono_string_to_utf8_checked (minfo->mcookie, error);
2704 if (!is_ok (error)) {
2705 image_g_free (image, res);
2706 return NULL;
2709 break;
2711 default:
2712 break;
2715 return res;
2717 #endif /* !DISABLE_REFLECTION_EMIT */
2719 MonoReflectionMarshalAsAttributeHandle
2720 mono_reflection_marshal_as_attribute_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
2721 MonoMarshalSpec *spec, MonoError *error)
2723 error_init (error);
2725 MonoReflectionMarshalAsAttributeHandle minfo = MONO_HANDLE_NEW (MonoReflectionMarshalAsAttribute, mono_object_new_checked (domain, mono_class_get_marshal_as_attribute_class (), error));
2726 goto_if_nok (error, fail);
2727 guint32 utype = spec->native;
2728 MONO_HANDLE_SETVAL (minfo, utype, guint32, utype);
2730 switch (utype) {
2731 case MONO_NATIVE_LPARRAY:
2732 MONO_HANDLE_SETVAL (minfo, array_subtype, guint32, spec->data.array_data.elem_type);
2733 MONO_HANDLE_SETVAL (minfo, size_const, gint32, spec->data.array_data.num_elem);
2734 if (spec->data.array_data.param_num != -1)
2735 MONO_HANDLE_SETVAL (minfo, size_param_index, gint16, spec->data.array_data.param_num);
2736 break;
2738 case MONO_NATIVE_BYVALTSTR:
2739 case MONO_NATIVE_BYVALARRAY:
2740 MONO_HANDLE_SETVAL (minfo, size_const, gint32, spec->data.array_data.num_elem);
2741 break;
2743 case MONO_NATIVE_CUSTOM:
2744 if (spec->data.custom_data.custom_name) {
2745 MonoType *mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, klass->image, error);
2746 goto_if_nok (error, fail);
2748 if (mtype) {
2749 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, mtype, error);
2750 goto_if_nok (error, fail);
2752 MONO_HANDLE_SET (minfo, marshal_type_ref, rt);
2755 MonoStringHandle custom_name = mono_string_new_handle (domain, spec->data.custom_data.custom_name, error);
2756 goto_if_nok (error, fail);
2757 MONO_HANDLE_SET (minfo, marshal_type, custom_name);
2759 if (spec->data.custom_data.cookie) {
2760 MonoStringHandle cookie = mono_string_new_handle (domain, spec->data.custom_data.cookie, error);
2761 goto_if_nok (error, fail);
2762 MONO_HANDLE_SET (minfo, marshal_cookie, cookie);
2764 break;
2766 default:
2767 break;
2770 return minfo;
2771 fail:
2772 return MONO_HANDLE_NEW (MonoReflectionMarshalAsAttribute, NULL);
2775 #ifndef DISABLE_REFLECTION_EMIT
2776 static MonoMethod*
2777 reflection_methodbuilder_to_mono_method (MonoClass *klass,
2778 ReflectionMethodBuilder *rmb,
2779 MonoMethodSignature *sig,
2780 MonoError *error)
2782 MonoMethod *m;
2783 MonoMethodWrapper *wrapperm;
2784 MonoMarshalSpec **specs = NULL;
2785 MonoReflectionMethodAux *method_aux;
2786 MonoImage *image;
2787 gboolean dynamic;
2788 int i;
2790 error_init (error);
2792 * Methods created using a MethodBuilder should have their memory allocated
2793 * inside the image mempool, while dynamic methods should have their memory
2794 * malloc'd.
2796 dynamic = rmb->refs != NULL;
2797 image = dynamic ? NULL : klass->image;
2799 if (!dynamic)
2800 g_assert (!mono_class_is_ginst (klass));
2802 mono_loader_lock ();
2804 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
2805 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
2806 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
2807 else
2808 m = (MonoMethod *)image_g_new0 (image, MonoDynamicMethod, 1);
2810 wrapperm = (MonoMethodWrapper*)m;
2812 m->dynamic = dynamic;
2813 m->slot = -1;
2814 m->flags = rmb->attrs;
2815 m->iflags = rmb->iattrs;
2816 m->name = string_to_utf8_image_raw (image, rmb->name, error);
2817 goto_if_nok (error, fail);
2818 m->klass = klass;
2819 m->signature = sig;
2820 m->sre_method = TRUE;
2821 m->skip_visibility = rmb->skip_visibility;
2822 if (rmb->table_idx)
2823 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
2825 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
2826 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
2827 m->string_ctor = 1;
2829 m->signature->pinvoke = 1;
2830 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
2831 m->signature->pinvoke = 1;
2833 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2835 method_aux->dllentry = rmb->dllentry ? string_to_utf8_image_raw (image, rmb->dllentry, error) : image_strdup (image, m->name);
2836 mono_error_assert_ok (error);
2837 method_aux->dll = string_to_utf8_image_raw (image, rmb->dll, error);
2838 mono_error_assert_ok (error);
2840 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
2842 if (image_is_dynamic (klass->image))
2843 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
2845 goto leave;
2847 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
2848 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
2849 MonoMethodHeader *header;
2850 guint32 code_size;
2851 gint32 max_stack, i;
2852 gint32 num_locals = 0;
2853 gint32 num_clauses = 0;
2854 guint8 *code;
2856 if (rmb->ilgen) {
2857 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
2858 code_size = rmb->ilgen->code_len;
2859 max_stack = rmb->ilgen->max_stack;
2860 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
2861 if (rmb->ilgen->ex_handlers)
2862 num_clauses = mono_reflection_method_count_clauses (rmb->ilgen);
2863 } else {
2864 if (rmb->code) {
2865 code = mono_array_addr (rmb->code, guint8, 0);
2866 code_size = mono_array_length (rmb->code);
2867 /* we probably need to run a verifier on the code... */
2868 max_stack = 8;
2870 else {
2871 code = NULL;
2872 code_size = 0;
2873 max_stack = 8;
2877 header = (MonoMethodHeader *)mono_image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
2878 header->code_size = code_size;
2879 header->code = (const unsigned char *)image_g_malloc (image, code_size);
2880 memcpy ((char*)header->code, code, code_size);
2881 header->max_stack = max_stack;
2882 header->init_locals = rmb->init_locals;
2883 header->num_locals = num_locals;
2885 for (i = 0; i < num_locals; ++i) {
2886 MonoReflectionLocalBuilder *lb =
2887 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
2889 header->locals [i] = image_g_new0 (image, MonoType, 1);
2890 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)lb->type, error);
2891 mono_error_assert_ok (error);
2892 memcpy (header->locals [i], type, MONO_SIZEOF_TYPE);
2895 header->num_clauses = num_clauses;
2896 if (num_clauses) {
2897 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
2898 rmb->ilgen, num_clauses, error);
2899 mono_error_assert_ok (error);
2902 wrapperm->header = header;
2903 MonoDynamicMethod *dm = (MonoDynamicMethod*)wrapperm;
2904 dm->assembly = klass->image->assembly;
2907 if (rmb->generic_params) {
2908 int count = mono_array_length (rmb->generic_params);
2909 MonoGenericContainer *container;
2911 container = (MonoGenericContainer *)mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
2912 container->is_method = TRUE;
2913 container->is_anonymous = FALSE;
2914 container->type_argc = count;
2915 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
2916 container->owner.method = m;
2918 m->is_generic = TRUE;
2919 mono_method_set_generic_container (m, container);
2921 for (i = 0; i < count; i++) {
2922 MonoReflectionGenericParam *gp =
2923 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
2924 MonoType *gp_type = mono_reflection_type_get_handle ((MonoReflectionType*)gp, error);
2925 mono_error_assert_ok (error);
2926 MonoGenericParamFull *param = (MonoGenericParamFull *) gp_type->data.generic_param;
2927 container->type_params [i] = *param;
2928 container->type_params [i].param.owner = container;
2930 gp->type.type->data.generic_param = (MonoGenericParam*)&container->type_params [i];
2932 MonoClass *gklass = mono_class_from_mono_type (gp_type);
2933 gklass->wastypebuilder = TRUE;
2937 * The method signature might have pointers to generic parameters that belong to other methods.
2938 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
2939 * generic parameters.
2941 for (i = 0; i < m->signature->param_count; ++i) {
2942 MonoType *t = m->signature->params [i];
2943 if (t->type == MONO_TYPE_MVAR) {
2944 MonoGenericParam *gparam = t->data.generic_param;
2945 if (gparam->num < count) {
2946 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
2947 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
2953 if (mono_class_is_gtd (klass)) {
2954 container->parent = mono_class_get_generic_container (klass);
2955 container->context.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
2957 container->context.method_inst = mono_get_shared_generic_inst (container);
2960 if (rmb->refs) {
2961 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
2962 int i;
2963 void **data;
2965 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
2967 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
2968 data [0] = GUINT_TO_POINTER (rmb->nrefs);
2969 for (i = 0; i < rmb->nrefs; ++i)
2970 data [i + 1] = rmb->refs [i];
2973 method_aux = NULL;
2975 /* Parameter info */
2976 if (rmb->pinfo) {
2977 if (!method_aux)
2978 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
2979 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
2980 for (i = 0; i <= m->signature->param_count; ++i) {
2981 MonoReflectionParamBuilder *pb;
2982 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
2983 if ((i > 0) && (pb->attrs)) {
2984 /* Make a copy since it might point to a shared type structure */
2985 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
2986 m->signature->params [i - 1]->attrs = pb->attrs;
2989 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
2990 MonoDynamicImage *assembly;
2991 guint32 idx, len;
2992 MonoTypeEnum def_type;
2993 char *p;
2994 const char *p2;
2996 if (!method_aux->param_defaults) {
2997 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
2998 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
3000 assembly = (MonoDynamicImage*)klass->image;
3001 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &def_type);
3002 /* Copy the data from the blob since it might get realloc-ed */
3003 p = assembly->blob.data + idx;
3004 len = mono_metadata_decode_blob_size (p, &p2);
3005 len += p2 - p;
3006 method_aux->param_defaults [i] = (uint8_t *)image_g_malloc (image, len);
3007 method_aux->param_default_types [i] = def_type;
3008 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
3011 if (pb->name) {
3012 method_aux->param_names [i] = string_to_utf8_image_raw (image, pb->name, error);
3013 mono_error_assert_ok (error);
3015 if (pb->cattrs) {
3016 if (!method_aux->param_cattr)
3017 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
3018 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
3024 /* Parameter marshalling */
3025 if (rmb->pinfo)
3026 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
3027 MonoReflectionParamBuilder *pb;
3028 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
3029 if (pb->marshal_info) {
3030 if (specs == NULL)
3031 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
3032 specs [pb->position] =
3033 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info, error);
3034 goto_if_nok (error, fail);
3038 if (specs != NULL) {
3039 if (!method_aux)
3040 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
3041 method_aux->param_marshall = specs;
3044 if (image_is_dynamic (klass->image) && method_aux)
3045 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
3047 leave:
3048 mono_loader_unlock ();
3049 if (!m) // FIXME: This leaks if image is not NULL.
3050 image_g_free (image, specs);
3051 return m;
3053 fail:
3054 m = NULL;
3055 goto leave;
3058 static MonoMethod*
3059 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb, MonoError *error)
3061 ReflectionMethodBuilder rmb;
3062 MonoMethodSignature *sig;
3064 mono_loader_lock ();
3066 if (!mono_reflection_methodbuilder_from_ctor_builder (&rmb, mb, error))
3067 return NULL;
3069 g_assert (klass->image != NULL);
3070 sig = ctor_builder_to_signature_raw (klass->image, mb, error); /* FIXME use handles */
3071 mono_loader_unlock ();
3072 return_val_if_nok (error, NULL);
3074 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3075 return_val_if_nok (error, NULL);
3076 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
3078 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save) {
3079 /* ilgen is no longer needed */
3080 mb->ilgen = NULL;
3083 return mb->mhandle;
3086 static MonoMethod*
3087 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilderHandle ref_mb, MonoError *error)
3089 ReflectionMethodBuilder rmb;
3090 MonoMethodSignature *sig;
3092 error_init (error);
3094 mono_loader_lock ();
3096 MonoReflectionMethodBuilder *mb = MONO_HANDLE_RAW (ref_mb); /* FIXME use handles */
3097 if (!mono_reflection_methodbuilder_from_method_builder (&rmb, mb, error))
3098 return NULL;
3100 g_assert (klass->image != NULL);
3101 sig = method_builder_to_signature (klass->image, ref_mb, error);
3102 mono_loader_unlock ();
3103 return_val_if_nok (error, NULL);
3105 MonoMethod *method = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3106 return_val_if_nok (error, NULL);
3107 MONO_HANDLE_SETVAL (ref_mb, mhandle, MonoMethod*, method);
3108 mono_save_custom_attrs (klass->image, method, mb->cattrs);
3110 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save)
3111 /* ilgen is no longer needed */
3112 mb->ilgen = NULL;
3113 return method;
3116 static MonoMethod*
3117 methodbuilder_to_mono_method_raw (MonoClass *klass, MonoReflectionMethodBuilder* mb_raw, MonoError *error)
3119 HANDLE_FUNCTION_ENTER (); /* FIXME change callers of methodbuilder_to_mono_method_raw to use handles */
3120 error_init (error);
3121 MONO_HANDLE_DCL (MonoReflectionMethodBuilder, mb);
3122 MonoMethod *result = methodbuilder_to_mono_method (klass, mb, error);
3123 HANDLE_FUNCTION_RETURN_VAL (result);
3126 #endif
3128 #ifndef DISABLE_REFLECTION_EMIT
3131 * fix_partial_generic_class:
3132 * @klass: a generic instantiation MonoClass
3133 * @error: set on error
3135 * Assumes that the generic container of @klass has its vtable
3136 * initialized, and updates the parent class, interfaces, methods and
3137 * fields of @klass by inflating the types using the generic context.
3139 * On success returns TRUE, on failure returns FALSE and sets @error.
3142 static gboolean
3143 fix_partial_generic_class (MonoClass *klass, MonoError *error)
3145 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
3146 int i;
3148 error_init (error);
3150 if (klass->wastypebuilder)
3151 return TRUE;
3153 if (klass->parent != gklass->parent) {
3154 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &mono_class_get_generic_class (klass)->context, error);
3155 if (mono_error_ok (error)) {
3156 MonoClass *parent = mono_class_from_mono_type (parent_type);
3157 mono_metadata_free_type (parent_type);
3158 if (parent != klass->parent) {
3159 /*fool mono_class_setup_parent*/
3160 klass->supertypes = NULL;
3161 mono_class_setup_parent (klass, parent);
3163 } else {
3164 if (gklass->wastypebuilder)
3165 klass->wastypebuilder = TRUE;
3166 return FALSE;
3170 if (!mono_class_get_generic_class (klass)->need_sync)
3171 return TRUE;
3173 int mcount = mono_class_get_method_count (klass);
3174 int gmcount = mono_class_get_method_count (gklass);
3175 if (mcount != gmcount) {
3176 mono_class_set_method_count (klass, gmcount);
3177 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * (gmcount + 1));
3179 for (i = 0; i < gmcount; i++) {
3180 klass->methods [i] = mono_class_inflate_generic_method_full_checked (
3181 gklass->methods [i], klass, mono_class_get_context (klass), error);
3182 mono_error_assert_ok (error);
3186 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
3187 klass->interface_count = gklass->interface_count;
3188 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
3189 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
3191 for (i = 0; i < gklass->interface_count; ++i) {
3192 MonoType *iface_type = mono_class_inflate_generic_type_checked (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass), error);
3193 return_val_if_nok (error, FALSE);
3195 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
3196 mono_metadata_free_type (iface_type);
3198 if (!ensure_runtime_vtable (klass->interfaces [i], error))
3199 return FALSE;
3201 klass->interfaces_inited = 1;
3204 int fcount = mono_class_get_field_count (klass);
3205 int gfcount = mono_class_get_field_count (gklass);
3206 if (fcount != gfcount) {
3207 mono_class_set_field_count (klass, gfcount);
3208 klass->fields = image_g_new0 (klass->image, MonoClassField, gfcount);
3210 for (i = 0; i < gfcount; i++) {
3211 klass->fields [i] = gklass->fields [i];
3212 klass->fields [i].parent = klass;
3213 klass->fields [i].type = mono_class_inflate_generic_type_checked (gklass->fields [i].type, mono_class_get_context (klass), error);
3214 return_val_if_nok (error, FALSE);
3218 /*We can only finish with this klass once it's parent has as well*/
3219 if (gklass->wastypebuilder)
3220 klass->wastypebuilder = TRUE;
3221 return TRUE;
3225 * ensure_generic_class_runtime_vtable:
3226 * @klass a generic class
3227 * @error set on error
3229 * Ensures that the generic container of @klass has a vtable and
3230 * returns TRUE on success. On error returns FALSE and sets @error.
3232 static gboolean
3233 ensure_generic_class_runtime_vtable (MonoClass *klass, MonoError *error)
3235 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
3237 error_init (error);
3239 if (!ensure_runtime_vtable (gklass, error))
3240 return FALSE;
3242 return fix_partial_generic_class (klass, error);
3246 * ensure_runtime_vtable:
3247 * @klass the class
3248 * @error set on error
3250 * Ensures that @klass has a vtable and returns TRUE on success. On
3251 * error returns FALSE and sets @error.
3253 static gboolean
3254 ensure_runtime_vtable (MonoClass *klass, MonoError *error)
3256 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3257 int i, num, j;
3259 error_init (error);
3261 if (!image_is_dynamic (klass->image) || (!tb && !mono_class_is_ginst (klass)) || klass->wastypebuilder)
3262 return TRUE;
3263 if (klass->parent)
3264 if (!ensure_runtime_vtable (klass->parent, error))
3265 return FALSE;
3267 if (tb) {
3268 num = tb->ctors? mono_array_length (tb->ctors): 0;
3269 num += tb->num_methods;
3270 mono_class_set_method_count (klass, num);
3271 klass->methods = (MonoMethod **)mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
3272 num = tb->ctors? mono_array_length (tb->ctors): 0;
3273 for (i = 0; i < num; ++i) {
3274 MonoMethod *ctor = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), error);
3275 if (!ctor)
3276 return FALSE;
3277 klass->methods [i] = ctor;
3279 num = tb->num_methods;
3280 j = i;
3281 for (i = 0; i < num; ++i) {
3282 MonoMethod *meth = methodbuilder_to_mono_method_raw (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), error); /* FIXME use handles */
3283 if (!meth)
3284 return FALSE;
3285 klass->methods [j++] = meth;
3288 if (tb->interfaces) {
3289 klass->interface_count = mono_array_length (tb->interfaces);
3290 klass->interfaces = (MonoClass **)mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
3291 for (i = 0; i < klass->interface_count; ++i) {
3292 MonoType *iface = mono_type_array_get_and_resolve_raw (tb->interfaces, i, error); /* FIXME use handles */
3293 return_val_if_nok (error, FALSE);
3294 klass->interfaces [i] = mono_class_from_mono_type (iface);
3295 if (!ensure_runtime_vtable (klass->interfaces [i], error))
3296 return FALSE;
3298 klass->interfaces_inited = 1;
3300 } else if (mono_class_is_ginst (klass)){
3301 if (!ensure_generic_class_runtime_vtable (klass, error)) {
3302 mono_class_set_type_load_failure (klass, "Could not initialize vtable for generic class due to: %s", mono_error_get_message (error));
3303 return FALSE;
3307 if (mono_class_is_interface (klass) && !mono_class_is_ginst (klass)) {
3308 int slot_num = 0;
3309 int mcount = mono_class_get_method_count (klass);
3310 for (i = 0; i < mcount; ++i) {
3311 MonoMethod *im = klass->methods [i];
3312 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
3313 im->slot = slot_num++;
3316 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
3317 mono_class_setup_interface_offsets (klass);
3318 mono_class_setup_interface_id (klass);
3322 * The generic vtable is needed even if image->run is not set since some
3323 * runtime code like ves_icall_Type_GetMethodsByName depends on
3324 * method->slot being defined.
3328 * tb->methods could not be freed since it is used for determining
3329 * overrides during dynamic vtable construction.
3332 return TRUE;
3335 static MonoMethod*
3336 mono_reflection_method_get_handle (MonoObject *method, MonoError *error)
3338 error_init (error);
3339 MonoClass *klass = mono_object_class (method);
3340 if (is_sr_mono_method (klass)) {
3341 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
3342 return sr_method->method;
3344 if (is_sre_method_builder (klass)) {
3345 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
3346 return mb->mhandle;
3348 if (mono_is_sre_method_on_tb_inst (klass)) {
3349 MonoClass *handle_class;
3351 MonoMethod *result = mono_reflection_resolve_object (NULL, method, &handle_class, NULL, error);
3352 return_val_if_nok (error, NULL);
3354 return result;
3357 g_error ("Can't handle methods of type %s:%s", klass->name_space, klass->name);
3358 return NULL;
3361 void
3362 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
3364 MonoReflectionTypeBuilder *tb;
3365 int i, j, onum;
3366 MonoReflectionMethod *m;
3368 error_init (error);
3369 *overrides = NULL;
3370 *num_overrides = 0;
3372 g_assert (image_is_dynamic (klass->image));
3374 if (!mono_class_has_ref_info (klass))
3375 return;
3377 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3378 g_assert (strcmp (mono_object_class (tb)->name, "TypeBuilder") == 0);
3380 onum = 0;
3381 if (tb->methods) {
3382 for (i = 0; i < tb->num_methods; ++i) {
3383 MonoReflectionMethodBuilder *mb =
3384 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3385 if (mb->override_methods)
3386 onum += mono_array_length (mb->override_methods);
3390 if (onum) {
3391 *overrides = g_new0 (MonoMethod*, onum * 2);
3393 onum = 0;
3394 for (i = 0; i < tb->num_methods; ++i) {
3395 MonoReflectionMethodBuilder *mb =
3396 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3397 if (mb->override_methods) {
3398 for (j = 0; j < mono_array_length (mb->override_methods); ++j) {
3399 m = mono_array_get (mb->override_methods, MonoReflectionMethod*, j);
3401 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject*)m, error);
3402 return_if_nok (error);
3403 (*overrides) [onum * 2 + 1] = mb->mhandle;
3405 g_assert (mb->mhandle);
3407 onum ++;
3413 *num_overrides = onum;
3416 /* This initializes the same data as mono_class_setup_fields () */
3417 static void
3418 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
3420 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3421 MonoReflectionFieldBuilder *fb;
3422 MonoClassField *field;
3423 MonoFieldDefaultValue *def_values;
3424 MonoImage *image = klass->image;
3425 const char *p, *p2;
3426 int i, instance_size, packing_size = 0;
3427 guint32 len, idx;
3429 if (klass->parent) {
3430 if (!klass->parent->size_inited)
3431 mono_class_init (klass->parent);
3432 instance_size = klass->parent->instance_size;
3433 } else {
3434 instance_size = sizeof (MonoObject);
3437 int fcount = tb->num_fields;
3438 mono_class_set_field_count (klass, fcount);
3440 error_init (error);
3442 if (tb->class_size) {
3443 packing_size = tb->packing_size;
3444 instance_size += tb->class_size;
3447 klass->fields = image_g_new0 (image, MonoClassField, fcount);
3448 def_values = image_g_new0 (image, MonoFieldDefaultValue, fcount);
3449 mono_class_set_field_def_values (klass, def_values);
3451 This is, guess what, a hack.
3452 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
3453 On the static path no field class is resolved, only types are built. This is the right thing to do
3454 but we suck.
3455 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
3457 klass->size_inited = 1;
3459 for (i = 0; i < fcount; ++i) {
3460 MonoArray *rva_data;
3461 fb = (MonoReflectionFieldBuilder *)mono_array_get (tb->fields, gpointer, i);
3462 field = &klass->fields [i];
3463 field->parent = klass;
3464 field->name = string_to_utf8_image_raw (image, fb->name, error); /* FIXME use handles */
3465 if (!mono_error_ok (error))
3466 return;
3467 if (fb->attrs) {
3468 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3469 return_if_nok (error);
3470 field->type = mono_metadata_type_dup (klass->image, type);
3471 field->type->attrs = fb->attrs;
3472 } else {
3473 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type, error);
3474 return_if_nok (error);
3477 if (!klass->enumtype && !mono_type_get_underlying_type (field->type)) {
3478 mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
3479 continue;
3482 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && (rva_data = fb->rva_data)) {
3483 char *base = mono_array_addr (rva_data, char, 0);
3484 size_t size = mono_array_length (rva_data);
3485 char *data = (char *)mono_image_alloc (klass->image, size);
3486 memcpy (data, base, size);
3487 def_values [i].data = data;
3489 if (fb->offset != -1)
3490 field->offset = fb->offset;
3491 fb->handle = field;
3492 mono_save_custom_attrs (klass->image, field, fb->cattrs);
3494 if (fb->def_value) {
3495 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3496 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
3497 idx = mono_dynimage_encode_constant (assembly, fb->def_value, &def_values [i].def_type);
3498 /* Copy the data from the blob since it might get realloc-ed */
3499 p = assembly->blob.data + idx;
3500 len = mono_metadata_decode_blob_size (p, &p2);
3501 len += p2 - p;
3502 def_values [i].data = (const char *)mono_image_alloc (image, len);
3503 memcpy ((gpointer)def_values [i].data, p, len);
3507 if (!mono_class_has_failure (klass))
3508 mono_class_layout_fields (klass, instance_size, packing_size, tb->class_size, TRUE);
3511 static void
3512 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
3514 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3515 MonoReflectionPropertyBuilder *pb;
3516 MonoImage *image = klass->image;
3517 MonoProperty *properties;
3518 MonoClassPropertyInfo *info;
3519 int i;
3521 error_init (error);
3523 info = mono_class_get_property_info (klass);
3524 if (!info) {
3525 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
3526 mono_class_set_property_info (klass, info);
3529 info->count = tb->properties ? mono_array_length (tb->properties) : 0;
3530 info->first = 0;
3532 properties = image_g_new0 (image, MonoProperty, info->count);
3533 info->properties = properties;
3534 for (i = 0; i < info->count; ++i) {
3535 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3536 properties [i].parent = klass;
3537 properties [i].attrs = pb->attrs;
3538 properties [i].name = string_to_utf8_image_raw (image, pb->name, error); /* FIXME use handles */
3539 if (!mono_error_ok (error))
3540 return;
3541 if (pb->get_method)
3542 properties [i].get = pb->get_method->mhandle;
3543 if (pb->set_method)
3544 properties [i].set = pb->set_method->mhandle;
3546 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
3547 if (pb->def_value) {
3548 guint32 len, idx;
3549 const char *p, *p2;
3550 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
3551 if (!info->def_values)
3552 info->def_values = image_g_new0 (image, MonoFieldDefaultValue, info->count);
3553 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
3554 idx = mono_dynimage_encode_constant (assembly, pb->def_value, &info->def_values [i].def_type);
3555 /* Copy the data from the blob since it might get realloc-ed */
3556 p = assembly->blob.data + idx;
3557 len = mono_metadata_decode_blob_size (p, &p2);
3558 len += p2 - p;
3559 info->def_values [i].data = (const char *)mono_image_alloc (image, len);
3560 memcpy ((gpointer)info->def_values [i].data, p, len);
3565 static void
3566 typebuilder_setup_events (MonoClass *klass, MonoError *error)
3568 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
3569 MonoReflectionEventBuilder *eb;
3570 MonoImage *image = klass->image;
3571 MonoEvent *events;
3572 MonoClassEventInfo *info;
3573 int i;
3575 error_init (error);
3577 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
3578 mono_class_set_event_info (klass, info);
3580 info->count = tb->events ? mono_array_length (tb->events) : 0;
3581 info->first = 0;
3583 events = image_g_new0 (image, MonoEvent, info->count);
3584 info->events = events;
3585 for (i = 0; i < info->count; ++i) {
3586 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3587 events [i].parent = klass;
3588 events [i].attrs = eb->attrs;
3589 events [i].name = string_to_utf8_image_raw (image, eb->name, error); /* FIXME use handles */
3590 if (!mono_error_ok (error))
3591 return;
3592 if (eb->add_method)
3593 events [i].add = eb->add_method->mhandle;
3594 if (eb->remove_method)
3595 events [i].remove = eb->remove_method->mhandle;
3596 if (eb->raise_method)
3597 events [i].raise = eb->raise_method->mhandle;
3599 #ifndef MONO_SMALL_CONFIG
3600 if (eb->other_methods) {
3601 int j;
3602 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
3603 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
3604 MonoReflectionMethodBuilder *mb =
3605 mono_array_get (eb->other_methods,
3606 MonoReflectionMethodBuilder*, j);
3607 events [i].other [j] = mb->mhandle;
3610 #endif
3611 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
3615 struct remove_instantiations_user_data
3617 MonoClass *klass;
3618 MonoError *error;
3621 static gboolean
3622 remove_instantiations_of_and_ensure_contents (gpointer key,
3623 gpointer value,
3624 gpointer user_data)
3626 struct remove_instantiations_user_data *data = (struct remove_instantiations_user_data*)user_data;
3627 MonoType *type = (MonoType*)key;
3628 MonoClass *klass = data->klass;
3629 gboolean already_failed = !is_ok (data->error);
3630 MonoError lerror;
3631 MonoError *error = already_failed ? &lerror : data->error;
3633 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
3634 MonoClass *inst_klass = mono_class_from_mono_type (type);
3635 //Ensure it's safe to use it.
3636 if (!fix_partial_generic_class (inst_klass, error)) {
3637 mono_class_set_type_load_failure (inst_klass, "Could not initialized generic type instance due to: %s", mono_error_get_message (error));
3638 // Marked the class with failure, but since some other instantiation already failed,
3639 // just report that one, and swallow the error from this one.
3640 if (already_failed)
3641 mono_error_cleanup (error);
3643 return TRUE;
3644 } else
3645 return FALSE;
3649 * reflection_setup_internal_class:
3650 * @tb: a TypeBuilder object
3651 * @error: set on error
3653 * Creates a MonoClass that represents the TypeBuilder.
3654 * This is a trick that lets us simplify a lot of reflection code
3655 * (and will allow us to support Build and Run assemblies easier).
3657 * Returns TRUE on success. On failure, returns FALSE and sets @error.
3659 static gboolean
3660 reflection_setup_internal_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
3662 MonoReflectionModuleBuilderHandle module_ref = MONO_HANDLE_NEW_GET (MonoReflectionModuleBuilder, ref_tb, module);
3663 GHashTable *unparented_classes = MONO_HANDLE_GETVAL(module_ref, unparented_classes);
3665 if (unparented_classes) {
3666 return reflection_setup_internal_class_internal (ref_tb, error);
3667 } else {
3668 // If we're not being called recursively
3669 unparented_classes = g_hash_table_new (NULL, NULL);
3670 MONO_HANDLE_SETVAL (module_ref, unparented_classes, GHashTable *, unparented_classes);
3672 gboolean ret_val = reflection_setup_internal_class_internal (ref_tb, error);
3673 mono_error_assert_ok (error);
3675 // Fix the relationship between the created classes and their parents
3676 reflection_setup_class_hierarchy (unparented_classes, error);
3677 mono_error_assert_ok (error);
3679 g_hash_table_destroy (unparented_classes);
3680 MONO_HANDLE_SETVAL (module_ref, unparented_classes, GHashTable *, NULL);
3682 return ret_val;
3687 MonoReflectionTypeHandle
3688 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilderHandle ref_tb, MonoError *error)
3690 error_init (error);
3692 reflection_setup_internal_class (ref_tb, error);
3693 mono_error_assert_ok (error);
3695 MonoDomain *domain = MONO_HANDLE_DOMAIN (ref_tb);
3696 MonoType *type = MONO_HANDLE_GETVAL (MONO_HANDLE_CAST (MonoReflectionType, ref_tb), type);
3697 MonoClass *klass = mono_class_from_mono_type (type);
3699 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, cattrs);
3700 mono_save_custom_attrs (klass->image, klass, MONO_HANDLE_RAW (cattrs)); /* FIXME use handles */
3703 * we need to lock the domain because the lock will be taken inside
3704 * So, we need to keep the locking order correct.
3706 mono_loader_lock ();
3707 mono_domain_lock (domain);
3708 if (klass->wastypebuilder) {
3709 mono_domain_unlock (domain);
3710 mono_loader_unlock ();
3712 return mono_type_get_object_handle (domain, &klass->byval_arg, error);
3715 * Fields to set in klass:
3716 * the various flags: delegate/unicode/contextbound etc.
3718 mono_class_set_flags (klass, MONO_HANDLE_GETVAL (ref_tb, attrs));
3719 klass->has_cctor = 1;
3721 mono_class_setup_parent (klass, klass->parent);
3722 /* fool mono_class_setup_supertypes */
3723 klass->supertypes = NULL;
3724 mono_class_setup_supertypes (klass);
3725 mono_class_setup_mono_type (klass);
3727 /* enums are done right away */
3728 if (!klass->enumtype)
3729 if (!ensure_runtime_vtable (klass, error))
3730 goto failure;
3732 MonoArrayHandle nested_types = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, subtypes);
3733 if (!MONO_HANDLE_IS_NULL (nested_types)) {
3734 GList *nested = NULL;
3735 int num_nested = mono_array_handle_length (nested_types);
3736 MonoReflectionTypeHandle nested_tb = MONO_HANDLE_NEW (MonoReflectionType, NULL);
3737 for (int i = 0; i < num_nested; ++i) {
3738 MONO_HANDLE_ARRAY_GETREF (nested_tb, nested_types, i);
3740 if (MONO_HANDLE_GETVAL (nested_tb, type) == NULL) {
3741 reflection_setup_internal_class (MONO_HANDLE_CAST (MonoReflectionTypeBuilder, nested_tb), error);
3742 mono_error_assert_ok (error);
3745 MonoType *subtype = mono_reflection_type_handle_mono_type (nested_tb, error);
3746 goto_if_nok (error, failure);
3747 nested = g_list_prepend_image (klass->image, nested, mono_class_from_mono_type (subtype));
3749 mono_class_set_nested_classes_property (klass, nested);
3752 klass->nested_classes_inited = TRUE;
3754 typebuilder_setup_fields (klass, error);
3755 goto_if_nok (error, failure);
3756 typebuilder_setup_properties (klass, error);
3757 goto_if_nok (error, failure);
3759 typebuilder_setup_events (klass, error);
3760 goto_if_nok (error, failure);
3762 klass->wastypebuilder = TRUE;
3764 MonoArrayHandle generic_params = MONO_HANDLE_NEW_GET (MonoArray, ref_tb, generic_params);
3765 if (!MONO_HANDLE_IS_NULL (generic_params)) {
3766 int num_params = mono_array_handle_length (generic_params);
3767 MonoReflectionTypeHandle ref_gparam = MONO_HANDLE_NEW (MonoReflectionType, NULL);
3768 for (int i = 0; i < num_params; i++) {
3769 MONO_HANDLE_ARRAY_GETREF (ref_gparam, generic_params, i);
3770 MonoType *param_type = mono_reflection_type_handle_mono_type (ref_gparam, error);
3771 goto_if_nok (error, failure);
3772 MonoClass *gklass = mono_class_from_mono_type (param_type);
3774 gklass->wastypebuilder = TRUE;
3779 * If we are a generic TypeBuilder, there might be instantiations in the type cache
3780 * which have type System.Reflection.MonoGenericClass, but after the type is created,
3781 * we want to return normal System.MonoType objects, so clear these out from the cache.
3783 * Together with this we must ensure the contents of all instances to match the created type.
3785 if (domain->type_hash && mono_class_is_gtd (klass)) {
3786 struct remove_instantiations_user_data data;
3787 data.klass = klass;
3788 data.error = error;
3789 mono_error_assert_ok (error);
3790 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, &data);
3791 goto_if_nok (error, failure);
3794 mono_domain_unlock (domain);
3795 mono_loader_unlock ();
3797 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
3798 mono_class_set_type_load_failure (klass, "Not a valid enumeration");
3799 mono_error_set_type_load_class (error, klass, "Not a valid enumeration");
3800 goto failure_unlocked;
3803 MonoReflectionTypeHandle res = mono_type_get_object_handle (domain, &klass->byval_arg, error);
3804 goto_if_nok (error, failure_unlocked);
3806 return res;
3808 failure:
3809 mono_class_set_type_load_failure (klass, "TypeBuilder could not create runtime class due to: %s", mono_error_get_message (error));
3810 klass->wastypebuilder = TRUE;
3811 mono_domain_unlock (domain);
3812 mono_loader_unlock ();
3813 failure_unlocked:
3814 return NULL;
3817 typedef struct {
3818 MonoMethod *handle;
3819 MonoDomain *domain;
3820 } DynamicMethodReleaseData;
3823 * The runtime automatically clean up those after finalization.
3825 static MonoReferenceQueue *dynamic_method_queue;
3827 static void
3828 free_dynamic_method (void *dynamic_method)
3830 DynamicMethodReleaseData *data = (DynamicMethodReleaseData *)dynamic_method;
3831 MonoDomain *domain = data->domain;
3832 MonoMethod *method = data->handle;
3833 guint32 dis_link;
3835 mono_domain_lock (domain);
3836 dis_link = (guint32)(size_t)g_hash_table_lookup (domain->method_to_dyn_method, method);
3837 g_hash_table_remove (domain->method_to_dyn_method, method);
3838 mono_domain_unlock (domain);
3839 g_assert (dis_link);
3840 mono_gchandle_free (dis_link);
3842 mono_runtime_free_method (domain, method);
3843 g_free (data);
3846 static gboolean
3847 reflection_create_dynamic_method (MonoReflectionDynamicMethodHandle ref_mb, MonoError *error)
3849 MonoReferenceQueue *queue;
3850 MonoMethod *handle;
3851 DynamicMethodReleaseData *release_data;
3852 ReflectionMethodBuilder rmb;
3853 MonoMethodSignature *sig;
3854 MonoClass *klass;
3855 MonoDomain *domain;
3856 GSList *l;
3857 int i;
3859 error_init (error);
3861 if (mono_runtime_is_shutting_down ()) {
3862 mono_error_set_generic_error (error, "System", "InvalidOperationException", "");
3863 return FALSE;
3866 if (!(queue = dynamic_method_queue)) {
3867 mono_loader_lock ();
3868 if (!(queue = dynamic_method_queue))
3869 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
3870 mono_loader_unlock ();
3873 sig = dynamic_method_to_signature (ref_mb, error);
3874 return_val_if_nok (error, FALSE);
3876 MonoReflectionDynamicMethod *mb = MONO_HANDLE_RAW (ref_mb); /* FIXME convert reflection_create_dynamic_method to use handles */
3877 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
3880 * Resolve references.
3883 * Every second entry in the refs array is reserved for storing handle_class,
3884 * which is needed by the ldtoken implementation in the JIT.
3886 rmb.nrefs = mb->nrefs;
3887 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
3888 for (i = 0; i < mb->nrefs; i += 2) {
3889 MonoClass *handle_class;
3890 gpointer ref;
3891 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
3893 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
3894 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
3896 * The referenced DynamicMethod should already be created by the managed
3897 * code, except in the case of circular references. In that case, we store
3898 * method in the refs array, and fix it up later when the referenced
3899 * DynamicMethod is created.
3901 if (method->mhandle) {
3902 ref = method->mhandle;
3903 } else {
3904 /* FIXME: GC object stored in unmanaged memory */
3905 ref = method;
3907 /* FIXME: GC object stored in unmanaged memory */
3908 method->referenced_by = g_slist_append (method->referenced_by, mb);
3910 handle_class = mono_defaults.methodhandle_class;
3911 } else {
3912 MonoException *ex = NULL;
3913 ref = mono_reflection_resolve_object (mb->module->image, obj, &handle_class, NULL, error);
3914 if (!is_ok (error)) {
3915 g_free (rmb.refs);
3916 return FALSE;
3918 if (!ref)
3919 ex = mono_get_exception_type_load (NULL, NULL);
3920 else if (mono_security_core_clr_enabled ())
3921 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
3923 if (ex) {
3924 g_free (rmb.refs);
3925 mono_error_set_exception_instance (error, ex);
3926 return FALSE;
3930 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
3931 rmb.refs [i + 1] = handle_class;
3934 MonoAssembly *ass = NULL;
3935 if (mb->owner) {
3936 MonoType *owner_type = mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner, error);
3937 if (!is_ok (error)) {
3938 g_free (rmb.refs);
3939 return FALSE;
3941 klass = mono_class_from_mono_type (owner_type);
3942 ass = klass->image->assembly;
3943 } else {
3944 klass = mono_defaults.object_class;
3945 ass = (mb->module && mb->module->image) ? mb->module->image->assembly : NULL;
3948 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig, error);
3949 ((MonoDynamicMethod*)handle)->assembly = ass;
3950 g_free (rmb.refs);
3951 return_val_if_nok (error, FALSE);
3953 release_data = g_new (DynamicMethodReleaseData, 1);
3954 release_data->handle = handle;
3955 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
3956 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
3957 g_free (release_data);
3959 /* Fix up refs entries pointing at us */
3960 for (l = mb->referenced_by; l; l = l->next) {
3961 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
3962 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
3963 gpointer *data;
3965 g_assert (method->mhandle);
3967 data = (gpointer*)wrapper->method_data;
3968 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
3969 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
3970 data [i + 1] = mb->mhandle;
3973 g_slist_free (mb->referenced_by);
3975 /* ilgen is no longer needed */
3976 mb->ilgen = NULL;
3978 domain = mono_domain_get ();
3979 mono_domain_lock (domain);
3980 if (!domain->method_to_dyn_method)
3981 domain->method_to_dyn_method = g_hash_table_new (NULL, NULL);
3982 g_hash_table_insert (domain->method_to_dyn_method, handle, (gpointer)(size_t)mono_gchandle_new_weakref ((MonoObject *)mb, TRUE));
3983 mono_domain_unlock (domain);
3985 return TRUE;
3988 void
3989 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethodHandle mb, MonoError *error)
3991 (void) reflection_create_dynamic_method (mb, error);
3994 #endif /* DISABLE_REFLECTION_EMIT */
3996 MonoMethodSignature *
3997 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token, MonoError *error)
3999 MonoMethodSignature *sig;
4000 g_assert (image_is_dynamic (image));
4002 error_init (error);
4004 sig = (MonoMethodSignature *)g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
4005 if (sig)
4006 return sig;
4008 return mono_method_signature_checked (method, error);
4011 #ifndef DISABLE_REFLECTION_EMIT
4014 * ensure_complete_type:
4016 * Ensure that KLASS is completed if it is a dynamic type, or references
4017 * dynamic types.
4019 static void
4020 ensure_complete_type (MonoClass *klass, MonoError *error)
4022 error_init (error);
4024 if (image_is_dynamic (klass->image) && !klass->wastypebuilder && mono_class_has_ref_info (klass)) {
4025 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (klass); /* FIXME use handles */
4027 mono_domain_try_type_resolve_typebuilder (mono_domain_get (), tb, error);
4028 return_if_nok (error);
4030 // Asserting here could break a lot of code
4031 //g_assert (klass->wastypebuilder);
4034 if (mono_class_is_ginst (klass)) {
4035 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
4036 int i;
4038 for (i = 0; i < inst->type_argc; ++i) {
4039 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]), error);
4040 return_if_nok (error);
4045 gpointer
4046 mono_reflection_resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
4048 MonoClass *oklass = obj->vtable->klass;
4049 gpointer result = NULL;
4051 error_init (error);
4053 if (strcmp (oklass->name, "String") == 0) {
4054 result = mono_string_intern_checked ((MonoString*)obj, error);
4055 return_val_if_nok (error, NULL);
4056 *handle_class = mono_defaults.string_class;
4057 g_assert (result);
4058 } else if (strcmp (oklass->name, "RuntimeType") == 0) {
4059 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj, error);
4060 return_val_if_nok (error, NULL);
4061 MonoClass *mc = mono_class_from_mono_type (type);
4062 if (!mono_class_init (mc)) {
4063 mono_error_set_for_class_failure (error, mc);
4064 return NULL;
4067 if (context) {
4068 MonoType *inflated = mono_class_inflate_generic_type_checked (type, context, error);
4069 return_val_if_nok (error, NULL);
4071 result = mono_class_from_mono_type (inflated);
4072 mono_metadata_free_type (inflated);
4073 } else {
4074 result = mono_class_from_mono_type (type);
4076 *handle_class = mono_defaults.typehandle_class;
4077 g_assert (result);
4078 } else if (strcmp (oklass->name, "MonoMethod") == 0 ||
4079 strcmp (oklass->name, "MonoCMethod") == 0) {
4080 result = ((MonoReflectionMethod*)obj)->method;
4081 if (context) {
4082 result = mono_class_inflate_generic_method_checked ((MonoMethod *)result, context, error);
4083 mono_error_assert_ok (error);
4085 *handle_class = mono_defaults.methodhandle_class;
4086 g_assert (result);
4087 } else if (strcmp (oklass->name, "MonoField") == 0) {
4088 MonoClassField *field = ((MonoReflectionField*)obj)->field;
4090 ensure_complete_type (field->parent, error);
4091 return_val_if_nok (error, NULL);
4093 if (context) {
4094 MonoType *inflated = mono_class_inflate_generic_type_checked (&field->parent->byval_arg, context, error);
4095 return_val_if_nok (error, NULL);
4097 MonoClass *klass = mono_class_from_mono_type (inflated);
4098 MonoClassField *inflated_field;
4099 gpointer iter = NULL;
4100 mono_metadata_free_type (inflated);
4101 while ((inflated_field = mono_class_get_fields (klass, &iter))) {
4102 if (!strcmp (field->name, inflated_field->name))
4103 break;
4105 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
4106 result = inflated_field;
4107 } else {
4108 result = field;
4110 *handle_class = mono_defaults.fieldhandle_class;
4111 g_assert (result);
4112 } else if (strcmp (oklass->name, "TypeBuilder") == 0) {
4113 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
4114 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb, error);
4115 return_val_if_nok (error, NULL);
4116 MonoClass *klass;
4118 klass = type->data.klass;
4119 if (klass->wastypebuilder) {
4120 /* Already created */
4121 result = klass;
4123 else {
4124 mono_domain_try_type_resolve_typebuilder (mono_domain_get (), tb, error);
4125 return_val_if_nok (error, NULL);
4126 result = type->data.klass;
4127 g_assert (result);
4129 *handle_class = mono_defaults.typehandle_class;
4130 } else if (strcmp (oklass->name, "SignatureHelper") == 0) {
4131 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
4132 MonoMethodSignature *sig;
4133 int nargs, i;
4135 if (helper->arguments)
4136 nargs = mono_array_length (helper->arguments);
4137 else
4138 nargs = 0;
4140 sig = mono_metadata_signature_alloc (image, nargs);
4141 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
4142 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
4144 if (helper->unmanaged_call_conv) { /* unmanaged */
4145 sig->call_convention = helper->unmanaged_call_conv - 1;
4146 sig->pinvoke = TRUE;
4147 } else if (helper->call_conv & 0x02) {
4148 sig->call_convention = MONO_CALL_VARARG;
4149 } else {
4150 sig->call_convention = MONO_CALL_DEFAULT;
4153 sig->param_count = nargs;
4154 /* TODO: Copy type ? */
4155 sig->ret = helper->return_type->type;
4156 for (i = 0; i < nargs; ++i) {
4157 sig->params [i] = mono_type_array_get_and_resolve_raw (helper->arguments, i, error); /* FIXME use handles */
4158 if (!is_ok (error)) {
4159 image_g_free (image, sig);
4160 return NULL;
4164 result = sig;
4165 *handle_class = NULL;
4166 } else if (strcmp (oklass->name, "DynamicMethod") == 0) {
4167 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
4168 /* Already created by the managed code */
4169 g_assert (method->mhandle);
4170 result = method->mhandle;
4171 *handle_class = mono_defaults.methodhandle_class;
4172 } else if (strcmp (oklass->name, "MonoArrayMethod") == 0) {
4173 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
4174 MonoType *mtype;
4175 MonoClass *klass;
4176 MonoMethod *method;
4177 gpointer iter;
4178 char *name;
4180 mtype = mono_reflection_type_get_handle (m->parent, error);
4181 return_val_if_nok (error, NULL);
4182 klass = mono_class_from_mono_type (mtype);
4184 /* Find the method */
4186 name = mono_string_to_utf8_checked (m->name, error);
4187 return_val_if_nok (error, NULL);
4188 iter = NULL;
4189 while ((method = mono_class_get_methods (klass, &iter))) {
4190 if (!strcmp (method->name, name))
4191 break;
4193 g_free (name);
4195 // FIXME:
4196 g_assert (method);
4197 // FIXME: Check parameters/return value etc. match
4199 result = method;
4200 *handle_class = mono_defaults.methodhandle_class;
4201 } else if (is_sre_method_builder (oklass) ||
4202 mono_is_sre_ctor_builder (oklass) ||
4203 is_sre_field_builder (oklass) ||
4204 is_sre_gparam_builder (oklass) ||
4205 is_sre_generic_instance (oklass) ||
4206 is_sre_array (oklass) ||
4207 is_sre_byref (oklass) ||
4208 is_sre_pointer (oklass) ||
4209 !strcmp (oklass->name, "FieldOnTypeBuilderInst") ||
4210 !strcmp (oklass->name, "MethodOnTypeBuilderInst") ||
4211 !strcmp (oklass->name, "ConstructorOnTypeBuilderInst")) {
4212 static MonoMethod *resolve_method;
4213 if (!resolve_method) {
4214 MonoMethod *m = mono_class_get_method_from_name_flags (mono_class_get_module_builder_class (), "RuntimeResolve", 1, 0);
4215 g_assert (m);
4216 mono_memory_barrier ();
4217 resolve_method = m;
4219 void *args [16];
4220 args [0] = obj;
4221 obj = mono_runtime_invoke_checked (resolve_method, NULL, args, error);
4222 mono_error_assert_ok (error);
4223 g_assert (obj);
4224 return mono_reflection_resolve_object (image, obj, handle_class, context, error);
4225 } else {
4226 g_print ("%s\n", obj->vtable->klass->name);
4227 g_assert_not_reached ();
4229 return result;
4232 #else /* DISABLE_REFLECTION_EMIT */
4234 MonoArray*
4235 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4237 g_assert_not_reached ();
4238 return NULL;
4241 void
4242 mono_reflection_dynimage_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4244 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
4247 static gboolean
4248 mono_image_module_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
4250 g_assert_not_reached ();
4251 return FALSE;
4254 guint32
4255 mono_image_insert_string (MonoReflectionModuleBuilderHandle module, MonoStringHandle str, MonoError *error)
4257 g_assert_not_reached ();
4258 return 0;
4261 guint32
4262 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObjectHandle obj, MonoArrayHandle opt_param_types, MonoError *error)
4264 g_assert_not_reached ();
4265 return 0;
4268 guint32
4269 mono_image_create_token (MonoDynamicImage *assembly, MonoObjectHandle obj,
4270 gboolean create_open_instance, gboolean register_token, MonoError *error)
4272 g_assert_not_reached ();
4273 return 0;
4276 void
4277 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides, MonoError *error)
4279 error_init (error);
4280 *overrides = NULL;
4281 *num_overrides = 0;
4284 MonoReflectionTypeHandle
4285 ves_icall_TypeBuilder_create_runtime_class (MonoReflectionTypeBuilderHandle tb, MonoError *error)
4287 g_assert_not_reached ();
4288 return NULL;
4291 void
4292 ves_icall_DynamicMethod_create_dynamic_method (MonoReflectionDynamicMethodHandle mb, MonoError *error)
4294 error_init (error);
4297 MonoType*
4298 mono_reflection_type_get_handle (MonoReflectionType* ref, MonoError *error)
4300 error_init (error);
4301 if (!ref)
4302 return NULL;
4303 return ref->type;
4306 MonoType*
4307 mono_reflection_type_handle_mono_type (MonoReflectionTypeHandle ref, MonoError *error)
4309 error_init (error);
4310 if (MONO_HANDLE_IS_NULL (ref))
4311 return NULL;
4312 return MONO_HANDLE_GETVAL (ref, type);
4316 #endif /* DISABLE_REFLECTION_EMIT */
4318 void
4319 mono_sre_generic_param_table_entry_free (GenericParamTableEntry *entry)
4321 MONO_GC_UNREGISTER_ROOT_IF_MOVING (entry->gparam);
4322 g_free (entry);
4325 gint32
4326 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, gboolean create_open_instance, MonoError *error)
4328 error_init (error);
4329 if (MONO_HANDLE_IS_NULL (obj)) {
4330 mono_error_set_argument_null (error, "obj", "");
4331 return 0;
4333 return mono_image_create_token (MONO_HANDLE_GETVAL (mb, dynamic_image), obj, create_open_instance, TRUE, error);
4336 gint32
4337 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilderHandle mb,
4338 MonoReflectionMethodHandle method,
4339 MonoArrayHandle opt_param_types,
4340 MonoError *error)
4342 error_init (error);
4343 if (MONO_HANDLE_IS_NULL (method)) {
4344 mono_error_set_argument_null (error, "method", "");
4345 return 0;
4348 return mono_image_create_method_token (MONO_HANDLE_GETVAL (mb, dynamic_image), MONO_HANDLE_CAST (MonoObject, method), opt_param_types, error);
4351 void
4352 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
4354 MonoError error;
4355 mono_image_create_pefile (mb, file, &error);
4356 mono_error_set_pending_exception (&error);
4359 void
4360 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
4362 MonoError error;
4363 mono_image_build_metadata (mb, &error);
4364 mono_error_set_pending_exception (&error);
4367 void
4368 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilderHandle mb, MonoObjectHandle obj, guint32 token, MonoError *error)
4370 error_init (error);
4371 /* This function may be called by ModuleBuilder.FixupTokens to update
4372 * an existing token, so replace is okay here. */
4373 mono_dynamic_image_register_token (MONO_HANDLE_GETVAL (mb, dynamic_image), token, obj, MONO_DYN_IMAGE_TOK_REPLACE);
4376 MonoObjectHandle
4377 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilderHandle mb, guint32 token, MonoError *error)
4379 error_init (error);
4380 MonoDynamicImage *dynamic_image = MONO_HANDLE_GETVAL (mb, dynamic_image);
4381 return mono_dynamic_image_get_registered_token (dynamic_image, token, error);
4384 #ifndef DISABLE_REFLECTION_EMIT
4385 MonoArray*
4386 ves_icall_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
4388 MonoError error;
4389 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
4390 mono_error_set_pending_exception (&error);
4391 return result;
4393 #endif
4395 void
4396 ves_icall_AssemblyBuilder_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
4398 mono_reflection_dynimage_basic_init (assemblyb);
4401 void
4402 ves_icall_AssemblyBuilder_UpdateNativeCustomAttributes (MonoReflectionAssemblyBuilderHandle assemblyb, MonoError *error)
4404 MonoArrayHandle cattrs = MONO_HANDLE_NEW_GET (MonoArray, assemblyb, cattrs);
4406 MonoReflectionAssemblyHandle assembly_handle = MONO_HANDLE_CAST (MonoReflectionAssembly, assemblyb);
4407 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_handle, assembly);
4408 g_assert (assembly);
4410 mono_save_custom_attrs (assembly->image, assembly, MONO_HANDLE_RAW (cattrs));
4413 void
4414 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionTypeHandle enumtype,
4415 MonoReflectionTypeHandle t,
4416 MonoError *error)
4418 error_init (error);
4419 MONO_HANDLE_SETVAL (enumtype, type, MonoType*, MONO_HANDLE_GETVAL (t, type));
4422 void
4423 ves_icall_ModuleBuilder_basic_init (MonoReflectionModuleBuilderHandle moduleb, MonoError *error)
4425 error_init (error);
4426 mono_image_module_basic_init (moduleb, error);
4429 guint32
4430 ves_icall_ModuleBuilder_getUSIndex (MonoReflectionModuleBuilderHandle module, MonoStringHandle str, MonoError *error)
4432 return mono_image_insert_string (module, str, error);
4435 void
4436 ves_icall_ModuleBuilder_set_wrappers_type (MonoReflectionModuleBuilderHandle moduleb, MonoReflectionTypeHandle ref_type, MonoError *error)
4438 error_init (error);
4439 MonoDynamicImage *image = MONO_HANDLE_GETVAL (moduleb, dynamic_image);
4440 MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
4442 g_assert (type);
4443 image->wrappers_type = mono_class_from_mono_type (type);