Exemplo n.º 1
0
        private void TryOptimizeArgument(CilInstruction instruction)
        {
            var parameter = instruction.Operand as ParameterSignature;

            if (Method == null || Method.Signature == null || parameter == null)
            {
                return;
            }
            int index = Method.Signature.Parameters.IndexOf(parameter);

            if (index < 0 || index > byte.MaxValue)
            {
                return;
            }

            switch (instruction.OpCode.Code)
            {
            case CilCode.Ldarg:
                if (index <= 3)
                {
                    instruction.OpCode  = CilOpCodes.SingleByteOpCodes[CilOpCodes.Ldarg_0.Op2 + index];
                    instruction.Operand = null;
                }
                else
                {
                    instruction.OpCode = CilOpCodes.Ldarg_S;
                }
                break;

            case CilCode.Ldarga:
                instruction.OpCode = CilOpCodes.Ldarga_S;
                break;
            }
        }
Exemplo n.º 2
0
 public static CilInstruction Create(CilOpCode code, CilInstruction instruction)
 {
     if (code.OperandType != CilOperandType.ShortInlineBrTarget && code.OperandType != CilOperandType.InlineBrTarget)
     {
         throw new ArgumentException("Opcode does not accept an instruction operand.", "code");
     }
     return(new CilInstruction(0, code, instruction));
 }
Exemplo n.º 3
0
        public string FormatInstruction(CilInstruction instruction)
        {
            string minimal = FormatLabel(instruction.Offset) + ": " + FormatOpCode(instruction.OpCode);

            return(instruction.Operand == null
                ? minimal
                : minimal + " " + FormatOperand(instruction.OpCode.OperandType, instruction.Operand));
        }
Exemplo n.º 4
0
        private void TryOptimizeLdc(CilInstruction instruction)
        {
            int value = (int)instruction.Operand;

            if (value >= -1 && value <= 8)
            {
                instruction.OpCode  = CilOpCodes.SingleByteOpCodes[CilOpCodes.Ldc_I4_0.Op2 + value];
                instruction.Operand = null;
            }
            else if (value >= sbyte.MinValue && value <= sbyte.MaxValue)
            {
                instruction.OpCode  = CilOpCodes.Ldc_I4_S;
                instruction.Operand = Convert.ToSByte(value);
            }
        }
Exemplo n.º 5
0
        private void TryOptimizeVariable(CilInstruction instruction)
        {
            var variable    = instruction.Operand as VariableSignature;
            var localVarSig = Signature != null ? Signature.Signature as LocalVariableSignature : null;

            if (localVarSig == null || variable == null)
            {
                return;
            }
            int index = localVarSig.Variables.IndexOf(variable);

            if (index < 0 || index > byte.MaxValue)
            {
                return;
            }

            switch (instruction.OpCode.Code)
            {
            case CilCode.Ldloc:
                if (index <= 3)
                {
                    instruction.OpCode  = CilOpCodes.SingleByteOpCodes[CilOpCodes.Ldloc_0.Op2 + index];
                    instruction.Operand = null;
                }
                else
                {
                    instruction.OpCode = CilOpCodes.Ldloc_S;
                }
                break;

            case CilCode.Ldloca:
                instruction.OpCode = CilOpCodes.Ldloca_S;
                break;

            case CilCode.Stloc:
                if (index <= 3)
                {
                    instruction.OpCode  = CilOpCodes.SingleByteOpCodes[CilOpCodes.Stloc_0.Op2 + index];
                    instruction.Operand = null;
                }
                else
                {
                    instruction.OpCode = CilOpCodes.Stloc_S;
                }
                break;
            }
        }
