Exemplo n.º 1
0
        private int OperandToBranchDelta(CilInstruction instruction)
        {
            bool isShort = instruction.OpCode.OperandType == CilOperandType.ShortInlineBrTarget;

            int delta;

            switch (instruction.Operand)
            {
            case sbyte x:
                delta = x;
                break;

            case int x:
                delta = x;
                break;

            case ICilLabel label:
                int operandSize = isShort ? sizeof(sbyte) : sizeof(int);
                delta = label.Offset - (int)(_writer.Offset + (ulong)operandSize);
                break;

            default:
                return(ThrowInvalidOperandType <sbyte>(instruction, typeof(ICilLabel), typeof(sbyte)));
            }

            if (isShort && (delta < sbyte.MinValue || delta > sbyte.MaxValue))
            {
                _errorListener.RegisterException(new OverflowException(
                                                     $"{_diagnosticPrefix}Branch target at IL_{instruction.Offset:X4} is too far away for a ShortInlineBr instruction."));
            }

            return(delta);
        }
Exemplo n.º 2
0
        private T ThrowInvalidOperandType <T>(CilInstruction instruction, Type expectedOperand)
        {
            string found = instruction.Operand?.GetType().Name ?? "null";

            _errorListener.RegisterException(new ArgumentOutOfRangeException(
                                                 $"{_diagnosticPrefix}Expected a {expectedOperand.Name} operand at IL_{instruction.Offset:X4}, but found {found}."));
            return(default);
Exemplo n.º 3
0
 private double OperandToFloat64(CilInstruction instruction)
 {
     if (instruction.Operand is double x)
     {
         return(x);
     }
     return(ThrowInvalidOperandType <double>(instruction, typeof(double)));
 }
Exemplo n.º 4
0
 private float OperandToFloat32(CilInstruction instruction)
 {
     if (instruction.Operand is float x)
     {
         return(x);
     }
     return(ThrowInvalidOperandType <float>(instruction, typeof(float)));
 }
Exemplo n.º 5
0
 private long OperandToInt64(CilInstruction instruction)
 {
     if (instruction.Operand is long x)
     {
         return(x);
     }
     return(ThrowInvalidOperandType <long>(instruction, typeof(long)));
 }
Exemplo n.º 6
0
 private int OperandToInt32(CilInstruction instruction)
 {
     if (instruction.Operand is int x)
     {
         return(x);
     }
     return(ThrowInvalidOperandType <int>(instruction, typeof(int)));
 }
Exemplo n.º 7
0
 private sbyte OperandToSByte(CilInstruction instruction)
 {
     if (instruction.Operand is sbyte x)
     {
         return(x);
     }
     return(ThrowInvalidOperandType <sbyte>(instruction, typeof(sbyte)));
 }
Exemplo n.º 8
0
        private ushort OperandToArgumentIndex(CilInstruction instruction)
        {
            int variableIndex = _operandBuilder.GetArgumentIndex(instruction.Operand);

            if (instruction.OpCode.OperandType == CilOperandType.ShortInlineArgument && variableIndex > byte.MaxValue)
            {
                _errorListener.RegisterException(new OverflowException(
                                                     $"{_diagnosticPrefix}Argument index at IL_{instruction.Offset:X4} is too large for a ShortInlineArgument instruction."));
            }

            return(unchecked ((ushort)variableIndex));
        }
Exemplo n.º 9
0
        private ushort OperandToArgumentIndex(CilInstruction instruction)
        {
            int variableIndex = _operandBuilder.GetArgumentIndex(instruction.Operand);

            if (instruction.OpCode.OperandType == CilOperandType.ShortInlineArgument && variableIndex > byte.MaxValue)
            {
                throw new OverflowException(
                          $"Argument index at offset IL_{instruction.Offset:X4} is too large for a ShortInlineArgument instruction.");
            }

            return(unchecked ((ushort)variableIndex));
        }
Exemplo n.º 10
0
        /// <summary>
        /// Reads the next instruction from the input stream.
        /// </summary>
        /// <returns>The instruction.</returns>
        public CilInstruction ReadInstruction()
        {
            ulong start = Reader.Offset;

            var code    = ReadOpCode();
            var operand = ReadOperand(code.OperandType);
            var result  = new CilInstruction(_currentOffset, code, operand);

            _currentOffset += (int)(Reader.Offset - start);

            return(result);
        }
Exemplo n.º 11
0
        private static T ThrowInvalidOperandType <T>(CilInstruction instruction, params Type[] expectedOperands)
        {
            var names = expectedOperands
                        .Select(o => o.Name)
                        .ToArray();

            string operandTypesString = expectedOperands.Length > 1
                ? $"{string.Join(", ", names.Take(names.Length - 1))} or {names[names.Length - 1]}"
                : names[0];

            string found = instruction.Operand?.GetType().Name ?? "null";

            throw new ArgumentOutOfRangeException(
                      $"Expected a {operandTypesString} operand at offset IL_{instruction.Offset:X4}, but found {found}.");
        }
Exemplo n.º 12
0
        private void WriteOperand(CilInstruction instruction)
        {
            switch (instruction.OpCode.OperandType)
            {
            case CilOperandType.InlineNone:
                break;

            case CilOperandType.ShortInlineI:
                _writer.WriteSByte(OperandToSByte(instruction));
                break;

            case CilOperandType.InlineI:
                _writer.WriteInt32(OperandToInt32(instruction));
                break;

            case CilOperandType.InlineI8:
                _writer.WriteInt64(OperandToInt64(instruction));
                break;

            case CilOperandType.ShortInlineR:
                _writer.WriteSingle(OperandToFloat32(instruction));
                break;

            case CilOperandType.InlineR:
                _writer.WriteDouble(OperandToFloat64(instruction));
                break;

            case CilOperandType.ShortInlineVar:
                _writer.WriteByte((byte)OperandToLocalIndex(instruction));
                break;

            case CilOperandType.InlineVar:
                _writer.WriteUInt16(OperandToLocalIndex(instruction));
                break;

            case CilOperandType.ShortInlineArgument:
                _writer.WriteByte((byte)OperandToArgumentIndex(instruction));
                break;

            case CilOperandType.InlineArgument:
                _writer.WriteUInt16(OperandToArgumentIndex(instruction));
                break;

            case CilOperandType.ShortInlineBrTarget:
                _writer.WriteSByte((sbyte)OperandToBranchDelta(instruction));
                break;

            case CilOperandType.InlineBrTarget:
                _writer.WriteInt32(OperandToBranchDelta(instruction));
                break;

            case CilOperandType.InlineSwitch:
                var labels = (IList <ICilLabel>)instruction.Operand;
                _writer.WriteInt32(labels.Count);

                int baseOffset = (int)_writer.Offset + labels.Count * sizeof(int);
                for (int i = 0; i < labels.Count; i++)
                {
                    _writer.WriteInt32(labels[i].Offset - baseOffset);
                }

                break;

            case CilOperandType.InlineString:
                _writer.WriteUInt32(_operandBuilder.GetStringToken(instruction.Operand));
                break;

            case CilOperandType.InlineField:
            case CilOperandType.InlineMethod:
            case CilOperandType.InlineSig:
            case CilOperandType.InlineTok:
            case CilOperandType.InlineType:
                _writer.WriteUInt32(_operandBuilder.GetMemberToken(instruction.Operand).ToUInt32());
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Exemplo n.º 13
0
 /// <summary>
 /// Writes a single instruction to the output stream.
 /// </summary>
 /// <param name="instruction">The instruction to write.</param>
 public void WriteInstruction(CilInstruction instruction)
 {
     WriteOpCode(instruction.OpCode);
     WriteOperand(instruction);
 }
Exemplo n.º 14
0
 /// <summary>
 /// Creates a new instruction label.
 /// </summary>
 /// <param name="instruction">The instruction to reference.</param>
 public CilInstructionLabel(CilInstruction instruction)
 {
     Instruction = instruction ?? throw new ArgumentNullException(nameof(instruction));
 }
Exemplo n.º 15
0
        private void WriteOperand(CilInstruction instruction)
        {
            switch (instruction.OpCode.OperandType)
            {
            case CilOperandType.InlineNone:
                break;

            case CilOperandType.ShortInlineI:
                _writer.WriteSByte((sbyte)instruction.Operand);
                break;

            case CilOperandType.InlineI:
                _writer.WriteInt32((int)instruction.Operand);
                break;

            case CilOperandType.InlineI8:
                _writer.WriteInt64((long)instruction.Operand);
                break;

            case CilOperandType.ShortInlineR:
                _writer.WriteSingle((float)instruction.Operand);
                break;

            case CilOperandType.InlineR:
                _writer.WriteDouble((double)instruction.Operand);
                break;

            case CilOperandType.ShortInlineVar:
                _writer.WriteSByte((sbyte)_operandBuilder.GetVariableIndex(instruction.Operand));
                break;

            case CilOperandType.InlineVar:
                _writer.WriteUInt16((ushort)_operandBuilder.GetVariableIndex(instruction.Operand));
                break;

            case CilOperandType.ShortInlineArgument:
                _writer.WriteSByte((sbyte)_operandBuilder.GetArgumentIndex(instruction.Operand));
                break;

            case CilOperandType.InlineArgument:
                _writer.WriteUInt16((ushort)_operandBuilder.GetArgumentIndex(instruction.Operand));
                break;

            case CilOperandType.ShortInlineBrTarget:
                sbyte shortOffset = (sbyte)(((ICilLabel)instruction.Operand).Offset - (int)(_writer.Offset + sizeof(sbyte)));
                _writer.WriteSByte(shortOffset);
                break;

            case CilOperandType.InlineBrTarget:
                int longOffset = ((ICilLabel)instruction.Operand).Offset - (int)(_writer.Offset + sizeof(int));
                _writer.WriteInt32(longOffset);
                break;

            case CilOperandType.InlineSwitch:
                var labels = (IList <ICilLabel>)instruction.Operand;
                _writer.WriteInt32(labels.Count);

                int baseOffset = (int)_writer.Offset + labels.Count * sizeof(int);
                for (int i = 0; i < labels.Count; i++)
                {
                    _writer.WriteInt32(labels[i].Offset - baseOffset);
                }

                break;

            case CilOperandType.InlineString:
                _writer.WriteUInt32(_operandBuilder.GetStringToken(instruction.Operand));
                break;

            case CilOperandType.InlineField:
            case CilOperandType.InlineMethod:
            case CilOperandType.InlineSig:
            case CilOperandType.InlineTok:
            case CilOperandType.InlineType:
                _writer.WriteUInt32(_operandBuilder.GetMemberToken(instruction.Operand).ToUInt32());
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }