internal static ImmutableArray <byte> CreateBlob(ArraySegment <byte> bytes)
        {
            Debug.Assert(bytes.Array != null);

            if (bytes.Count < CompressionThreshold)
            {
                using (Cci.PooledBlobBuilder builder = Cci.PooledBlobBuilder.GetInstance())
                {
                    builder.WriteInt32(0);
                    builder.WriteBytes(bytes.Array, bytes.Offset, bytes.Count);
                    return(builder.ToImmutableArray());
                }
            }
            else
            {
                using (BlobBuildingStream builder = BlobBuildingStream.GetInstance())
                {
                    builder.WriteInt32(bytes.Count);

                    using (CountingDeflateStream deflater = new CountingDeflateStream(builder, CompressionLevel.Optimal, leaveOpen: true))
                    {
                        deflater.Write(bytes.Array, bytes.Offset, bytes.Count);
                    }

                    return(builder.ToImmutableArray());
                }
            }
        }
        /// <summary>
        /// Creates the blob to be saved to the PDB.
        /// </summary>
        internal static ImmutableArray <byte> CreateBlob(Stream stream)
        {
            Debug.Assert(stream != null);
            Debug.Assert(stream.CanRead);
            Debug.Assert(stream.CanSeek);

            long longLength = stream.Length;

            Debug.Assert(longLength >= 0);

            if (longLength > int.MaxValue)
            {
                throw new IOException(CodeAnalysisResources.StreamIsTooLong);
            }

            stream.Seek(0, SeekOrigin.Begin);
            int length = (int)longLength;

            if (length < CompressionThreshold)
            {
                using (Cci.PooledBlobBuilder builder = Cci.PooledBlobBuilder.GetInstance())
                {
                    builder.WriteInt32(0);
                    int bytesWritten = builder.TryWriteBytes(stream, length);

                    if (length != bytesWritten)
                    {
                        throw new EndOfStreamException();
                    }

                    return(builder.ToImmutableArray());
                }
            }
            else
            {
                using (BlobBuildingStream builder = BlobBuildingStream.GetInstance())
                {
                    builder.WriteInt32(length);

                    using (CountingDeflateStream deflater = new CountingDeflateStream(builder, CompressionLevel.Optimal, leaveOpen: true))
                    {
                        stream.CopyTo(deflater);

                        if (length != deflater.BytesWritten)
                        {
                            throw new EndOfStreamException();
                        }
                    }

                    return(builder.ToImmutableArray());
                }
            }
        }
示例#3
0
        private void RealizeBlocks()
        {
            // drop dead code.
            // We do not want to deal with unreachable code even when not optimizing.
            // sometimes dead code may have subtle verification violations
            // for example illegal fall-through in unreachable code is still illegal,
            // but compiler will not enforce returning from dead code.
            // it is easier to just remove dead code than make sure it is all valid
            MarkReachableBlocks();
            RewriteSpecialBlocks();
            DropUnreachableBlocks();

            if (_optimizations == OptimizationLevel.Release && OptimizeLabels())
            {
                // redo unreachable code elimination if some labels were optimized
                // as that could result in more dead code.
                MarkAllBlocksUnreachable();
                MarkReachableBlocks();
                DropUnreachableBlocks();
            }

            // some gotos must become leaves
            RewriteBranchesAcrossExceptionHandlers();

            // now we can compute block offsets and adjust branches
            while (ComputeOffsetsAndAdjustBranches())
            {
                // if branches were optimized, we may have more unreachable code
                // redo unreachable code elimination and if anything was dropped redo adjusting.
                MarkAllBlocksUnreachable();
                MarkReachableBlocks();
                if (!DropUnreachableBlocks())
                {
                    // nothing was dropped, we are done adjusting
                    break;
                }
            }

            // Now linearize everything with computed offsets.
            Cci.PooledBlobBuilder writer = Cci.PooledBlobBuilder.GetInstance();

            for (BasicBlock block = leaderBlock; block != null; block = block.NextBlock)
            {
                // If the block has any IL markers, we can calculate their real IL offsets now
                int blockFirstMarker = block.FirstILMarker;
                if (blockFirstMarker >= 0)
                {
                    int blockLastMarker = block.LastILMarker;
                    Debug.Assert(blockLastMarker >= blockFirstMarker);
                    for (int i = blockFirstMarker; i <= blockLastMarker; i++)
                    {
                        int blockOffset    = _allocatedILMarkers[i].BlockOffset;
                        int absoluteOffset = writer.Count + blockOffset;
                        _allocatedILMarkers[i] = new ILMarker()
                        {
                            BlockOffset = blockOffset, AbsoluteOffset = absoluteOffset
                        };
                    }
                }

                block.RegularInstructions?.WriteContentTo(writer);

                switch (block.BranchCode)
                {
                case ILOpCode.Nop:
                    break;

                case ILOpCode.Switch:
                    // switch (N, t1, t2... tN)
                    //  IL ==> ILOpCode.Switch < unsigned int32 > < int32 >... < int32 >

                    WriteOpCode(writer, ILOpCode.Switch);

                    SwitchBlock switchBlock = (SwitchBlock)block;
                    writer.WriteUInt32(switchBlock.BranchesCount);

                    int switchBlockEnd = switchBlock.Start + switchBlock.TotalSize;

                    ArrayBuilder <BasicBlock> blockBuilder = ArrayBuilder <BasicBlock> .GetInstance();

                    switchBlock.GetBranchBlocks(blockBuilder);

                    foreach (BasicBlock branchBlock in blockBuilder)
                    {
                        writer.WriteInt32(branchBlock.Start - switchBlockEnd);
                    }

                    blockBuilder.Free();

                    break;

                default:
                    WriteOpCode(writer, block.BranchCode);

                    if (block.BranchLabel != null)
                    {
                        int target      = block.BranchBlock.Start;
                        int curBlockEnd = block.Start + block.TotalSize;
                        int offset      = target - curBlockEnd;

                        if (block.BranchCode.GetBranchOperandSize() == 1)
                        {
                            sbyte btOffset = (sbyte)offset;
                            Debug.Assert(btOffset == offset);
                            writer.WriteSByte(btOffset);
                        }
                        else
                        {
                            writer.WriteInt32(offset);
                        }
                    }

                    break;
                }
            }

            this.RealizedIL = writer.ToImmutableArray();
            writer.Free();

            RealizeSequencePoints();

            this.RealizedExceptionHandlers = _scopeManager.GetExceptionHandlerRegions();
        }