-static MonoClass*
-inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
-{
- MonoType *args [1];
- args [0] = &arg0->byval_arg;
-
- return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
-}
-
-static MonoClass*
-array_class_get_if_rank (MonoClass *klass, guint rank)
-{
- return rank ? mono_array_class_get (klass, rank) : klass;
-}
-
-static void
-fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
-{
- valuetype_types [0] = eclass;
- if (eclass == mono_defaults.int16_class)
- valuetype_types [1] = mono_defaults.uint16_class;
- else if (eclass == mono_defaults.uint16_class)
- valuetype_types [1] = mono_defaults.int16_class;
- else if (eclass == mono_defaults.int32_class)
- valuetype_types [1] = mono_defaults.uint32_class;
- else if (eclass == mono_defaults.uint32_class)
- valuetype_types [1] = mono_defaults.int32_class;
- else if (eclass == mono_defaults.int64_class)
- valuetype_types [1] = mono_defaults.uint64_class;
- else if (eclass == mono_defaults.uint64_class)
- valuetype_types [1] = mono_defaults.int64_class;
- else if (eclass == mono_defaults.byte_class)
- valuetype_types [1] = mono_defaults.sbyte_class;
- else if (eclass == mono_defaults.sbyte_class)
- valuetype_types [1] = mono_defaults.byte_class;
- else if (eclass->enumtype && mono_class_enum_basetype (eclass))
- valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
-}
-
-static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
-static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
-static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
-static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
-static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
-
-/* this won't be needed once bug #325495 is completely fixed
- * though we'll need something similar to know which interfaces to allow
- * in arrays when they'll be lazyly created
- *
- * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
- * MS returns diferrent types based on which instance is called. For example:
- * object obj = new byte[10][];
- * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
- * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
- * a != b ==> true
- *
- * Fixing this should kill quite some code, save some bits and improve compatibility.
- */
-static MonoClass**
-get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
-{
- MonoClass *eclass = klass->element_class;
- MonoClass* generic_icollection_class;
- MonoClass* generic_ienumerable_class;
- MonoClass* generic_ienumerator_class;
- MonoClass* generic_ireadonlylist_class;
- MonoClass* generic_ireadonlycollection_class;
- MonoClass *valuetype_types[2] = { NULL, NULL };
- MonoClass **interfaces = NULL;
- int i, nifaces, interface_count, real_count, original_rank;
- int all_interfaces;
- gboolean internal_enumerator;
- gboolean eclass_is_valuetype;
-
- if (!mono_defaults.generic_ilist_class) {
- *num = 0;
- return NULL;
- }
- internal_enumerator = FALSE;
- eclass_is_valuetype = FALSE;
- original_rank = eclass->rank;
- if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
- MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
- if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
- /*
- * For a Enumerator<T[]> we need to get the list of interfaces for T.
- */
- eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
- original_rank = eclass->rank;
- if (!eclass->rank)
- eclass = eclass->element_class;
- internal_enumerator = TRUE;
- *is_enumerator = TRUE;
- } else {
- *num = 0;
- return NULL;
- }
- }
-
- /*
- * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
- * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
- */
- all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
-
- generic_icollection_class = mono_class_get_generic_icollection_class ();
- generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
- generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
- generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
- generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
-
- mono_class_init (eclass);
-
- /*
- * Arrays in 2.0 need to implement a number of generic interfaces
- * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
- * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
- * We collect the types needed to build the
- * instantiations in interfaces at intervals of 3/5, because 3/5 are
- * the generic interfaces needed to implement.
- *
- * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
- * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
- */
- if (eclass->valuetype) {
- nifaces = generic_ireadonlylist_class ? 5 : 3;
- fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
-
- /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
- real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
- if (internal_enumerator) {
- ++real_count;
- if (valuetype_types [1])
- ++real_count;
- }
-
- interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
- interfaces [0] = valuetype_types [0];
- if (valuetype_types [1])
- interfaces [nifaces] = valuetype_types [1];
-
- eclass_is_valuetype = TRUE;
- } else {
- int j;
- int idepth = eclass->idepth;
- if (!internal_enumerator)
- idepth--;
- nifaces = generic_ireadonlylist_class ? 2 : 3;
-
- // FIXME: This doesn't seem to work/required for generic params
- if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
- mono_class_setup_interface_offsets (eclass);
-
- interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
- /* we add object for interfaces and the supertypes for the other
- * types. The last of the supertypes is the element class itself which we
- * already created the explicit interfaces for (so we include it for IEnumerator
- * and exclude it for arrays).
- */
- if (MONO_CLASS_IS_INTERFACE (eclass))
- interface_count++;
- else
- interface_count += idepth;
- if (eclass->rank && eclass->element_class->valuetype) {
- fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
- if (valuetype_types [1])
- ++interface_count;
- }
- /* IList, ICollection, IEnumerable, IReadOnlyList */
- interface_count *= nifaces;
- real_count = interface_count;
- if (internal_enumerator) {
- real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
- if (valuetype_types [1])
- ++real_count;
- }
- interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
- if (MONO_CLASS_IS_INTERFACE (eclass)) {
- interfaces [0] = mono_defaults.object_class;
- j = nifaces;
- } else {
- j = 0;
- for (i = 0; i < idepth; i++) {
- mono_class_init (eclass->supertypes [i]);
- interfaces [j] = eclass->supertypes [i];
- j += nifaces;
- }
- }
- if (all_interfaces) {
- for (i = 0; i < eclass->interface_offsets_count; i++) {
- interfaces [j] = eclass->interfaces_packed [i];
- j += nifaces;
- }
- } else {
- for (i = 0; i < eclass->interface_count; i++) {
- interfaces [j] = eclass->interfaces [i];
- j += nifaces;
- }
- }
- if (valuetype_types [1]) {
- interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
- j += nifaces;
- }
- }
-
- /* instantiate the generic interfaces */
- for (i = 0; i < interface_count; i += nifaces) {
- MonoClass *iface = interfaces [i];
-
- interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
- interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
-
- if (eclass->valuetype) {
- interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
- if (generic_ireadonlylist_class) {
- interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
- interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
- }
- } else {
- if (!generic_ireadonlylist_class)
- interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
- }
- }
- if (internal_enumerator) {
- int j;
- /* instantiate IEnumerator<iface> */
- for (i = 0; i < interface_count; i++) {
- interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
- }
- j = interface_count;
- if (!eclass_is_valuetype) {
- if (MONO_CLASS_IS_INTERFACE (eclass)) {
- interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
- j ++;
- } else {
- for (i = 0; i < eclass->idepth; i++) {
- interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
- j ++;
- }
- }
- for (i = 0; i < eclass->interface_offsets_count; i++) {
- interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
- j ++;
- }
- } else {
- interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
- }
- if (valuetype_types [1])
- interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
- }
-#if 0
- {
- char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
- for (i = 0; i < real_count; ++i) {
- char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
- g_print ("%s implements %s\n", type_name, name);
- g_free (name);
- }
- g_free (type_name);
- }
-#endif
- *num = real_count;
- return interfaces;
-}
-
-static int
-find_array_interface (MonoClass *klass, const char *name)
-{
- int i;
- for (i = 0; i < klass->interface_count; ++i) {
- if (strcmp (klass->interfaces [i]->name, name) == 0)
- return i;
- }
- return -1;
-}
-