Example #1
0
        void ParseTypeHandle()
        {
            int token            = MetadataTokens.GetToken(_input.ReadTypeHandle());
            int newToken         = _getAlternateStreamToken(token);
            int newEncodedHandle = CodedIndex.TypeDefOrRefOrSpec(MetadataTokens.EntityHandle(newToken));

            _output.WriteCompressedInteger(newEncodedHandle);
        }
Example #2
0
        public void TypeDefOrRefOrSpec()
        {
            Assert.Equal(0, CodedIndex.TypeDefOrRefOrSpec(default(TypeDefinitionHandle)));
            Assert.Equal((0xffffff << 2) | 2, CodedIndex.TypeDefOrRefOrSpec(MetadataTokens.TypeSpecificationHandle(0xffffff)));

            Assert.Equal(0x04 | 0, CodedIndex.TypeDefOrRefOrSpec(MetadataTokens.TypeDefinitionHandle(1)));
            Assert.Equal(0x04 | 1, CodedIndex.TypeDefOrRefOrSpec(MetadataTokens.TypeReferenceHandle(1)));
            Assert.Equal(0x04 | 2, CodedIndex.TypeDefOrRefOrSpec(MetadataTokens.TypeSpecificationHandle(1)));
        }
Example #3
0
        private void DeclareInterfacesAndCreateInterfaceMap(Type type, TypeDefinitionHandle handle)
        {
            // Only add those interfaces that are not already implemented by the base type.
            // This prevents the generation of assembly dependencies not covered by the
            // GetReferencedAssemblies method.
            HashSet <Type> interfaces
                = new HashSet <Type>((type.BaseType is null
                   ? type.GetInterfaces()
                   : type.GetInterfaces().Except(type.BaseType.GetInterfaces()))
                                     .OrderBy(t => CodedIndex.TypeDefOrRefOrSpec(_metadata.GetTypeHandle(t))));

            foreach (var ifc in interfaces)
            {
                _metadata.Builder.AddInterfaceImplementation(handle, _metadata.GetTypeHandle(ifc));
            }

            // If the type is an interface there may be no interface map.
            // TODO: This isn't necessarily true for Default interface methods.
            if (type.IsInterface)
            {
                return;
            }

            // Build the interface map.
            // All interfaces need to be considered (not just the ones added by the type) because
            // the type may override interface methods of interfaces implemented by the base type.
            // It is also possible for a type to use a base type method to implement an interface
            // method of an interface added by the type. For these reasons it is not sufficient
            // to only use the interfaces declared by a type or look at the declaring type of a
            // method implementing an interface method.
            foreach (var ifcm in from ifc in type.GetInterfaces() select type.GetInterfaceMap(ifc))
            {
                bool implementedByType = interfaces.Contains(ifcm.InterfaceType);

                for (int i = 0; i < ifcm.InterfaceMethods.Length; ++i)
                {
                    MethodInfo targetMethod = ifcm.TargetMethods[i];
                    MethodInfo ifcMethod    = ifcm.InterfaceMethods[i];

                    // Declare a method override either when the interface implementation or
                    // the interface method implementation is declared by the type.
                    if (implementedByType || targetMethod.DeclaringType.Equals(type))
                    {
                        // Mark the target method as implementing the interface method.
                        // (This is the equivalent of .Override in msil)
                        _metadata.Builder.AddMethodImplementation(
                            (TypeDefinitionHandle)_metadata.GetTypeHandle(targetMethod.DeclaringType),
                            _metadata.GetMethodHandle(targetMethod),
                            _metadata.GetMethodHandle(ifcMethod));
                    }
                }
            }
        }
        public void Type(EntityHandle type, string?alias = null)
        {
            if (alias != null)
            {
                // <import> ::= AliasType <alias> <target-type>
                Builder.WriteByte((byte)ImportDefinitionKind.AliasType);
                Builder.WriteCompressedInteger(MetadataTokens.GetHeapOffset(MetadataBuilder.GetOrAddBlobUTF8(alias)));
            }
            else
            {
                // <import> ::= ImportType <target-type>
                Builder.WriteByte((byte)ImportDefinitionKind.ImportType);
            }

            Builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(type));
        }