Exemplo n.º 6
0
        private void OptimizeMacro(CilInstruction instruction)
        {
            switch (instruction.OpCode.OperandType)
            {
            case CilOperandType.InlineBrTarget:
                TryOptimizeBranch(instruction);
                break;

            case CilOperandType.InlineVar:
                TryOptimizeVariable(instruction);
                break;

            case CilOperandType.InlineArgument:
                TryOptimizeArgument(instruction);
                break;
            }

            if (instruction.OpCode.Code == CilCode.Ldc_I4)
            {
                TryOptimizeLdc(instruction);
            }
        }
Exemplo n.º 7
0
        private void TryOptimizeBranch(CilInstruction instruction)
        {
            CilInstruction operand         = instruction.Operand as CilInstruction;
            int            relativeOperand = operand.Offset - (instruction.Offset + 2);

            if (operand == null || relativeOperand < sbyte.MinValue || relativeOperand > sbyte.MaxValue)
            {
                return;
            }
            switch (instruction.OpCode.Code)
            {
            case CilCode.Br:
                instruction.OpCode = CilOpCodes.Br_S;
                break;

            case CilCode.Leave:
                instruction.OpCode = CilOpCodes.Leave_S;
                break;

            case CilCode.Brfalse:
                instruction.OpCode = CilOpCodes.Brfalse_S;
                break;

            case CilCode.Brtrue:
                instruction.OpCode = CilOpCodes.Brtrue_S;
                break;

            case CilCode.Beq:
                instruction.OpCode = CilOpCodes.Beq_S;
                break;

            case CilCode.Bge:
                instruction.OpCode = CilOpCodes.Bge_S;
                break;

            case CilCode.Bge_Un:
                instruction.OpCode = CilOpCodes.Bge_Un_S;
                break;

            case CilCode.Bgt:
                instruction.OpCode = CilOpCodes.Bgt_S;
                break;

            case CilCode.Bgt_Un:
                instruction.OpCode = CilOpCodes.Bgt_Un_S;
                break;

            case CilCode.Ble:
                instruction.OpCode = CilOpCodes.Ble_S;
                break;

            case CilCode.Ble_Un:
                instruction.OpCode = CilOpCodes.Ble_Un_S;
                break;

            case CilCode.Blt:
                instruction.OpCode = CilOpCodes.Blt_S;
                break;

            case CilCode.Blt_Un:
                instruction.OpCode = CilOpCodes.Blt_Un_S;
                break;

            case CilCode.Bne_Un:
                instruction.OpCode = CilOpCodes.Bne_Un_S;
                break;
            }
        }
