Exemple #1
0
        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);
        }
Exemple #3
0
        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);
             }
         }
     }
 }
Exemple #5
0
 public MethodILBuilder(Emit.Module moduleBeingBuilt)
 {
     this.ilBits           = new Microsoft.Cci.MemoryStream();
     this.writer           = new Microsoft.Cci.BinaryWriter(this.ilBits);
     this.moduleBeingBuilt = moduleBeingBuilt;
 }
Exemple #6
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 (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;
 }
Exemple #8
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 (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;
        }