public void Serialize(Microsoft.Cci.BinaryWriter to) { switch (this.Discriminator) { case ConstantValueTypeDiscriminator.Boolean: to.WriteBool(this.BooleanValue); break; case ConstantValueTypeDiscriminator.SByte: to.WriteSbyte(this.SByteValue); break; case ConstantValueTypeDiscriminator.Byte: to.WriteByte(this.ByteValue); break; case ConstantValueTypeDiscriminator.Char: case ConstantValueTypeDiscriminator.Int16: to.WriteShort(this.Int16Value); break; case ConstantValueTypeDiscriminator.UInt16: to.WriteUshort(this.UInt16Value); break; case ConstantValueTypeDiscriminator.Single: to.WriteFloat(this.SingleValue); break; case ConstantValueTypeDiscriminator.Int32: to.WriteInt(this.Int32Value); break; case ConstantValueTypeDiscriminator.UInt32: to.WriteUint(this.UInt32Value); break; case ConstantValueTypeDiscriminator.Double: to.WriteDouble(this.DoubleValue); break; case ConstantValueTypeDiscriminator.Int64: to.WriteLong(this.Int64Value); break; case ConstantValueTypeDiscriminator.UInt64: to.WriteUlong(this.UInt64Value); break; default: throw ExceptionUtilities.UnexpectedValue(this.Discriminator); } }
/// <summary> /// Produces a serialized blob of all constant initializers. /// Nonconstat initializers are matched with a zero of corresponding size. /// </summary> private byte[] GetRawData(ImmutableArray <BoundExpression> inits) { // the initial size is a guess. // there is no point to be precise here as MemoryStream always has N + 1 storage // and will need to be trimmed regardless var ms = new Microsoft.Cci.MemoryStream((uint)(inits.Length * 4)); var bw = new Microsoft.Cci.BinaryWriter(ms); SerializeArrayRecursive(bw, inits); byte[] data = ms.Buffer; // trim Array.Resize(ref data, (int)ms.Position); return(data); }
private static void WriteOpCode(Microsoft.Cci.BinaryWriter writer, ILOpCode code) { var size = code.Size(); if (size == 1) { writer.WriteByte((byte)code); } else { // IL opcodes that occupy two bytes are written to // the byte stream with the high-order byte first, // in contrast to the little-endian format of the // numeric arguments and tokens. Debug.Assert(size == 2); writer.WriteByte((byte)((ushort)code >> 8)); writer.WriteByte((byte)((ushort)code & 0xff)); } }
private void SerializeArrayRecursive(Microsoft.Cci.BinaryWriter bw, ImmutableArray <BoundExpression> inits) { if (inits.Length != 0) { if (inits[0].Kind == BoundKind.ArrayInitialization) { foreach (var init in inits) { SerializeArrayRecursive(bw, ((BoundArrayInitialization)init).Initializers); } } else { foreach (var init in inits) { AsConstOrDefault(init).Serialize(bw); } } } }
public MethodILBuilder(Emit.Module moduleBeingBuilt) { this.ilBits = new Microsoft.Cci.MemoryStream(); this.writer = new Microsoft.Cci.BinaryWriter(this.ilBits); this.moduleBeingBuilt = moduleBeingBuilt; }
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 (isOptimizing && 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 = Microsoft.Cci.MemoryStream.GetInstance(); var writer = new Microsoft.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 = this.allocatedILMarkers[i].BlockOffset; int absoluteOffset = (int)realizedIlBitStream.Position + blockOffset; this.allocatedILMarkers[i] = new ILMarker() { BlockOffset = blockOffset, AbsoluteOffset = absoluteOffset }; } } var bits = block.RegularInstructions; if (bits != null) { bits.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(); }
public ILBuilder(Emit.Module moduleBeingBuilt) { this.ilBits = new Microsoft.Cci.MemoryStream(); this.writer = new Microsoft.Cci.BinaryWriter(this.ilBits); this.moduleBeingBuilt = moduleBeingBuilt; }
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 (isOptimizing && 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 = Microsoft.Cci.MemoryStream.GetInstance(); var writer = new Microsoft.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 = this.allocatedILMarkers[i].BlockOffset; int absoluteOffset = (int)realizedIlBitStream.Position + blockOffset; this.allocatedILMarkers[i] = new ILMarker() { BlockOffset = blockOffset, AbsoluteOffset = absoluteOffset }; } } var bits = block.RegularInstructions; if (bits != null) { bits.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(); }
/// <summary> /// Produces a serialized blob of all constant initializers. /// Nonconstat initializers are matched with a zero of corresponding size. /// </summary> private byte[] GetRawData(ImmutableArray<BoundExpression> inits) { // the initial size is a guess. // there is no point to be precise here as MemoryStream always has N + 1 storage // and will need to be trimmed regardless var ms = new Microsoft.Cci.MemoryStream((uint)(inits.Length * 4)); var bw = new Microsoft.Cci.BinaryWriter(ms); SerializeArrayRecursive(bw, inits); byte[] data = ms.Buffer; // trim Array.Resize(ref data, (int)ms.Position); return data; }