Exemplo n.º 8
0
        private void ExpandMacro(CilInstruction instruction)
        {
            switch (instruction.OpCode.Code)
            {
            case CilCode.Br_S:
                instruction.OpCode = CilOpCodes.Br;
                break;

            case CilCode.Leave_S:
                instruction.OpCode = CilOpCodes.Leave;
                break;

            case CilCode.Brfalse_S:
                instruction.OpCode = CilOpCodes.Brfalse;
                break;

            case CilCode.Brtrue_S:
                instruction.OpCode = CilOpCodes.Brtrue;
                break;

            case CilCode.Beq_S:
                instruction.OpCode = CilOpCodes.Beq;
                break;

            case CilCode.Bge_S:
                instruction.OpCode = CilOpCodes.Bge;
                break;

            case CilCode.Bge_Un_S:
                instruction.OpCode = CilOpCodes.Bge_Un;
                break;

            case CilCode.Bgt_S:
                instruction.OpCode = CilOpCodes.Bgt;
                break;

            case CilCode.Bgt_Un_S:
                instruction.OpCode = CilOpCodes.Bgt_Un;
                break;

            case CilCode.Ble_S:
                instruction.OpCode = CilOpCodes.Ble;
                break;

            case CilCode.Ble_Un_S:
                instruction.OpCode = CilOpCodes.Ble_Un;
                break;

            case CilCode.Blt_S:
                instruction.OpCode = CilOpCodes.Blt;
                break;

            case CilCode.Blt_Un_S:
                instruction.OpCode = CilOpCodes.Blt_Un;
                break;

            case CilCode.Bne_Un_S:
                instruction.OpCode = CilOpCodes.Bne_Un;
                break;

            case CilCode.Ldloc_S:
                instruction.OpCode = CilOpCodes.Ldloc;
                break;

            case CilCode.Ldloca_S:
                instruction.OpCode = CilOpCodes.Ldloca;
                break;

            case CilCode.Ldloc_0:
            case CilCode.Ldloc_1:
            case CilCode.Ldloc_2:
            case CilCode.Ldloc_3:
                instruction.Operand = ((IOperandResolver)this).ResolveVariable(instruction.OpCode.Name[instruction.OpCode.Name.Length - 1] - 48);
                instruction.OpCode  = CilOpCodes.Ldloc;
                break;

            case CilCode.Stloc_S:
                instruction.OpCode = CilOpCodes.Stloc;
                break;

            case CilCode.Stloc_0:
            case CilCode.Stloc_1:
            case CilCode.Stloc_2:
            case CilCode.Stloc_3:
                instruction.Operand = ((IOperandResolver)this).ResolveVariable(instruction.OpCode.Name[instruction.OpCode.Name.Length - 1] - 48);
                instruction.OpCode  = CilOpCodes.Stloc;
                break;

            case CilCode.Ldarg_S:
                instruction.OpCode = CilOpCodes.Ldarg;
                break;

            case CilCode.Ldarga_S:
                instruction.OpCode = CilOpCodes.Ldarga;
                break;

            case CilCode.Ldarg_0:
            case CilCode.Ldarg_1:
            case CilCode.Ldarg_2:
            case CilCode.Ldarg_3:
                instruction.Operand = ((IOperandResolver)this).ResolveParameter(instruction.OpCode.Name[instruction.OpCode.Name.Length - 1] - 48);
                instruction.OpCode  = CilOpCodes.Ldarg;
                break;

            case CilCode.Starg_S:
                instruction.OpCode = CilOpCodes.Starg;
                break;

            case CilCode.Ldc_I4_0:
            case CilCode.Ldc_I4_1:
            case CilCode.Ldc_I4_2:
            case CilCode.Ldc_I4_3:
            case CilCode.Ldc_I4_4:
            case CilCode.Ldc_I4_5:
            case CilCode.Ldc_I4_6:
            case CilCode.Ldc_I4_7:
            case CilCode.Ldc_I4_8:
                instruction.Operand = instruction.OpCode.Name[instruction.OpCode.Name.Length - 1] - 48;
                instruction.OpCode  = CilOpCodes.Ldc_I4;
                break;

            case CilCode.Ldc_I4_S:
                instruction.OpCode = CilOpCodes.Ldc_I4;
                break;

            case CilCode.Ldc_I4_M1:
                instruction.OpCode  = CilOpCodes.Ldc_I4;
                instruction.Operand = -1;
                break;
            }
        }
