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