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 void WritePrimitive() { var writer = new BlobBuilder(17); writer.WriteUInt32(0x11223344); writer.WriteUInt16(0x5566); writer.WriteByte(0x77); writer.WriteUInt64(0x8899aabbccddeeff); writer.WriteInt32(-1); writer.WriteInt16(-2); writer.WriteSByte(-3); writer.WriteBoolean(true); writer.WriteBoolean(false); writer.WriteInt64(unchecked ((long)0xfedcba0987654321)); writer.WriteDateTime(new DateTime(0x1112223334445556)); writer.WriteDecimal(102030405060.70m); writer.WriteDouble(double.NaN); writer.WriteSingle(float.NegativeInfinity); var guid = new Guid("01020304-0506-0708-090A-0B0C0D0E0F10"); writer.WriteBytes(guid.ToByteArray()); writer.WriteGuid(guid); AssertEx.Equal(new byte[] { 0x44, 0x33, 0x22, 0x11, 0x66, 0x55, 0x77, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfd, 0x01, 0x00, 0x21, 0x43, 0x65, 0x87, 0x09, 0xBA, 0xDC, 0xFE, 0x56, 0x55, 0x44, 0x34, 0x33, 0x22, 0x12, 0x11, 0x02, 0xD6, 0xE0, 0x9A, 0x94, 0x47, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x80, 0xFF, 0x04, 0x03, 0x02, 0x01, 0x06, 0x05, 0x08, 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x04, 0x03, 0x02, 0x01, 0x06, 0x05, 0x08, 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 }, writer.ToArray()); }
public void WritePrimitive() { var writer = new BlobBuilder(17); writer.WriteUInt32(0x11223344); writer.WriteUInt16(0x5566); writer.WriteByte(0x77); writer.WriteUInt64(0x8899aabbccddeeff); writer.WriteInt32(-1); writer.WriteInt16(-2); writer.WriteSByte(-3); writer.WriteBoolean(true); writer.WriteBoolean(false); writer.WriteInt64(unchecked((long)0xfedcba0987654321)); writer.WriteDateTime(new DateTime(0x1112223334445556)); writer.WriteDecimal(102030405060.70m); writer.WriteDouble(double.NaN); writer.WriteSingle(float.NegativeInfinity); var guid = new Guid("01020304-0506-0708-090A-0B0C0D0E0F10"); writer.WriteBytes(guid.ToByteArray()); writer.WriteGuid(guid); AssertEx.Equal(new byte[] { 0x44, 0x33, 0x22, 0x11, 0x66, 0x55, 0x77, 0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xfd, 0x01, 0x00, 0x21, 0x43, 0x65, 0x87, 0x09, 0xBA, 0xDC, 0xFE, 0x56, 0x55, 0x44, 0x34, 0x33, 0x22, 0x12, 0x11, 0x02, 0xD6, 0xE0, 0x9A, 0x94, 0x47, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x80, 0xFF, 0x04, 0x03, 0x02, 0x01, 0x06, 0x05, 0x08, 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x04, 0x03, 0x02, 0x01, 0x06, 0x05, 0x08, 0x07, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 }, writer.ToArray()); }
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)); }