Example #1
0
        /// <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();
        }