public void WriteData(Cci.BinaryWriter resourceWriter) { if (fileReference == null) { try { using (Stream stream = streamProvider()) { if (stream == null) { throw new InvalidOperationException(CodeAnalysisResources.ResourceStreamProviderShouldReturnNonNullStream); } var count = (int)(stream.Length - stream.Position); resourceWriter.WriteInt(count); var to = resourceWriter.BaseStream; var position = (int)to.Position; to.Position = (uint)(position + count); resourceWriter.Align(8); var buffer = to.Buffer; stream.Read(buffer, position, count); } } catch (Exception e) { throw new ResourceException(this.name, e); } } }
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. var realizedIlBitStream = Cci.MemoryStream.GetInstance(); var writer = new Cci.BinaryWriter(realizedIlBitStream); for (var 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 = (int)realizedIlBitStream.Position + blockOffset; _allocatedILMarkers[i] = new ILMarker() { BlockOffset = blockOffset, AbsoluteOffset = absoluteOffset }; } } block.RegularInstructions?.WriteTo(realizedIlBitStream); 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); var switchBlock = (SwitchBlock)block; writer.WriteUint(switchBlock.BranchesCount); int switchBlockEnd = switchBlock.Start + switchBlock.TotalSize; var blockBuilder = ArrayBuilder<BasicBlock>.GetInstance(); switchBlock.GetBranchBlocks(blockBuilder); foreach (var branchBlock in blockBuilder) { writer.WriteInt(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.BranchOperandSize() == 1) { sbyte btOffset = (sbyte)offset; Debug.Assert(btOffset == offset); writer.WriteSbyte(btOffset); } else { writer.WriteInt(offset); } } break; } } this.RealizedIL = realizedIlBitStream.ToArray(); realizedIlBitStream.Free(); RealizeSequencePoints(); this.RealizedExceptionHandlers = _scopeManager.GetExceptionHandlerRegions(); }
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 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. var realizedIlBitStream = Cci.MemoryStream.GetInstance(); var writer = new Cci.BinaryWriter(realizedIlBitStream); for (var 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 = (int)realizedIlBitStream.Position + blockOffset; _allocatedILMarkers[i] = new ILMarker() { BlockOffset = blockOffset, AbsoluteOffset = absoluteOffset }; } } block.RegularInstructions?.WriteTo(realizedIlBitStream); 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); var switchBlock = (SwitchBlock)block; writer.WriteUint(switchBlock.BranchesCount); int switchBlockEnd = switchBlock.Start + switchBlock.TotalSize; var blockBuilder = ArrayBuilder <BasicBlock> .GetInstance(); switchBlock.GetBranchBlocks(blockBuilder); foreach (var branchBlock in blockBuilder) { writer.WriteInt(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.BranchOperandSize() == 1) { sbyte btOffset = (sbyte)offset; Debug.Assert(btOffset == offset); writer.WriteSbyte(btOffset); } else { writer.WriteInt(offset); } } break; } } this.RealizedIL = realizedIlBitStream.ToArray(); realizedIlBitStream.Free(); RealizeSequencePoints(); this.RealizedExceptionHandlers = _scopeManager.GetExceptionHandlerRegions(); }