Exemplo n.º 1
0
        private unsafe static void ConvertConstantSignature(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 double d)
                    {
                        // GeneralConstant: VALUETYPE TypeDefOrRefOrSpecEncoded <date-time>
                        builder.WriteByte((byte)SignatureTypeKind.ValueType);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                        builder.WriteDateTime(new DateTime(BitConverter.DoubleToInt64Bits(d)));
                    }
                    else if (value is 0 && rawTypeCode == (byte)SignatureTypeKind.Class)
                    {
                        // 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 = AssemblyDisplayNameBuilder.GetConstantTypeCode(value);
                        builder.WriteByte((byte)enumTypeCode);
                        builder.WriteConstant(value);
                        builder.WriteCompressedInteger(typeRefDefSpec);
                    }

                    break;
        public BlobHandle GetConstantBlob(object value)
        {
            string str = value as string;

            if (str != null)
            {
                return(this.GetBlob(str));
            }

            var writer = new BlobBuilder();

            writer.WriteConstant(value);
            return(this.GetBlob(writer));
        }
        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 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;

            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));
        }