/// <summary> /// Does for locals what <see cref="System.Runtime.CompilerServices.DynamicAttribute"/> does for parameters, return types, and fields. /// In particular, indicates which occurences of <see cref="object"/> in the signature are really dynamic. /// </summary> /// <remarks> /// Appears when there are dynamic locals. /// </remarks> public static void ReadDynamicLocalsRecord(byte[] bytes, ref int offset, int size, out ImmutableArray<DynamicLocalBucket> buckets) { int tempOffset = offset; int bucketCount = BitConverter.ToInt32(bytes, tempOffset); tempOffset += 4; var builder = ArrayBuilder<DynamicLocalBucket>.GetInstance(bucketCount); for (int i = 0; i < bucketCount; i++) { const int numFlagBytes = 64; var flags = 0UL; for (int j = 0; j < numFlagBytes; j++) { var flag = bytes[tempOffset + j] != 0; if (flag) { flags |= 1UL << j; } } tempOffset += numFlagBytes; int flagCount = BitConverter.ToInt32(bytes, tempOffset); tempOffset += 4; int slotId = BitConverter.ToInt32(bytes, tempOffset); tempOffset += 4; const int numNameBytes = 128; var pooled = PooledStringBuilder.GetInstance(); var nameBuilder = pooled.Builder; for (int j = 0; j < numNameBytes; j += 2) { char ch = BitConverter.ToChar(bytes, tempOffset + j); if (ch == 0) break; nameBuilder.Append(ch); } tempOffset += numNameBytes; //The Identifier name takes 64 WCHAR no matter how big its actual length is. var name = pooled.ToStringAndFree(); var bucket = new DynamicLocalBucket(flagCount, flags, slotId, name); builder.Add(bucket); } buckets = builder.ToImmutableAndFree(); offset += size - CdiRecordHeaderSize; Debug.Assert(offset >= tempOffset); }
/// <summary> /// Does for locals what <see cref="System.Runtime.CompilerServices.DynamicAttribute"/> does for parameters, return types, and fields. /// In particular, indicates which occurrences of <see cref="object"/> in the signature are really dynamic. /// </summary> /// <remarks> /// Appears when there are dynamic locals. /// </remarks> /// <exception cref="InvalidOperationException">Bad data.</exception> public static ImmutableArray<DynamicLocalBucket> DecodeDynamicLocalsRecord(ImmutableArray<byte> bytes) { int offset = 0; int bucketCount = ReadInt32(bytes, ref offset); var builder = ArrayBuilder<DynamicLocalBucket>.GetInstance(bucketCount); for (int i = 0; i < bucketCount; i++) { const int FlagBytesCount = 64; ulong flags = 0UL; for (int j = 0; j < FlagBytesCount; j++) { var flag = ReadByte(bytes, ref offset) != 0; if (flag) { flags |= 1UL << j; } } int flagCount = ReadInt32(bytes, ref offset); int slotId = ReadInt32(bytes, ref offset); const int NameBytesCount = 128; var pooled = PooledStringBuilder.GetInstance(); var nameBuilder = pooled.Builder; int nameEnd = offset + NameBytesCount; while (offset < nameEnd) { char ch = (char)ReadInt16(bytes, ref offset); if (ch == 0) { // The Identifier name takes 64 WCHAR no matter how big its actual length is. offset = nameEnd; break; } nameBuilder.Append(ch); } var name = pooled.ToStringAndFree(); var bucket = new DynamicLocalBucket(flagCount, flags, slotId, name); builder.Add(bucket); } return builder.ToImmutableAndFree(); }