Example #5
0
        private static TypeSignature _forClassOrValueType(EntityHandle handle, bool isValueType)
        {
            if (handle.IsNil)
            {
                throw new ArgumentException("Handle for a class or value type must not be null.", nameof(handle));
            }

            var builder = TypeSignatureBuilder.getInstance();

            try {
                builder.appendByte((byte)(isValueType ? SignatureTypeKind.ValueType : SignatureTypeKind.Class));
                builder.appendCompressedUnsignedInt(CodedIndex.TypeDefOrRefOrSpec(handle));
                return(builder.makeSignature());
            }
            finally {
                builder.clear();
            }
        }
Example #6
0
        public void Errors()
        {
            var badHandleKind = CustomAttributeHandle.FromRowId(1);

            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.HasCustomAttribute(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.HasConstant(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.CustomAttributeType(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.HasDeclSecurity(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.HasFieldMarshal(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.HasSemantics(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.Implementation(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.MemberForwarded(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.MemberRefParent(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.MethodDefOrRef(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.ResolutionScope(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.TypeDefOrRef(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.TypeDefOrRefOrSpec(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.TypeOrMethodDef(badHandleKind));
            AssertExtensions.Throws <ArgumentException>(null, () => CodedIndex.HasCustomDebugInformation(badHandleKind));
        }
            public void EmitAtCurrentIndexStack(BlobBuilder signatureBuilder)
            {
                if (!Complete)
                {
                    if (_embeddedDataIndex < _embeddedData.Length)
                    {
                        string indexData = string.Join(".", _indexStack);
                        while ((_embeddedDataIndex < _embeddedData.Length) && _embeddedData[_embeddedDataIndex].index == indexData)
                        {
                            switch (_embeddedData[_embeddedDataIndex].kind)
                            {
                            case EmbeddedSignatureDataKind.OptionalCustomModifier:
                            {
                                signatureBuilder.WriteByte((byte)SignatureTypeCode.OptionalModifier);
                                EntityHandle handle = _metadataEmitter.GetTypeRef((MetadataType)_embeddedData[_embeddedDataIndex].type);
                                signatureBuilder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(handle));
                            }
                            break;

                            case EmbeddedSignatureDataKind.RequiredCustomModifier:
                            {
                                signatureBuilder.WriteByte((byte)SignatureTypeCode.RequiredModifier);
                                EntityHandle handle = _metadataEmitter.GetTypeRef((MetadataType)_embeddedData[_embeddedDataIndex].type);
                                signatureBuilder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(handle));
                            }
                            break;

                            case EmbeddedSignatureDataKind.ArrayShape:
                                return;

                            default:
                                throw new NotImplementedException();
                            }

                            _embeddedDataIndex++;
                        }
                    }
                }
            }
        private void SerializeImport(BlobBuilder writer, UsedNamespaceOrType import)
        {
            if (import.TargetXmlNamespaceOpt != null)
            {
                Debug.Assert(import.TargetNamespaceOpt == null);
                Debug.Assert(import.TargetAssemblyOpt == null);
                Debug.Assert(import.TargetTypeOpt == null);

                // <import> ::= ImportXmlNamespace <alias> <target-namespace>
                writer.WriteByte((byte)ImportDefinitionKind.ImportXmlNamespace);
                writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(_debugMetadataOpt.GetOrAddBlobUTF8(import.AliasOpt)));
                writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(_debugMetadataOpt.GetOrAddBlobUTF8(import.TargetXmlNamespaceOpt)));
            }
            else if (import.TargetTypeOpt != null)
            {
                Debug.Assert(import.TargetNamespaceOpt == null);
                Debug.Assert(import.TargetAssemblyOpt == null);

                if (import.AliasOpt != null)
                {
                    // <import> ::= AliasType <alias> <target-type>
                    writer.WriteByte((byte)ImportDefinitionKind.AliasType);
                    writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(_debugMetadataOpt.GetOrAddBlobUTF8(import.AliasOpt)));
                }
                else
                {
                    // <import> ::= ImportType <target-type>
                    writer.WriteByte((byte)ImportDefinitionKind.ImportType);
                }

                writer.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(import.TargetTypeOpt))); // TODO: index in release build
            }
            else if (import.TargetNamespaceOpt != null)
            {
                if (import.TargetAssemblyOpt != null)
                {
                    if (import.AliasOpt != null)
                    {
                        // <import> ::= AliasAssemblyNamespace <alias> <target-assembly> <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.AliasAssemblyNamespace);
                        writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(_debugMetadataOpt.GetOrAddBlobUTF8(import.AliasOpt)));
                    }
                    else
                    {
                        // <import> ::= ImportAssemblyNamespace <target-assembly> <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.ImportAssemblyNamespace);
                    }

                    writer.WriteCompressedInteger(MetadataTokens.GetRowNumber(GetAssemblyReferenceHandle(import.TargetAssemblyOpt)));
                }
                else
                {
                    if (import.AliasOpt != null)
                    {
                        // <import> ::= AliasNamespace <alias> <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.AliasNamespace);
                        writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(_debugMetadataOpt.GetOrAddBlobUTF8(import.AliasOpt)));
                    }
                    else
                    {
                        // <import> ::= ImportNamespace <target-namespace>
                        writer.WriteByte((byte)ImportDefinitionKind.ImportNamespace);
                    }
                }

                // TODO: cache?
                string namespaceName = TypeNameSerializer.BuildQualifiedNamespaceName(import.TargetNamespaceOpt);
                writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(_debugMetadataOpt.GetOrAddBlobUTF8(namespaceName)));
            }
            else
            {
                // <import> ::= ImportReferenceAlias <alias>
                Debug.Assert(import.AliasOpt != null);
                Debug.Assert(import.TargetAssemblyOpt == null);

                writer.WriteByte((byte)ImportDefinitionKind.ImportAssemblyReferenceAlias);
                writer.WriteCompressedInteger(MetadataTokens.GetHeapOffset(_debugMetadataOpt.GetOrAddBlobUTF8(import.AliasOpt)));
            }
        }
        private BlobHandle SerializeLocalConstantSignature(ILocalDefinition localConstant)
        {
            var builder = new BlobBuilder();

            // TODO: BlobEncoder.LocalConstantSignature

            // CustomMod*
            var encoder = new CustomModifiersEncoder(builder);

            SerializeCustomModifiers(encoder, localConstant.CustomModifiers);

            var type     = localConstant.Type;
            var typeCode = type.TypeCode(Context);

            object value = localConstant.CompileTimeValue.Value;

            // PrimitiveConstant or EnumConstant
            if (value is decimal)
            {
                builder.WriteByte((byte)SignatureTypeKind.ValueType);
                builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type)));

                builder.WriteDecimal((decimal)value);
            }
            else if (value is DateTime)
            {
                builder.WriteByte((byte)SignatureTypeKind.ValueType);
                builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type)));

                builder.WriteDateTime((DateTime)value);
            }
            else if (typeCode == PrimitiveTypeCode.String)
            {
                builder.WriteByte((byte)ConstantTypeCode.String);
                if (value == null)
                {
                    builder.WriteByte(0xff);
                }
                else
                {
                    builder.WriteUTF16((string)value);
                }
            }
            else if (value != null)
            {
                // TypeCode
                builder.WriteByte((byte)GetConstantTypeCode(value));

                // Value
                builder.WriteConstant(value);

                // EnumType
                if (type.IsEnum)
                {
                    builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type)));
                }
            }
            else if (this.module.IsPlatformType(type, PlatformType.SystemObject))
            {
                builder.WriteByte((byte)SignatureTypeCode.Object);
            }
            else
            {
                builder.WriteByte((byte)(type.IsValueType ? SignatureTypeKind.ValueType : SignatureTypeKind.Class));
                builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type)));
            }

            return(_debugMetadataOpt.GetOrAddBlob(builder));
        }
        public unsafe static void Convert(BlobBuilder builder, MetadataModel metadataModel, byte[] signature, object value)
        {
            fixed(byte *sigPtr = signature)
            {
                var sigReader = new BlobReader(sigPtr, signature.Length);

                // copy custom modifiers over:
                byte rawTypeCode;

                while (true)
                {
                    rawTypeCode = sigReader.ReadByte();
                    if (rawTypeCode != (int)SignatureTypeCode.OptionalModifier && rawTypeCode != (int)SignatureTypeCode.RequiredModifier)
                    {
                        break;
                    }

                    builder.WriteByte(rawTypeCode);
                    builder.WriteCompressedInteger(sigReader.ReadCompressedInteger());
                }

                switch ((SignatureTypeCode)rawTypeCode)
                {
                case (SignatureTypeCode)SignatureTypeKind.Class:
                case (SignatureTypeCode)SignatureTypeKind.ValueType:
                    int typeRefDefSpec = sigReader.ReadCompressedInteger();

                    if (value is decimal)
                    {
                        // GeneralConstant: VALUETYPE TypeDefOrRefOrSpecEncoded <decimal>
                        builder.WriteByte((byte)SignatureTypeKind.ValueType);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                        builder.WriteDecimal((decimal)value);
                    }
                    else if (value is DateTime)
                    {
                        // GeneralConstant: VALUETYPE TypeDefOrRefOrSpecEncoded <date-time>
                        builder.WriteByte((byte)SignatureTypeKind.ValueType);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                        builder.WriteDateTime((DateTime)value);
                    }
                    else if (value == null)
                    {
                        // GeneralConstant: CLASS TypeDefOrRefOrSpecEncoded
                        builder.WriteByte(rawTypeCode);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                    }
                    else
                    {
                        // EnumConstant ::= EnumTypeCode EnumValue EnumType
                        // EnumTypeCode ::= BOOLEAN | CHAR | I1 | U1 | I2 | U2 | I4 | U4 | I8 | U8
                        // EnumType     ::= TypeDefOrRefOrSpecEncoded

                        var enumTypeCode = MetadataHelpers.GetConstantTypeCode(value);
                        builder.WriteByte((byte)enumTypeCode);
                        builder.WriteConstant(value);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                    }

                    break;

                case SignatureTypeCode.Object:
                    // null:
                    Debug.Assert(value == null);
                    builder.WriteByte((byte)SignatureTypeCode.Object);
                    break;

                case SignatureTypeCode.Boolean:
                case SignatureTypeCode.Char:
                case SignatureTypeCode.SByte:
                case SignatureTypeCode.Byte:
                case SignatureTypeCode.Int16:
                case SignatureTypeCode.UInt16:
                case SignatureTypeCode.Int32:
                case SignatureTypeCode.UInt32:
                case SignatureTypeCode.Int64:
                case SignatureTypeCode.UInt64:
                case SignatureTypeCode.Single:
                case SignatureTypeCode.Double:
                case SignatureTypeCode.String:
                    // PrimitiveConstant
                    builder.WriteByte(rawTypeCode);
                    builder.WriteConstant(value);
                    break;

                case SignatureTypeCode.SZArray:
                case SignatureTypeCode.Array:
                case SignatureTypeCode.GenericTypeInstance:
                    Debug.Assert(value == null);

                    // Find an existing TypeSpec in metadata.
                    // If there isn't one we can't represent the constant type in the Portable PDB, use Object.

                    // +1/-1 for the type code we already read.
                    var spec = new byte[sigReader.RemainingBytes + 1];
                    Buffer.BlockCopy(signature, sigReader.Offset - 1, spec, 0, spec.Length);

                    TypeSpecificationHandle typeSpec;
                    if (metadataModel.TryResolveTypeSpecification(spec, out typeSpec))
                    {
                        builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(typeSpec));
                    }
                    else
                    {
                        // TODO: warning - can't translate const type
                        builder.WriteByte((byte)SignatureTypeCode.Object);
                    }

                    break;

                case SignatureTypeCode.GenericMethodParameter:
                case SignatureTypeCode.GenericTypeParameter:
                case SignatureTypeCode.FunctionPointer:
                case SignatureTypeCode.Pointer:
                    // generic parameters, pointers are not valid types for constants:
                    throw new BadImageFormatException();
                }
            }
        }
        private void CreateType(Type type)
        {
            // Check reserved and not already emitted
            if (!_metadata.TryGetTypeDefinition(type, out var metadata))
            {
                ThrowMetadataIsNotReserved("Type", type);
            }
            EnsureMetadataWasNotEmitted(metadata, type);

            // Add the type definition
            var baseTypeHandle = type.BaseType != null?_metadata.GetTypeHandle(type.BaseType) : default;

            var typeHandle = _metadata.Builder.AddTypeDefinition(
                type.Attributes,
                type.DeclaringType == null ? _metadata.GetOrAddString(ApplyNameChange(type.Namespace)) : default(StringHandle),
                _metadata.GetOrAddString(type.Name),
                baseTypeHandle,
                MetadataTokens.FieldDefinitionHandle(_metadata.Builder.GetRowCount(TableIndex.Field) + 1),
                MetadataTokens.MethodDefinitionHandle(_metadata.Builder.GetRowCount(TableIndex.MethodDef) + 1));

            // Verify and mark emitted
            VerifyEmittedHandle(metadata, typeHandle);
            metadata.MarkAsEmitted();

            // Setup pack and size attributes (if explicit layout)
            if (type.IsExplicitLayout)
            {
                _metadata.Builder.AddTypeLayout(
                    typeHandle,
                    (ushort)type.StructLayoutAttribute.Pack,
                    (uint)type.StructLayoutAttribute.Size
                    );
            }

            // Add implemented interfaces (not for enums though - eg: IComparable etc...)
            if (!type.IsEnum)
            {
                foreach (var itf in type.GetInterfaces().OrderBy(t => CodedIndex.TypeDefOrRefOrSpec(_metadata.GetTypeHandle(t))))
                {
                    _metadata.Builder.AddInterfaceImplementation(typeHandle, _metadata.GetTypeHandle(itf));
                }
            }

            // Setup enclosing type
            if (type.DeclaringType != null)
            {
                _metadata.Builder.AddNestedType(typeHandle, (TypeDefinitionHandle)_metadata.GetTypeHandle(type.DeclaringType));
            }

            // Create attributes
            CreateCustomAttributes(typeHandle, type.GetCustomAttributesData());

            // Handle generics type
            if (type.IsGenericType)
            {
                if (type.IsGenericTypeDefinition)
                {
                    var genericType = type.GetGenericTypeDefinition();
                    var typeInfo    = genericType.GetTypeInfo();

                    for (var i = 0; i < typeInfo.GenericTypeParameters.Length; ++i)
                    {
                        var parm = typeInfo.GenericTypeParameters[i];
                        var attr = parm.GenericParameterAttributes;

                        var genericParameterHandle =
                            _metadata.Builder.AddGenericParameter(typeHandle, attr, _metadata.GetOrAddString(parm.Name),
                                                                  i);

                        foreach (var constraint in parm.GetGenericParameterConstraints())
                        {
                            _metadata.Builder.AddGenericParameterConstraint(genericParameterHandle,
                                                                            _metadata.GetTypeHandle(constraint));
                        }
                    }
                }
            }

            // Create members...
            CreateFields(type.GetFields(AllFields));
            CreatePropertiesForType(type.GetProperties(AllProperties));
            CreateEventsForType(type.GetEvents(AllEvents));
            CreateConstructors(type.GetConstructors(AllMethods));
            CreateMethods(type.GetMethods(AllMethods));
        }
        public static ReadyToRunStandaloneMethodMetadata Compute(EcmaMethod wrappedMethod)
        {
            var metadataReader = wrappedMethod.MetadataReader;
            var _module        = wrappedMethod.Module;
            var rva            = wrappedMethod.MetadataReader.GetMethodDefinition(wrappedMethod.Handle).RelativeVirtualAddress;
            var _methodBody    = _module.PEReader.GetMethodBody(rva);

            byte[] _alternateILStream = _methodBody.GetILBytes();

            var exceptionRegions = _methodBody.ExceptionRegions;

            ILExceptionRegion[] _exceptionRegions;

            int length = exceptionRegions.Length;

            if (length == 0)
            {
                _exceptionRegions = Array.Empty <ILExceptionRegion>();
            }
            else
            {
                _exceptionRegions = new ILExceptionRegion[length];
                for (int i = 0; i < length; i++)
                {
                    var exceptionRegion = exceptionRegions[i];

                    _exceptionRegions[i] = new ILExceptionRegion(
                        (ILExceptionRegionKind)exceptionRegion.Kind, // assumes that ILExceptionRegionKind and ExceptionRegionKind enums are in sync
                        exceptionRegion.TryOffset,
                        exceptionRegion.TryLength,
                        exceptionRegion.HandlerOffset,
                        exceptionRegion.HandlerLength,
                        MetadataTokens.GetToken(exceptionRegion.CatchType),
                        exceptionRegion.FilterOffset);
                }
            }

            BlobReader localsBlob = default(BlobReader);

            if (!_methodBody.LocalSignature.IsNil)
            {
                localsBlob = wrappedMethod.MetadataReader.GetBlobReader(wrappedMethod.MetadataReader.GetStandaloneSignature(_methodBody.LocalSignature).Signature);
            }

            AlternativeTypeRefProvider alternateTypes = new AlternativeTypeRefProvider();
            EcmaSignatureEncoder <AlternativeTypeRefProvider> alternateEncoder = new EcmaSignatureEncoder <AlternativeTypeRefProvider>(alternateTypes);
            Dictionary <int, int> _alternateNonTokenStrings  = new Dictionary <int, int>();
            BlobBuilder           _alternateNonTypeRefStream = new BlobBuilder();
            BlobBuilder           _nonCodeAlternateBlob      = new BlobBuilder();

            {
                // Generate alternate stream for exceptions.
                _nonCodeAlternateBlob.WriteCompressedInteger(_exceptionRegions.Length);

                for (int i = 0; i < _exceptionRegions.Length; i++)
                {
                    var region = _exceptionRegions[i];
                    _nonCodeAlternateBlob.WriteCompressedInteger((int)region.Kind);
                    _nonCodeAlternateBlob.WriteCompressedInteger((int)region.TryOffset);
                    _nonCodeAlternateBlob.WriteCompressedInteger((int)region.TryLength);
                    _nonCodeAlternateBlob.WriteCompressedInteger((int)region.HandlerOffset);
                    _nonCodeAlternateBlob.WriteCompressedInteger((int)region.HandlerLength);
                    if (region.Kind == ILExceptionRegionKind.Catch)
                    {
                        int alternateToken = GetAlternateStreamToken(region.ClassToken);
                        int encodedToken   = CodedIndex.TypeDefOrRefOrSpec(MetadataTokens.EntityHandle(alternateToken));
                        _nonCodeAlternateBlob.WriteCompressedInteger(encodedToken);
                    }
                    else if (region.Kind == ILExceptionRegionKind.Filter)
                    {
                        _nonCodeAlternateBlob.WriteCompressedInteger(region.FilterOffset);
                    }
                }

                if (localsBlob.Length == 0)
                {
                    // No locals. Encode a 2 to indicate this
                    _nonCodeAlternateBlob.WriteByte(2);
                }
                else
                {
                    _nonCodeAlternateBlob.WriteByte(_methodBody.LocalVariablesInitialized ? (byte)1 : (byte)0);
                    EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(localsBlob, _nonCodeAlternateBlob, GetAlternateStreamToken);
                    sigTranslator.ParseLocalsSignature();
                }
            }

            ILTokenReplacer.Replace(_alternateILStream, GetAlternateStreamToken);

            // Add all the streams together into the _nonCodeAlternateBlob
            int expectedFinalSize = _nonCodeAlternateBlob.Count + _alternateILStream.Length + _alternateNonTypeRefStream.Count;

            _nonCodeAlternateBlob.WriteBytes(_alternateILStream);
            _nonCodeAlternateBlob.LinkSuffix(_alternateNonTypeRefStream);
            Debug.Assert(expectedFinalSize == _nonCodeAlternateBlob.Count);

            ReadyToRunStandaloneMethodMetadata methodBlock = new ReadyToRunStandaloneMethodMetadata();

            methodBlock.ConstantData = _nonCodeAlternateBlob.ToArray();
            methodBlock.TypeRefs     = alternateTypes._alternateTypeRefStream.ToArray();
            return(methodBlock);

            ///// HELPER FUNCTIONS

            unsafe int GetAlternateStreamToken(int token)
            {
                if (token == 0 || !_alternateNonTokenStrings.TryGetValue(token, out int alternateToken))
                {
                    var handle = MetadataTokens.Handle(token);

                    if (handle.Kind == HandleKind.TypeDefinition || handle.Kind == HandleKind.TypeReference)
                    {
                        EcmaType ecmaType = (EcmaType)wrappedMethod.Module.GetObject(MetadataTokens.EntityHandle(token));
                        alternateToken = MetadataTokens.GetToken(alternateTypes.GetTypeDefOrRefHandleForTypeDesc(ecmaType));
                    }
                    else
                    {
                        BlobBuilder blob = new BlobBuilder();
                        int         flag = 0;
                        if (handle.Kind == HandleKind.UserString)
                        {
                            string strAlternate = metadataReader.GetUserString((UserStringHandle)handle);
                            flag = 0x70000000;
                            blob.WriteCompressedInteger(strAlternate.Length);
                            fixed(char *charData = strAlternate)
                            {
                                blob.WriteBytes((byte *)charData, strAlternate.Length * 2);
                            }

                            // TODO: consider encoding via wtf-8, or possibly utf-8
                        }
                        else if (handle.Kind == HandleKind.TypeSpecification)
                        {
                            flag = 0x1B000000;
                            var sigBlob = metadataReader.GetBlobReader(metadataReader.GetTypeSpecification((TypeSpecificationHandle)handle).Signature);
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseType();
                        }
                        else if (handle.Kind == HandleKind.MemberReference)
                        {
                            flag = 0x0a000000;
                            var memberReference = metadataReader.GetMemberReference((MemberReferenceHandle)handle);
                            var sigBlob         = metadataReader.GetBlobReader(memberReference.Signature);
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseMemberRefSignature();
                            blob.WriteSerializedString(metadataReader.GetString(memberReference.Name));
                            blob.WriteCompressedInteger(CodedIndex.MemberRefParent(MetadataTokens.EntityHandle(GetAlternateStreamToken(MetadataTokens.GetToken(memberReference.Parent)))));
                        }
                        else if (handle.Kind == HandleKind.MethodDefinition)
                        {
                            flag = 0x0a000000;
                            var methodDefinition = metadataReader.GetMethodDefinition((MethodDefinitionHandle)handle);
                            var sigBlob          = metadataReader.GetBlobReader(methodDefinition.Signature);
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseMethodSignature();
                            blob.WriteSerializedString(metadataReader.GetString(methodDefinition.Name));
                            blob.WriteCompressedInteger(CodedIndex.MemberRefParent(MetadataTokens.EntityHandle(GetAlternateStreamToken(MetadataTokens.GetToken(methodDefinition.GetDeclaringType())))));
                        }
                        else if (handle.Kind == HandleKind.FieldDefinition)
                        {
                            flag = 0x0a000000;
                            var fieldDefinition = metadataReader.GetFieldDefinition((FieldDefinitionHandle)handle);
                            var sigBlob         = metadataReader.GetBlobReader(fieldDefinition.Signature);
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseFieldSignature();
                            blob.WriteSerializedString(metadataReader.GetString(fieldDefinition.Name));
                            blob.WriteCompressedInteger(CodedIndex.MemberRefParent(MetadataTokens.EntityHandle(GetAlternateStreamToken(MetadataTokens.GetToken(fieldDefinition.GetDeclaringType())))));
                        }
                        else if (handle.Kind == HandleKind.MethodSpecification)
                        {
                            flag = 0x2B000000;
                            var methodSpecification = metadataReader.GetMethodSpecification((MethodSpecificationHandle)handle);
                            var sigBlob             = metadataReader.GetBlobReader(methodSpecification.Signature);
                            blob.WriteCompressedInteger(MetadataTokens.GetRowNumber(MetadataTokens.EntityHandle(GetAlternateStreamToken(MetadataTokens.GetToken(methodSpecification.Method)))));
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseMethodSpecSignature();
                        }
                        else if (handle.Kind == HandleKind.StandaloneSignature)
                        {
                            flag = 0x11000000;
                            var reader  = wrappedMethod.Module.MetadataReader;
                            var sigBlob = reader.GetBlobReader(reader.GetStandaloneSignature((StandaloneSignatureHandle)handle).Signature);
                            EcmaSignatureTranslator sigTranslator = new EcmaSignatureTranslator(sigBlob, blob, GetAlternateStreamToken);
                            sigTranslator.ParseMethodSignature();
                        }

                        _alternateNonTypeRefStream.WriteBytes(blob.ToArray());
                        alternateToken = (_alternateNonTokenStrings.Count + 1) | flag;
                    }
                    _alternateNonTokenStrings.Add(token, alternateToken);
                }

                return(alternateToken);
            }
        }