Exemplo n.º 9
0
        private void ResolveOperand(IList <CilInstruction> instructions, CilInstruction current)
        {
            var nextOffset = current.Offset + current.Size;

            switch (current.OpCode.OperandType)
            {
            case CilOperandType.InlineArgument:
            case CilOperandType.ShortInlineArgument:
                var parameter = _resolver.ResolveParameter(Convert.ToInt32(current.Operand));
                if (parameter != null)
                {
                    current.Operand = parameter;
                }
                break;

            case CilOperandType.InlineVar:
            case CilOperandType.ShortInlineVar:
                var variable = _resolver.ResolveVariable(Convert.ToInt32(current.Operand));
                if (variable != null)
                {
                    current.Operand = variable;
                }
                break;

            case CilOperandType.ShortInlineBrTarget:
            case CilOperandType.InlineBrTarget:
                var targetInstruction = instructions.FirstOrDefault(
                    x => x.Offset == nextOffset + Convert.ToInt32(current.Operand));
                if (targetInstruction != null)
                {
                    current.Operand = targetInstruction;
                }
                break;

            case CilOperandType.InlineField:
            case CilOperandType.InlineMethod:
            case CilOperandType.InlineSig:
            case CilOperandType.InlineTok:
            case CilOperandType.InlineType:
                var member = _resolver.ResolveMember((MetadataToken)current.Operand);
                if (member != null)
                {
                    current.Operand = member;
                }
                break;

            case CilOperandType.InlineString:
                var stringValue = _resolver.ResolveString(((MetadataToken)current.Operand).ToUInt32());
                if (stringValue != null)
                {
                    current.Operand = stringValue;
                }
                break;

            case CilOperandType.InlineSwitch:
                var targetOffsets = (IList <int>)current.Operand;
                var targets       = new List <CilInstruction>(targetOffsets.Count);
                for (int i = 0; i < targetOffsets.Count; i++)
                {
                    targets.Add(instructions.FirstOrDefault(
                                    x => x.Offset == nextOffset + targetOffsets[i]));
                }
                current.Operand = targets;
                break;
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Writes the operand of the instruction to the output stream.
        /// </summary>
        /// <param name="instruction"></param>
        /// <exception cref="InvalidOperationException"></exception>
        private void WriteOperand(CilInstruction instruction)
        {
            switch (instruction.OpCode.OperandType)
            {
            case CilOperandType.InlineArgument:
                _writer.WriteUInt16((ushort)_builder.GetParameterIndex(instruction.Operand as ParameterSignature));
                break;

            case CilOperandType.ShortInlineArgument:
                _writer.WriteByte((byte)_builder.GetParameterIndex(instruction.Operand as ParameterSignature));
                break;

            case CilOperandType.InlineVar:
                _writer.WriteUInt16((ushort)_builder.GetVariableIndex(instruction.Operand as VariableSignature));
                break;

            case CilOperandType.ShortInlineVar:
                _writer.WriteByte((byte)_builder.GetVariableIndex(instruction.Operand as VariableSignature));
                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.InlineBrTarget:
                _writer.WriteInt32(((CilInstruction)instruction.Operand).Offset -
                                   (instruction.Offset + instruction.Size));
                break;

            case CilOperandType.ShortInlineBrTarget:
                _writer.WriteSByte((sbyte)(((CilInstruction)instruction.Operand).Offset -
                                           (instruction.Offset + instruction.Size)));
                break;

            case CilOperandType.InlineField:
            case CilOperandType.InlineMethod:
            case CilOperandType.InlineSig:
            case CilOperandType.InlineTok:
            case CilOperandType.InlineType:
                var token = _builder.GetMetadataToken((IMetadataMember)instruction.Operand);
                if (token.Rid == 0)
                {
                    throw new InvalidOperationException($"Member {instruction.Operand} has an invalid metadata token.");
                }

                _writer.WriteUInt32(token.ToUInt32());
                break;

            case CilOperandType.InlineString:
                _writer.WriteUInt32(_builder.GetStringOffset((string)instruction.Operand));
                break;

            case CilOperandType.InlineSwitch:
                var targets = (IList <CilInstruction>)instruction.Operand;
                _writer.WriteInt32(targets.Count);
                foreach (var target in targets)
                {
                    _writer.WriteInt32(target.Offset - (instruction.Offset + instruction.Size));
                }
                break;

            case CilOperandType.InlineNone:
                break;
            }
        }
Exemplo n.º 11
0
 /// <summary>
 /// Writes a single instruction to the output stream.
 /// </summary>
 /// <param name="instruction">The instruction to write.</param>
 public void Write(CilInstruction instruction)
 {
     WriteOpCode(instruction.OpCode);
     WriteOperand(instruction);
 }
Exemplo n.º 12
0
 private bool Equals(CilInstruction other)
 {
     return(Offset == other.Offset && OpCode.Equals(other.OpCode) && Equals(Operand, other.Operand));
 }