/// <summary>
        /// Read a method that describes the type system to metadata mappings.
        /// </summary>
        private void ReadMetadataMethod(MethodIL methodOfMappings, Dictionary <MetadataType, int> typeMappings, Dictionary <MethodDesc, int> methodMappings, Dictionary <FieldDesc, int> fieldMappings, HashSet <ModuleDesc> metadataModules)
        {
            ILStreamReader il = new ILStreamReader(methodOfMappings);

            // structure is
            // REPEAT N TIMES
            // ldtoken type/method/field OR ldc.i4 0. If ldtoken instruction is replaced with a ldc.i4, skip this entry
            // ldc.i4 metadata value
            // pop
            // pop
            while (true)
            {
                if (il.TryReadRet()) // ret
                {
                    break;
                }

                TypeSystemEntity tse;
                if (il.TryReadLdtokenAsTypeSystemEntity(out tse))
                {
                    int metadataTokenValue = il.ReadLdcI4();
                    il.ReadPop();
                    il.ReadPop();

                    if (tse is MetadataType)
                    {
                        MetadataType type = (MetadataType)tse;
                        metadataModules.Add(type.Module);
                        typeMappings.Add(type, metadataTokenValue);
                    }
                    else if (tse is MethodDesc)
                    {
                        MethodDesc method = (MethodDesc)tse;
                        // Finalizers are called via a field on the EEType. They should not be reflectable.
                        if (!method.IsFinalizer)
                        {
                            metadataModules.Add(((MetadataType)method.OwningType).Module);
                            methodMappings.Add(method, metadataTokenValue);
                        }
                    }
                    else if (tse is FieldDesc)
                    {
                        FieldDesc field = (FieldDesc)tse;
                        metadataModules.Add(((MetadataType)field.OwningType).Module);
                        fieldMappings.Add(field, metadataTokenValue);
                    }
                }
                else
                {
                    int deadLdtokenSignifier = il.ReadLdcI4();
                    Debug.Assert(deadLdtokenSignifier == 0);
                    il.ReadLdcI4();
                    il.ReadPop();
                    il.ReadPop();
                }
            }
        }
        /// <summary>
        /// Read a method that describes the type system to metadata mappings.
        /// </summary>
        private void ReadMetadataMethod(MethodIL methodOfMappings, out List <MetadataMapping <MetadataType> > typeMappings, out List <MetadataMapping <MethodDesc> > methodMappings, out List <MetadataMapping <FieldDesc> > fieldMappings, ref HashSet <ModuleDesc> metadataModules)
        {
            typeMappings   = new List <MetadataMapping <MetadataType> >();
            methodMappings = new List <MetadataMapping <MethodDesc> >();
            fieldMappings  = new List <MetadataMapping <FieldDesc> >();

            ILStreamReader il = new ILStreamReader(methodOfMappings);

            // structure is
            // REPEAT N TIMES
            // ldtoken type/method/field OR ldc.i4 0. If ldtoken instruction is replaced with a ldc.i4, skip this entry
            // ldc.i4 metadata value
            // pop
            // pop
            while (true)
            {
                if (il.TryReadRet()) // ret
                {
                    break;
                }

                TypeSystemEntity tse;
                if (il.TryReadLdtokenAsTypeSystemEntity(out tse))
                {
                    int metadataTokenValue = il.ReadLdcI4();
                    il.ReadPop();
                    il.ReadPop();

                    if (tse is MetadataType)
                    {
                        MetadataType type = (MetadataType)tse;
                        metadataModules.Add(type.Module);
                        typeMappings.Add(new MetadataMapping <MetadataType>(type, metadataTokenValue));
                    }
                    else if (tse is MethodDesc)
                    {
                        MethodDesc method = (MethodDesc)tse;
                        metadataModules.Add(((MetadataType)method.OwningType).Module);
                        methodMappings.Add(new MetadataMapping <MethodDesc>(method, metadataTokenValue));
                    }
                    else if (tse is FieldDesc)
                    {
                        FieldDesc field = (FieldDesc)tse;
                        metadataModules.Add(((MetadataType)field.OwningType).Module);
                        fieldMappings.Add(new MetadataMapping <FieldDesc>(field, metadataTokenValue));
                    }
                }
                else
                {
                    int deadLdtokenSignifier = il.ReadLdcI4();
                    Debug.Assert(deadLdtokenSignifier == 0);
                    il.ReadLdcI4();
                    il.ReadPop();
                    il.ReadPop();
                }
            }
        }
        private Dictionary <MethodDesc, MethodDesc> LoadDynamicInvokeStubs()
        {
            MetadataType typeWithMetadataMappings = (MetadataType)_metadataDescribingModule.GetTypeByCustomAttributeTypeName(MetadataMappingTypeName);
            Dictionary <MethodDesc, MethodDesc> dynamicInvokeMapTable = new Dictionary <MethodDesc, MethodDesc>();
            MethodDesc dynamicInvokeStubDescriptorMethod = typeWithMetadataMappings.GetMethod("DynamicInvokeStubs", null);

            if (dynamicInvokeStubDescriptorMethod == null)
            {
                return(dynamicInvokeMapTable);
            }

            ILProvider     ilProvider = new ILProvider(null);
            ILStreamReader il         = new ILStreamReader(ilProvider.GetMethodIL(dynamicInvokeStubDescriptorMethod));

            // structure is
            // REPEAT N TIMES
            //ldtoken method
            //ldtoken dynamicInvokeStubMethod
            //pop
            //pop
            while (true)
            {
                if (il.TryReadRet()) // ret
                {
                    break;
                }

                MethodDesc method = il.ReadLdtokenAsTypeSystemEntity() as MethodDesc;
                MethodDesc dynamicMethodInvokeStub = il.ReadLdtokenAsTypeSystemEntity() as MethodDesc;
                il.ReadPop();
                il.ReadPop();

                if ((method != null) && (dynamicMethodInvokeStub != null))
                {
                    dynamicInvokeMapTable[method] = dynamicMethodInvokeStub;
                }
                else
                {
                    throw new BadImageFormatException();
                }
            }

            return(dynamicInvokeMapTable);
        }
        private void ReadRequiredTemplates(MethodIL methodIL, HashSet <TypeDesc> typeTemplates, HashSet <MethodDesc> methodTemplates, HashSet <FieldDesc> fieldTemplates)
        {
            ILStreamReader il = new ILStreamReader(methodIL);

            if (!_typeSystemContext.SupportsUniversalCanon)
            {
                return;
            }

            //
            // Types, methods and field tokens listed here are *open* generic definitions determined by the reducer as needing reflection.
            // Type tokens listed are tokens of generic type definitions that will need reflection support.
            // Method tokens listed are either tokens of generic method definitions, or non-generic methods on generic containing type definitions, and need reflection support.
            // Field tokens listed are for fields on generic type definitions that will need reflection support
            // The canonical form supported by the typesystem context will determine how to instantiate the types/methods/fields listed here, and templatize them for
            // reflection support at runtime (templates used by the dynamic TypeLoader component of the runtime).
            //

            // structure is
            // REPEAT N TIMES
            //ldtoken type
            //pop
            while (true)
            {
                if (il.TryReadRet()) // ret
                {
                    break;
                }

                TypeSystemEntity tse;
                il.TryReadLdtokenAsTypeSystemEntity(out tse);
                il.ReadPop();

                if (tse == null)
                {
                    throw new BadImageFormatException();
                }

                if (tse is MetadataType)
                {
                    MetadataType type = (MetadataType)tse;
                    Debug.Assert(type.IsGenericDefinition && type.HasInstantiation);

                    type = _typeSystemContext.GetInstantiatedType(type, GetUniversalCanonicalInstantiation(type.Instantiation.Length));

                    typeTemplates.Add(type);
                }
                else if (tse is MethodDesc)
                {
                    MethodDesc method         = (MethodDesc)tse;
                    TypeDesc   containingType = method.OwningType;

                    Debug.Assert(method.IsTypicalMethodDefinition);
                    Debug.Assert(method.HasInstantiation || method.OwningType.HasInstantiation);

                    if (containingType.HasInstantiation)
                    {
                        containingType = _typeSystemContext.GetInstantiatedType((MetadataType)containingType, GetUniversalCanonicalInstantiation(containingType.Instantiation.Length));
                        method         = containingType.GetMethod(method.Name, method.GetTypicalMethodDefinition().Signature);
                        typeTemplates.Add(containingType);
                    }

                    if (method.HasInstantiation)
                    {
                        method = _typeSystemContext.GetInstantiatedMethod(method, GetUniversalCanonicalInstantiation(method.Instantiation.Length));
                    }

                    methodTemplates.Add(method);
                }
                else if (tse is FieldDesc)
                {
                    FieldDesc field          = (FieldDesc)tse;
                    TypeDesc  containingType = field.OwningType;

                    Debug.Assert(containingType.HasInstantiation && containingType.IsGenericDefinition);

                    containingType = _typeSystemContext.GetInstantiatedType((MetadataType)containingType, GetUniversalCanonicalInstantiation(containingType.Instantiation.Length));
                    field          = containingType.GetField(field.Name);

                    typeTemplates.Add(containingType);
                    fieldTemplates.Add(field);
                }
            }
        }
        private IEnumerable <TypeSystemEntity> ReadRequiredGenericsEntities(MethodIL method)
        {
            ILStreamReader il = new ILStreamReader(method);

            // structure is
            // REPEAT N TIMES
            //ldtoken generic type/method/field
            //pop
            while (true)
            {
                if (il.TryReadRet()) // ret
                {
                    yield break;
                }

                TypeSystemEntity tse;
                il.TryReadLdtokenAsTypeSystemEntity(out tse);
                il.ReadPop();

                if (tse == null)
                {
                    throw new BadImageFormatException();
                }

                if (tse is TypeDesc)
                {
                    if (tse is DefType)
                    {
                        if (((TypeDesc)tse).Instantiation.CheckValidInstantiationArguments() && ((TypeDesc)tse).CheckConstraints())
                        {
                            yield return(tse);
                        }
                    }
                    else if (tse is ByRefType)
                    {
                        // Skip by ref types.
                    }
                    else
                    {
                        throw new BadImageFormatException();
                    }
                }
                else if (tse is FieldDesc)
                {
                    TypeDesc owningType = ((FieldDesc)tse).OwningType;

                    if (owningType.Instantiation.CheckValidInstantiationArguments() && owningType.CheckConstraints())
                    {
                        yield return(tse);
                    }
                }
                else if (tse is MethodDesc)
                {
                    MethodDesc genericMethod = (MethodDesc)tse;

                    if (genericMethod.Instantiation.CheckValidInstantiationArguments() &&
                        genericMethod.OwningType.Instantiation.CheckValidInstantiationArguments() &&
                        genericMethod.CheckConstraints())
                    {
                        // TODO: Detect large number of instantiations of the same method and collapse to using dynamic
                        // USG instantiations at runtime, to avoid infinite generic expansion and large compilation times.
                        yield return(tse);
                    }
                }
            }
        }